What only a person can do
The steps a coding agent always leaves to you, why each one is yours, and what actually stops an agent that ignores them.
An agent can run almost the whole loop. A few steps stay with you, whatever the agent is asked to do. The guide tells every agent what they are, and the skill repeats the most important ones. Each one guards against a mistake that would be hard or impossible to undo.
The steps that stay with you
Section titled “The steps that stay with you”Publishing, other than through promote
Section titled “Publishing, other than through promote”An agent never pushes a feature branch, the ghostbranch branch or a ghostbranch-gate/… branch to the public repo with git, and never skips git hooks with --no-verify. It pushes feature work to the shadow repo only.
The one exception is an archived feature’s own pull request branch. After the hand-off, fixes to that pull request go there: the agent commits on origin/<branch> and pushes with git push origin HEAD:<branch>, never from the old shadow branch. The guard still refuses the archive’s private commits. Nothing else goes to origin (see After publishing).
Why: promote is the only path for feature work where everything that goes public has been rebased on public main, tested by CI and scanned for leaks. A plain git push skips all three, and once something is public you can’t take it back. The push guard refuses such a push with PUSH_BLOCKED, which is why --no-verify, which skips the guard, is off limits too.
Approving a publish, or letting agents publish
Section titled “Approving a publish, or letting agents publish”An agent never types or reads a console code, never fakes a terminal to get one, and never runs ghostbranch agents allow.
Why: the code is how Ghostbranch knows a person read the summary of what’s about to go public and said yes. An agent answering its own code would make that meaningless. A grant is the same decision made ahead of time, for a while, so it’s yours as well. Letting agents publish covers grants.
Editing Ghostbranch’s records to get past a check
Section titled “Editing Ghostbranch’s records to get past a check”An agent never edits grants.json, plan files or .ghostbranch.yml to make a check pass.
Why: each one holds a decision. The grants file is your permission. A plan file is what you approved, and apply checks it against the real commits anyway. .ghostbranch.yml sets what the leak scan looks for on every feature: loosening it to get one feature through loosens it for all of them.
Waiving a leak finding
Section titled “Waiving a leak finding”An agent never runs ghostbranch waivers add, edits waivers.json, or hides a finding any other way.
Why: a waiver says “I’ve looked at this value, and it’s safe to make public”. Only someone who knows what the value is can say that, and a wrong waiver publishes a secret for good. An agent may rewrite a value that’s plainly fake, such as a placeholder in a test, and must tell you which finding it rewrote. Anything that might be real, it hands to you. See When the gate finds a leak.
Repos, settings, tokens and secrets
Section titled “Repos, settings, tokens and secrets”An agent never creates or deletes repos, except the shadow repo that ghostbranch init creates. It never changes repo settings, tokens or secrets either.
Why: these decide who can see and change your code. A wrong setting can quietly expose a private repo or give a token more reach than it needs. When a token lacks a permission, the agent tells you which one, from TOKEN_PERMISSION_MISSING or ghostbranch doctor, and never asks for wider access than that.
Your login
Section titled “Your login”An agent never runs ghostbranch login or logout, and doesn’t rely on your stored login.
Why: your login is you, with your right to publish. An agent should use the token you gave it. When an agent’s session falls back to your login, doctor and agents status warn AGENT_ON_PERSON_LOGIN, and the agent should tell you.
Other things an agent leaves to you
Section titled “Other things an agent leaves to you”Some steps aren’t forbidden, but they’re your call. An agent may suggest them and give you the command, never run them itself:
- Installing the push guard in your checkout, with
ghostbranch guard install. - Letting agents publish for a while, with
ghostbranch agents allow. - Turning on scheduled sync, which costs Actions minutes, by setting
sync.schedulein.ghostbranch.yml.
Ghostbranch also marks some situations as a person’s: a step in next has needs_human: true, or the error’s code is one a person must act on (explain says so). For example, closing a feature in a way that would lose work, removing a repo pair, a shadow branch that has gone its own way (SYNC_DIVERGED), or a token that lacks a permission. When the agent sees one, it stops.
What the agent does instead
Section titled “What the agent does instead”It stops, and gives you the exact command and the reason. It doesn’t look for another way round. In this leak drill the gate found a token, and the second step in next was a person’s:
The first step in that next, rewriting the commit and gating again, was one an agent could take. The waiver wasn’t. So the agent’s handover says: here’s the finding, here’s the command if you judge it safe, and here’s what I’ll do if you’d rather I removed it.
The token is the real boundary
Section titled “The token is the real boundary”The rules on this page, the code, grants and the push guard are friction. They catch the mistakes of an agent that’s doing its best to follow them. There’s no hidden switch either: no flag or environment variable skips the code, and calling yourself human: in GHOSTBRANCH_ACTOR approves nothing.
But an agent that is set on ignoring the rules runs as you, on your machine. It could fake a terminal, edit the files, or push with git directly. What it can’t do is use a power its token doesn’t have. Give it a token that reaches only the shadow repo, and keep it away from your own tokens, and it can’t publish at all, whatever it does. Strict isolation shows how.
Errors you may see
Section titled “Errors you may see”APPROVAL_REQUIREDexit 5This needs a person: a code typed at a console. For promote and apply, an agent grant also works.
- no_console: no terminal a person can type into
- not_confirmed, timeout, too_many_attempts: the person did not confirm
- grant_needs_yes: a grant exists, but --yes was not passed
Stop and give the human the command in next. It needs a person at a console; for promote and apply, an agent grant made with ghostbranch agents allow also works (feature close and remove ignore grants). Never fake a terminal, answer the code, edit grants.json or run ghostbranch agents allow yourself.
This needs a person.
PUSH_BLOCKEDexit 1The pre-push guard refused to push feature work to the public repo.
- pushing a feature branch, the overlay branch or a gate branch to the public remote
- pushing commits that contain a shadow feature
Publish features only with ghostbranch promote. Never bypass the hook with --no-verify.
SYNC_DIVERGEDexit 4A shadow branch has commits that the public branch does not.
A person investigates the branches in details.branches; Ghostbranch never force-pushes a shadow branch.
This needs a person.
TOKEN_PERMISSION_MISSINGexit 1The token in use lacks a GitHub permission this command needs: error.details.permission on error.details.repo.
- a fine-grained token or the Ghostbranch app wasn't granted that permission, for example Workflows: write to change .github/workflows files
- the repo isn't in the token's or the app installation's repository access
- a classic or OAuth token lacks the scope named (OAuth scope: ...)
Run ghostbranch doctor: it lists every permission the token lacks, for each command. A person grants error.details.permission on error.details.repo (in the fine-grained token's settings, or the Ghostbranch app installation's repository access), then runs the command in error.details.command again. Never ask for wider access than doctor names.
This needs a person.
WAIVERS_UNREADABLEwarningwaivers.json could not be read, so no waiver applied and every finding blocked.
A person fixes the file or clears it with ghostbranch waivers revoke --all. If the message says a newer Ghostbranch wrote it, upgrade ghostbranch on this machine instead: revoke --all keeps a newer file.
This needs a person.