From 2cffbe6121d9650144ac906d7632978a6e360a52 Mon Sep 17 00:00:00 2001 From: Adan Date: Wed, 12 Aug 2026 19:03:20 +0000 Subject: [PATCH] Make the README agent-native and ship a Claude Code skill Lead with the agent interface (one verb, JSON, stable exit codes) and add skills/greentree/SKILL.md, a drop-in Claude Code skill that teaches an agent to land changes with gate instead of raw git, how to react to each exit code, and not to re-run cached verdicts. Co-Authored-By: Claude Fable 5 --- README.md | 29 +++++++++++++--- skills/greentree/SKILL.md | 72 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+), 4 deletions(-) create mode 100644 skills/greentree/SKILL.md diff --git a/README.md b/README.md index dd0f4b8..b5bd014 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,7 @@ and refuses to create a commit from any tree that has not passed.

+Built for coding agents: one verb, JSON on every command, stable exit codes, and a drop-in skill.
An open source primitive from reachpad · Apache-2.0 · Linux and macOS

@@ -210,15 +211,35 @@ freely with a running watcher. ### For coding agents -The agent-facing contract is one verb and one exit-code table: +An agent is the primary user. The whole interface an agent needs is one +verb and one exit-code table: ```sh -greentree gate --json -m "" +greentree gate --json -m "" # verify, then commit the tree; idempotent ``` -[docs/AGENTS.md](docs/AGENTS.md) has the copy-paste project-instructions +Every command takes `--json` (exactly one object on stdout) and returns a +stable exit code, so an agent branches on the code, never on parsed text: +`0` committed, `10` a check failed (output at `.log_tail`), `11` not +verified yet (run `test` first), `12` unsnapshotable, `13` locked. No +prose to interpret, no re-running "to be sure" — a cache hit proves the +content already passed. + +**Drop-in skill.** [`skills/greentree/`](skills/greentree/SKILL.md) is a +Claude Code skill that teaches an agent the workflow and the exit codes. +Copy it into a project so the agent loads it automatically: + +```sh +cp -r skills/greentree .claude/skills/ +``` + +The skill tells the agent to land changes with `greentree gate` instead of +raw `git commit`/`git push`, how to react to each exit code, and not to +re-run cached verdicts. + +**Enforce it.** [docs/AGENTS.md](docs/AGENTS.md) has a project-instructions snippet and a Claude Code hook that blocks `git commit`/`git push` so the -gate is the only door. +gate is the only door, even if the agent forgets. ### The gate before GitHub diff --git a/skills/greentree/SKILL.md b/skills/greentree/SKILL.md new file mode 100644 index 0000000..d6315db --- /dev/null +++ b/skills/greentree/SKILL.md @@ -0,0 +1,72 @@ +--- +name: greentree +description: Land code changes through greentree instead of raw git. Use in any repo that has a greentree.yaml or the greentree binary on PATH, whenever about to commit, push, run tests, or land a change, or when asked "is it green" / "did it pass". greentree verifies the working tree, caches the result by content, and only lets a verified tree become a commit. +--- + +# greentree: verify the tree before it becomes a commit + +greentree runs this repo's checks against the current working tree, caches +the verdict by content (tree hash), and creates the commit from the exact +tree that passed. Use it instead of running tests by hand and then +`git commit`/`git push`. + +Applies when the repo has a `greentree.yaml`, or `greentree` is on PATH and +`greentree status` succeeds. + +## Landing a change: one command + +```sh +greentree gate --json -m "" +``` + +`gate` runs the required checks (instant when this exact content already +passed), then commits the verified tree. It is idempotent: running it twice +in a row is a no-op. This replaces `git add`/`git commit`/`git push`. + +Add `--push` to also push. Without it, `gate` commits locally only. + +## Branch on the exit code, never on the text + +| exit | meaning | do this | +|---|---|---| +| 0 | verified and committed | done | +| 10 | a check failed | read `.log_tail` in the JSON, fix the code, run `gate` again | +| 11 | tree not verified yet | run `greentree test --json`, then `gate` | +| 12 | repo mid-merge/rebase, or a dirty submodule | resolve it, then `gate` | +| 13 | another greentree run is in progress | wait a moment, then retry | +| 14 | config error | read `.error`; fix `greentree.yaml` | +| 15 | publish/push failed | read `.error` (e.g. remote rejected, no token) | + +## While iterating + +- `greentree test --json` runs the checks without committing. `.ok` is the + answer. Per-check detail is in `.results`. +- `greentree status --json` answers "would a commit succeed right now?" + without running anything new. Read `.publishable`. + +## Rules that keep it correct + +- Do not run `git commit` or `git push` directly in a greentree repo. The + commit must be built from the tested tree; `gate` does that. Bypassing it + produces an unverified commit. +- A cache hit is as authoritative as a fresh run. The tree hash proves the + content is identical, so do NOT re-run "to be sure" — that is wasted work. +- Do not edit files while `gate` or `test` is running. If the tree changes + mid-run the verdict is `cancelled` (it binds to no tree) and you will + just rerun it. Make your edits, then run the check. +- When a check fails (exit 10), the output is in the JSON: `.log` is the + full log file path, `.log_tail` is the last lines. Read it before + guessing at a fix. + +## Gate before GitHub + +The published commit is built from the exact verified tree, so it needs no +re-check. If the repo enforces a `greentree/` required status, a +plain `git push` can be made mergeable by attesting the pushed commit: + +```sh +git push +greentree attest --json # posts greentree/ on HEAD if verified +``` + +`gate --push` does the commit, push, and status in one step.