skills/gardener/SKILL.md
Operate the `first-tree gardener` CLI — an automated maintenance agent that responds to reviewer feedback on Context Tree sync PRs, posts structured verdict comments on source-repo PRs/issues, and (push mode) installs a GitHub Actions workflow that replaces the long-running gardener service with event-driven per-PR sync. Use whenever a task involves reviewing, responding to, or resolving feedback on tree sync PRs, gating source-repo PRs/issues against a Context Tree, or setting up automatic tree-issue creation from a codebase's CI.
npx skillsauth add agent-team-foundation/first-tree gardenerInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
This skill is the operational handbook for the gardener product. If you
have not yet loaded the first-tree entry-point skill, load that first —
it explains the toolkit layout and how the four skills relate. This skill
covers how to drive the first-tree gardener CLI.
The expected user onboarding shape is one short message naming a codebase repo and a tree repo, e.g.:
监听
https://github.com/<codebase-repo>这个 repo, tree 是https://github.com/<tree-repo>. update the latest first-tree CLI first, set up gardener + breeze for this scope, the rest of the check are after the onboarding
From that one line, branch on scenarios A–E below to pick the right
setup path, then run Scenario F to smoke-test the full pipeline end
to end. Do not pepper the user with config questions up front —
infer what you can, ask only when the inference is genuinely ambiguous.
Always finish by restarting the breeze daemon with the new
--allow-repo list so notifications flow.
Before picking a scenario, resolve the source repo's permission level so you don't guess push vs pull:
gh repo view <source-slug> --json viewerPermission -q .viewerPermission
ADMIN / MAINTAIN / WRITE → go to Scenario B (push mode,
lower latency, no daemon).READ / TRIAGE / NONE → go to Scenario C (pull mode, local
daemon). The user cannot land a workflow file in the source repo;
don't even suggest it.null/empty → stop and ask the user. null on a public repo
usually means gh isn't authenticated (the command "succeeds" but
the viewer is anonymous); treat it the same as the fail branch, not
as READ.If the tree repo doesn't exist yet, run Scenario A first, then come back to this step.
Gardener + breeze together form a routing pipeline. Scenarios A–E below each set up some subset of it; this overview is the target state every scenario points at so you can tell the user what they're getting:
source-repo activity (PR merges, new PRs)
│
▼
gardener sync ──► detects drift between source and tree
│
▼ (--open-issues mode, preferred for multi-owner trees)
one tree-repo issue per proposal, assigned to that node's owners
│
▼
GitHub notification fires for each assignee
│
▼
the assignee's breeze (on their own laptop) sees the notification
│
▼
breeze dispatches to the right agent (gardener draft-node)
│
▼
agent opens a tree PR ──► gardener-respond handles review feedback
Key shape — GitHub assignment is the routing table. If gardener
assigns @bingran-you, bingran's breeze picks it up. If it assigns
@serenakeyitan, her breeze does. No central queue, no shared server.
Each person runs their own breeze against their own notifications.
Two handshake points the onboarding must actually verify:
owners: frontmatter — without it, sync --open-issues
falls back to the tree-repo default owner and labels the issue
needs-owner. Fine for demos; not for steady-state routing.--allow-repo list — without it, the assignment notification fires
and dies in the void. This is the "connect the pipes" step: you are
not done with onboarding until breeze has surfaced at least one real
gardener notification.See Scenario F — try it end-to-end below for the smoke test, then Scenario G — review the draft-node PR for closing the loop.
Detected when the user hasn't given a tree slug, or the slug 404s.
first-tree tree init — scaffold a new tree in cwd.gh repo create ...), push, bind locally..claude/gardener-config.yaml with the codebase slug under
target_repos.Step 0 returned ADMIN / MAINTAIN / WRITE for the source repo.
CLAUDE_CODE_OAUTH_TOKEN locally via
claude setup-token. If they prefer the API-key path, confirm
ANTHROPIC_API_KEY is available instead.first-tree gardener install-workflow --tree-repo <tree> inside the
codebase repo.skills/first-tree/references/workflow-mode.md for
TREE_REPO_TOKEN + CLAUDE_CODE_OAUTH_TOKEN secret setup
(ANTHROPIC_API_KEY stays an optional fallback; audit-log caveats
must be surfaced before gh secret set).Step 0 returned READ / TRIAGE / NONE for the source repo, or the user explicitly said they can't push.
Pick a routing mode before running any command:
| Command | What it does | When to use |
|---|---|---|
| first-tree gardener sync --open-issues (operator-run) | Opens one issue per drift proposal on the tree repo, assigned to that node's owners. Breeze on the owner's laptop picks it up → dispatches to gardener draft-node → draft-node opens the fix PR. Today this is an operator-run step — run it manually (or on a cron) from the tree repo; it isn't wired into the gardener start daemon. | Default for multi-owner trees. This is the only mode that exercises the draft-node dispatch — it uses GitHub assignment as the distributed queue each owner's local breeze pulls from. Scenario F validates this path. |
| first-tree gardener start --sync-apply | Tells the pull-mode daemon's scheduled sync sweep to open one PR directly on the tree repo with all drift fixes batched together. No issue, no assignment step. | Solo trees, quick-sync demos, or when you want drift fixed automatically without the issue-first routing hop. Scenario F does not apply (no assignment step to observe). |
Once you've picked a routing mode:
export ANTHROPIC_API_KEY=... in the shell that will start the daemon
(launchd inherits env at bootstrap time, not at run time).first-tree gardener start --tree-path . --code-repo <source> --assign-owners (then run first-tree gardener sync --open-issues manually or on a cron)first-tree gardener start --tree-path . --code-repo <source> --assign-owners --sync-applyfirst-tree breeze start --allow-repo <tree-slug>,<source-slug>
The --allow-repo flag is required — breeze silently scans
nothing without it. If the daemon is already running with a different
allowlist, first-tree breeze start now fails loudly (#293); stop it
first (first-tree breeze stop) then re-start with the merged csv.first-tree gardener status + first-tree breeze status to confirm
both are live, then run Scenario F to watch the full chain
execute on a real (or synthetic) drift.No watch-subscription requirement for routing. Breeze uses
/notifications?participating=true(per #290), so the tree-repo issue's assignee receives the notification directly from the assignment — they don't need to Watch the tree repo. Watching a third-party source repo you aren't directly participating on is a no-op under this filter. Pull-mode gardener itself doesn't consume GitHub notifications;gardener syncpolls source activity viaghdirectly on its own schedule.
Detected when ~/.gardener/config.json already exists or target_repos
in the tree's gardener-config.yaml is non-empty.
target_repos in
.claude/gardener-config.yaml.install-workflow in the new codebase if the user
owns it; pull mode: gardener stop && gardener start with the added
--code-repo.User describes missing comments or stale notifications.
gardener status + tail the latest log under ~/.gardener/logs/.ANTHROPIC_API_KEY is in the launchd plist
(plutil -p ~/.gardener/launchd/com.first-tree.gardener.<user>.plist).gardener stop && gardener start ... with the same args. Restart
breeze with breeze start --allow-repo ... after.Runs after A/B/C/D so the user can watch one full cycle execute: drift detected → issue filed on tree → breeze notification → draft-node dispatch → fix PR opened → Scenario G review. Don't skip this on the first onboarding — it's the only way to verify routing actually works before the user walks away thinking it does.
The chain Scenario F proves is wired:
source drift → [gardener sync] → tree-repo issue → GitHub notification
→ [owner's breeze] → [gardener draft-node] → tree-repo PR → Scenario G
Every arrow is a place that can silently drop the message. Each step below names the checkpoint so you know exactly where the break is.
TREE_REPO_TOKEN set on the shell; at least one
NODE.md in the tree has owners: frontmatter naming a GitHub login;
breeze is installed on the laptop owned by that login; that breeze
has both the tree and source repos in its --allow-repo list. No
GitHub watch subscription is required — the assignee receives a
participating notification from the assignment itself.cd <tree-path>
first-tree gardener sync --open-issues --dry-run
Expect: would open issue on <tree-slug>: "[gardener] <title>"
with the right assignees listed. If it says [needs-owner], the
affected node's owners: frontmatter is empty — fix that first, or
the routing step (5) has nowhere to go.first-tree gardener sync --open-issues
Expect: ✒ opened issue on <tree-slug>: <url> (assignees: @<login>).
Open the URL in the browser and confirm the assignees match the
NODE.md frontmatter. Checkpoint: the issue exists on GitHub with
a <!-- gardener:sync-proposal ... --> marker in the body and a
### Proposed node content section.~/.breeze/inbox.json gets
a new entry for the issue and the Claude Code statusline announces
it. Checkpoint: first-tree breeze inbox lists the new issue.
If nothing appears: check first-tree breeze status, confirm the
--allow-repo list, confirm gh auth status user matches the
assignee.<!-- gardener:sync-proposal marker, and invokes
first-tree gardener draft-node --issue <n> --tree-repo <slug>
under the hood. draft-node copies the ### Proposed node content
into the tree at the right NODE.md path and opens a PR named
first-tree/draft-node-<proposal_id> against the tree repo.
Checkpoint: a new PR exists on the tree repo, linked from the
issue (Closes <tree-slug>#<n> on merge.), and breeze has labeled
the issue breeze:done. See Scenario G for what that PR looks like
and how to review it.If any step fails, the pipeline isn't connected — fix that step before
telling the user onboarding is done. The most common breaks are (a)
breeze isn't running with the tree repo in --allow-repo, (b) the
NODE.md has no owners:, or (c) the assignee's gh auth status login
doesn't match the login in owners:.
After Scenario F lands, a tree PR branch named
first-tree/draft-node-<proposal_id> appears on the tree repo. This is
where the human reviews the machine-drafted NODE.md before it merges.
[gardener] draft <node>
title or a first-tree/draft-node-<proposal_id> head branch.Closes <tree-slug>#<n> on merge.) and shows the source SHA or
source PR. The NODE.md content was copied verbatim from the issue
body; draft-node does not synthesize or summarize.gh pr merge --squash. The tree issue
closes automatically via the Closes directive.If draft-node skips because the issue body has no ### Proposed node content section (common on merged-PR variants), hand-edit the tree
from the issue's summary links instead.
After any scenario, restart breeze with the full --allow-repo list so
gardener-filed tree issues and PR comments surface in the Claude Code
statusline. Never use --allow-repo all — it reopens the
2026-04-21 stranger-repo incident.
Gardener supports two deployment shapes that share the same verdict and issue-filing logic:
| Mode | How it runs | When to use |
|---|---|---|
| Push (workflow) | .github/workflows/first-tree-sync.yml in the codebase repo fires per-PR; no daemon. | You (or your agent) can land a workflow file in the codebase. Lowest latency, zero infra. |
| Pull (daemon) | first-tree gardener start launches a long-running daemon that polls every configured source repo on a timer. | The codebase repo is third-party or you otherwise can't push workflow files. Also the right choice when you want drift detection (gardener sync) on a schedule. |
Both modes open the same tree-repo issue on merge and post the same
verdict comment shape on open/updated PRs. The only difference is the
trigger. For the push-mode installer + auth + troubleshooting walkthrough,
see ../first-tree/references/workflow-mode.md.
Load this skill when the task involves any of:
Gardener is designed for agents, not humans. Every subcommand is idempotent and guarded against acting on its own prior comments.
first-tree gardener sync) to propagate a decision; gardener's
respond subcommand fixes these based on reviewer feedback.comment subcommand evaluates against the bound
Context Tree and annotates with a structured verdict.comment sees a merged source PR
that was never reviewed while open, it can open a tree issue so the
tree picks up the decision retroactively. Gated by TREE_REPO_TOKEN.<!-- gardener:state · reviewed=<sha> · verdict=… · severity=… · tree_sha=… -->,
a sibling last_consumed_rereview line, and a sibling
quiet_refresh_cid line for rescan fast-path. Parsing is additive —
legacy comments without newer fields degrade gracefully.comment) — gardener does not comment on
first-tree sync PRs themselves; use respond for those.These are the commands you invoke directly to set gardener up or check on it. Everything else is driven by these, by breeze, or by CI.
| Command | Purpose |
|---|---|
| first-tree gardener install-workflow | Scaffold .github/workflows/first-tree-sync.yml in a codebase repo — the push-mode entry point. Per-PR events drive the sync flow; no daemon required. |
| first-tree gardener start | Launch the pull-mode daemon in the background. Writes ~/.gardener/config.json from --tree-path + repeated --code-repo args, then boots a launchd job (macOS) or detached process. Schedules: --gardener-interval (default 5m), --sync-interval (default 1h). --assign-owners and --sync-apply wire their downstream flags. |
| first-tree gardener stop | Tear down the launchd job (macOS) or SIGTERM the PID in ~/.gardener/state.json. Idempotent. |
| first-tree gardener status | Print the recorded PID + uptime, configured schedule, and last outcome + next-due time per sweep. Read-only. |
| first-tree gardener run-once | Run both sweeps inline, no daemon. Useful for cron-style deployments or exercising the pipeline before leaving a daemon running. |
These are the units of work. You can still invoke them manually for one-off
runs or dry-runs, but the normal trigger is start, push-mode workflow, or
breeze's notification dispatch.
| Command | Purpose |
|---|---|
| first-tree gardener sync | Detect drift between the tree and its bound source repos. Writes proposals under .first-tree/proposals/, edits tree files, commits to a new branch in the tree repo, and opens a PR labeled first-tree:sync. Phases: --propose detects + writes proposals, --apply also writes new tree files and opens the PR, default is detect-only. Moved from first-tree tree sync. |
| first-tree gardener comment | Review a source-repo PR or issue against the tree and post a structured verdict comment. Scan mode (no --pr/--issue) walks every open PR and issue. The merge→tree-issue branch only fires on a single MERGED PR with a prior gardener marker (single-item invocation), and requires TREE_REPO_TOKEN. Pass --assign-owners to auto-assign NODE owners on the tree issue. |
| first-tree gardener respond | Acknowledge reviewer feedback on a sync PR (Phase 5: real edit orchestrator for parent_subdomain_missing + planner seam — see #160 / #219; unsupported patterns fall back to a placeholder reply). |
| first-tree gardener draft-node | Consume a tree-repo issue carrying the gardener:sync-proposal marker (filed by sync --open-issues or comment on a merged PR), copy the proposed NODE.md onto a deterministic first-tree/draft-node-<proposal_id> branch, and open a tree PR for human review. Invoked by breeze when the assignee is the breeze identity; not typically run by hand. Requires TREE_REPO_TOKEN. |
| first-tree gardener daemon | Foreground loop invoked by start. Not intended for direct human use. |
For full options on any command, run first-tree gardener <command> --help.
gardener comment fails closed without a classifier. Before running any
of the scan/single-item/pull/push-mode flows below, provision:
ANTHROPIC_API_KEY — required for every shipped automation path.
Without it the stock CLI refuses to post verdicts and exits 0 with
BREEZE_RESULT: status=skipped summary=no classifier injected.GARDENER_CLASSIFIER_MODEL — optional override (default
claude-haiku-4-5). Blank values are normalized to the default, so
it's safe to leave the GitHub Actions secret unset.See the per-mode flows below for where each automation entrypoint reads
these vars (shell env for scan/single-item/run-once, launchd plist
for pull-mode daemon on macOS, workflow env: block for push mode).
export ANTHROPIC_API_KEY=sk-... # required
# export GARDENER_CLASSIFIER_MODEL=... # optional; default claude-haiku-4-5
npx -p first-tree first-tree gardener comment
Run from inside a tree repo. Reads .claude/gardener-config.yaml, then
walks every open PR and issue on every configured source repo
(target_repo scalar + target_repos list, deduped), posting structured
verdict comments against the tree. Results are aggregated into a single
BREEZE_RESULT trailer with repos=<n>. Without ANTHROPIC_API_KEY
the stock CLI skips the sweep (status=skipped summary=no classifier injected) and does not call gh.
npx -p first-tree first-tree gardener comment --merged-since 24h --assign-owners
Same as scan mode but also fetches PRs merged within the window (e.g.
1h, 24h, 7d, or an ISO-8601 timestamp) and routes them through the
same reviewer. Merged PRs with a prior gardener marker take the
merge→tree-issue branch when TREE_REPO_TOKEN is set — this is how the
gardener pull-mode daemon catches post-merge events without needing
GitHub webhooks. Without --merged-since, scan mode looks at open items
only; the merge→tree-issue branch still fires from single-item
invocations as before.
npx -p first-tree first-tree gardener comment --pr 42 --repo owner/app-repo
npx -p first-tree first-tree gardener comment --issue 7 --repo owner/app-repo
The single-item form is what breeze-runner calls when dispatching on a
notification. Skips the scan; reviews exactly the one item. Also takes
the merge→tree-issue branch when pointed at a single MERGED PR with a
prior gardener marker and TREE_REPO_TOKEN set. ANTHROPIC_API_KEY
must be present in the invoking shell or the run exits early with
status=skipped summary=no classifier injected.
Use this when push-mode workflows aren't an option or when you want
drift detection (gardener sync) to run on a timer in addition to
per-PR verdict comments.
export ANTHROPIC_API_KEY=sk-... # required; forwarded into launchd plist
# export GARDENER_CLASSIFIER_MODEL=... # optional override
# 1. Bind the tree checkout first (if not already): `first-tree tree bind`
# 2. Start the daemon pointed at the tree + the code repos to watch.
npx -p first-tree first-tree gardener start \
--tree-path ../my-org-tree \
--code-repo my-org/web --code-repo my-org/api \
--gardener-interval 5m \
--sync-interval 1h \
--assign-owners
What happens:
~/.gardener/config.json is written with the supplied schedule.com.first-tree.gardener.<user>.plist
lives at ~/.gardener/launchd/ and is bootstrapped into the user
domain. ANTHROPIC_API_KEY and (if set) GARDENER_CLASSIFIER_MODEL
from the invoking shell are forwarded into the plist's
EnvironmentVariables dict — launchd does not inherit shell env, so
these must be exported before gardener start. On other platforms,
a detached child process is spawned with the full parent env.gardener-sweep or sync-sweep is due and runs it as a subprocess
(gardener comment --merged-since 2×interval and gardener sync
respectively). Outcomes get written to ~/.gardener/state.json.Inspect and tear down:
npx -p first-tree first-tree gardener status # last runs + next due
npx -p first-tree first-tree gardener run-once # fire both sweeps inline
npx -p first-tree first-tree gardener stop # launchctl bootout + SIGTERM
Set --sync-apply on start to have sync-sweep open tree PRs
automatically (gardener sync --apply); without it, the sweep stays in
detect-only mode.
Agent-driven path. Before running anything, walk the user through the
preflight in ../first-tree/references/workflow-mode.md
(confirm consent, tree-repo slug, codebase-repo slug). Then:
npx -p first-tree first-tree gardener install-workflow \
--tree-repo <OWNER>/<TREE_REPO_NAME>
Set the TREE_REPO_TOKEN secret (see the workflow-mode reference for
the quick gh auth token path and its caveats, or the scoped-PAT
fallback) and the CLAUDE_CODE_OAUTH_TOKEN secret on the codebase
repo. The generated workflow installs claude, authenticates it via
CLAUDE_CODE_OAUTH_TOKEN, and runs first-tree gardener comment on
every PR. ANTHROPIC_API_KEY / GARDENER_CLASSIFIER_MODEL remain
optional secrets if you want an API-key fallback or model override.
Commit the generated workflow file and open a PR. On every PR merge
thereafter the workflow files a tree-repo issue assigned to the NODE
owners.
npx -p first-tree first-tree gardener respond --pr 123 --repo owner/tree-repo
Single-PR only. There is no scan mode — discovery for respond lives in
breeze's notification poller. Add --dry-run to preview.
Current behavior (placeholder reply only):
respondbumps the attempts marker and posts an acknowledgement reply, but does not yet editNODE.md, commit, or push. Wiring the real edit orchestrator is tracked in #160 with the Phase 5 scope proposal in #219.
Both subcommands accept --dry-run, which prints every planned
gh/git call without executing it. Use this when introducing gardener
to a new repo or verifying config before a live run.
Add --assign-owners to have merged-PR tree issues auto-assigned to
the NODE owners resolved from the tree's CODEOWNERS. Push-mode
workflows set this flag by default; pull-mode deployments can opt in
per-invocation.
npx -p first-tree first-tree gardener <command>
This always runs the latest published version.
Gardener reads .claude/gardener-config.yaml from the tree repo
(resolved via --tree-path, default cwd):
# Either form (or both) is accepted. Scan mode sweeps the deduped union
# in source order: scalar first, then list, then any extras the typed
# loader adds. Pick scalar when binding one source repo, list for fan-out.
target_repo: owner/app-repo # source repo to review (scalar)
target_repos: # source repos to review (list)
- owner/app-repo-frontend
- owner/app-repo-backend
tree_repo: owner/tree-repo # this tree repo (for attribution links)
modules:
comment:
enabled: true # set false to opt the tree out entirely
respond:
enabled: true
The modules.<name>.enabled: false knob is the opt-out: gardener exits
0 with a skipped status without calling gh.
Gardener reads a small set of env vars. CLAUDE_CODE_OAUTH_TOKEN
authenticates the installed claude CLI in CI; ANTHROPIC_API_KEY
is the fallback classifier path when claude auth is unavailable;
TREE_REPO_TOKEN is required only for the merge→issue branch.
| Variable | Purpose |
|---|---|
| CLAUDE_CODE_OAUTH_TOKEN | OAuth token for the installed claude CLI in CI. The push-mode workflow generated by install-workflow forwards this into the gardener step so selectClassifier() can use the claude-cli path without a separate API key. |
| ANTHROPIC_API_KEY | Fallback classifier credential for gardener comment when claude is unavailable or unauthenticated. Forwarded into the launchd plist by gardener start; also accepted by the push-mode workflow as an optional fallback secret. If neither claude auth nor ANTHROPIC_API_KEY is available, runComment fails closed and emits BREEZE_RESULT: status=skipped summary=no classifier injected without touching gh. |
| GARDENER_CLASSIFIER_MODEL | Optional override for the classifier model (default claude-haiku-4-5). Blank/unset is normalized to the default, so it's safe to leave the GitHub Actions secret empty. |
| BREEZE_SNAPSHOT_DIR | Directory with pre-fetched pr-view.json, pr.diff, issue-view.json, issue-comments.json, pr-reviews.json, subject.json. Set by breeze-runner so gardener doesn't re-fetch. Also enables snapshot-mode idempotency checks in respond when pr-commits.json is present. |
| TREE_REPO_TOKEN | PAT with repo scope on the tree repo. Consumed only by comment's merge→issue branch, for gh issue create and the follow-up marker PATCH. No fallback to GH_TOKEN/GITHUB_TOKEN — if unset, the merge→issue path silently skips and logs skipped: token_absent. |
| COMMENT_LOG | Path for JSONL run events from comment (default $HOME/.gardener/comment-runs.jsonl; falls back to $TMPDIR when HOME is unset). |
| RESPOND_LOG | Same shape for respond (default $HOME/.gardener/respond-runs.jsonl). |
Gardener refuses to act when:
ANTHROPIC_API_KEY is unset (no classifier injected — comment
exits 0 with status=skipped summary=no classifier injected before
calling gh)first-tree:sync PR on a tree repo — use
respond there, not comment.claude/gardener-config.yaml--pr, --issue, --repo) are missingTREE_REPO_TOKEN is unset on the merge→issue branch (skips that
branch; other branches continue)All subcommands are safe to re-run. Idempotency lives in the state
marker: the SHA in reviewed=<sha> tells gardener whether a PR has
already been reviewed at this revision, and the tree_issue_created=<url>
field prevents duplicate issue creation on a retry.
first-tree — entry-point skill: methodology, references, routing.
Load this first.tree — load if the task also requires direct reads or writes against
the tree repo (gardener operates on PRs; tree tools operate on the
tree itself).breeze — load if gardener is being invoked from the breeze daemon's
dispatch pipeline rather than manually.tools
Canonical whitepaper and routing skill for First Tree. Explains what belongs in a Context Tree, how source or workspace roots, tree repos, and bindings relate, and how the current `first-tree tree` and `first-tree github scan` surfaces fit together. Use when you need shared First Tree concepts, need to choose between onboarding, sync, write, or GitHub notification workflows, or need the high-level CLI map before acting.
tools
One-shot onboarding command for First Tree. Drives a repo or workspace from "no first-tree" all the way to "tree bound, real content drafted, daemon running, agent templates confirmed" — end to end, in one skill invocation. Trigger this skill when the user invokes `/first-tree-onboarding`, says "onboard this repo to first-tree", "set up first-tree here", "complete first-tree onboarding", or runs first-tree against an unbound repo or workspace. Also trigger when re-running on an already-bound repo to refresh skills, draft missing content, or reverify the daemon. Use this skill instead of running `first-tree tree init` from raw memory; it owns role-by-role branching, the initial-content drafting phase the CLI does NOT do, and the final doctor checks.
development
Audit and repair drift between merged code and the Context Tree in both directions — tree→code (does code still support tree facts?) and code→tree (does the tree register everything code now contains?). Use when the tree may be stale, wrong, outdated, or missing coverage for recent code changes; after a large merge; before release; on a freshly onboarded tree; or when a GitHub notification was routed `route=sync`. Sync owns broad drift discovery, structural skeleton repair, and substantive write hand-off across one tree. Use `first-tree-write` instead when the user already gave you a specific PR / doc / note to write into the tree.
tools
Operate the `first-tree github scan` CLI — the GitHub notification daemon and inbox runtime. Use whenever you need to run, start, stop, inspect, poll, or debug github-scan; view or respond to GitHub-triggered work from the terminal; or wire up the github-scan statusline hook.