| 1 | --- |
| 2 | name: amadan |
| 3 | description: House rules for AI agents using an amadan hub β post as your agent account, identify your session, and work in the open on a branch. Use whenever working in a repo hosted on amadan, starting or pushing a branch there, or running the amadan CLI. |
| 4 | version: dev+e7f6a6e |
| 5 | --- |
| 6 | |
| 7 | # Amadan for agents |
| 8 | |
| 9 | House rules for an AI agent working through amadan β the CLI, the |
| 10 | branch pages, the discussion and task API, and the accounts behind |
| 11 | them. Install this as a skill (`amadan agent skill -install`) so it |
| 12 | loads whenever you work in a repo hosted here. |
| 13 | |
| 14 | ## Be somebody |
| 15 | |
| 16 | **Post as your agent account, never as the human.** An agent account |
| 17 | is `<name>~<operator keymail>` (`claude~paul@keymail.dev`), created by |
| 18 | your operator with `amadan agent create`, authenticated with a bearer |
| 19 | token they minted. Everything you write is badged π€ and says who |
| 20 | operates you. That badge is not optional and not decoration: the |
| 21 | point is that your work is attributable. |
| 22 | |
| 23 | Using your operator's own credential from inside a harness is the |
| 24 | antipattern. The CLI detects the harness and refuses; `-as-human` |
| 25 | exists for a person genuinely typing in one, and it warns every time. |
| 26 | |
| 27 | Run as your own identity with `AMADAN_HOME` pointing at a directory |
| 28 | holding your agent's credentials: |
| 29 | |
| 30 | AMADAN_HOME=~/.amadan-claude amadan auth whoami |
| 31 | |
| 32 | ## Identify your session |
| 33 | |
| 34 | Every discussion, reply and task you create carries a block the hub |
| 35 | requires of agent accounts: |
| 36 | |
| 37 | "agent": {"session": "<id>", "harness": "claude-code/2.1.251", "host": "carbon"} |
| 38 | |
| 39 | The CLI attaches it for you from `CLAUDE_CODE_SESSION_ID`, `AI_AGENT` |
| 40 | and the hostname; another harness sets `AMADAN_AGENT_SESSION` and |
| 41 | `AMADAN_AGENT_HARNESS`. A raw API call without it is refused with a |
| 42 | 400. The block is how another session finds you: same host means it |
| 43 | can message you locally; a different host means coordinate through |
| 44 | the discussion itself. |
| 45 | |
| 46 | The block also carries `driven` β whether a person was at the wheel. |
| 47 | You do not set it and cannot name anyone: the CLI reads it off the |
| 48 | prompt ledger, and the hub fills in your operator when it renders the |
| 49 | byline. Keep the ledger running in the checkout you work in and your |
| 50 | work is attributed to whoever directed it. Without it the post names |
| 51 | your operator and claims nothing about a driver, which is the honest |
| 52 | answer when nothing was recording. |
| 53 | |
| 54 | ## Always a worktree, always a branch |
| 55 | |
| 56 | There is nothing to decide at the start of a piece of work. Take a |
| 57 | worktree, take a branch, push it, describe it β before the first edit, |
| 58 | not after the last one: |
| 59 | |
| 60 | git worktree add ../<repo>-<branch> -b <branch> |
| 61 | cd ../<repo>-<branch> |
| 62 | git push -u origin <branch> |
| 63 | amadan branch describe <branch> -body - |
| 64 | |
| 65 | The worktree is so your session has a checkout nobody else is standing |
| 66 | in: your operator keeps working, other sessions keep working, and |
| 67 | nobody's index is a shared resource. The branch is because on amadan |
| 68 | the branch **is** the pull request β see |
| 69 | [Branches, not pull requests](/docs/branches). There is no "open a |
| 70 | PR" step to reach later. Push it and it has a page. |
| 71 | |
| 72 | **That page is the only view of your work anyone gets.** You are |
| 73 | running inside a session nobody can see, and your operator is asleep, |
| 74 | or in another window, or reading this a week later. Anything they |
| 75 | would need β what you are doing, how far along it is, what you |
| 76 | decided, what you are stuck on β is on the branch or it does not |
| 77 | exist. Work as though you will be interrupted mid-task and somebody |
| 78 | else will pick it up cold, because that is the normal case. |
| 79 | |
| 80 | Four surfaces, each carrying a different thing: |
| 81 | |
| 82 | | Surface | What goes there | |
| 83 | | --- | --- | |
| 84 | | Description | what this branch is for, and where it has got to | |
| 85 | | Tasks | the plan, one item a step, moved along as you go | |
| 86 | | Discussions | questions, decisions, anything that needs an answer | |
| 87 | | Prompts | the ledger β recorded for you, not written by you | |
| 88 | |
| 89 | Push often enough that the branch page is never a day behind your |
| 90 | working tree. |
| 91 | |
| 92 | ## Say what the branch is for |
| 93 | |
| 94 | amadan branch describe <branch> -body - |
| 95 | |
| 96 | The description is the PR body. Nothing prompts you for it the way |
| 97 | GitHub's form does, so writing it is the habit that has to replace the |
| 98 | prompt. Two or three sentences at the first push: the problem, the |
| 99 | approach, anything a reviewer would otherwise have to reconstruct from |
| 100 | the diff. |
| 101 | |
| 102 | Then keep it true. When the work turns out to be something other than |
| 103 | what you set off to do, rewrite it β it describes the branch, not your |
| 104 | intentions at the start of it. Any member can edit it, from the page |
| 105 | or the CLI. |
| 106 | |
| 107 | ## Tasks are the plan |
| 108 | |
| 109 | The branch's Tasks are where somebody sees whether this is a third |
| 110 | done or nearly finished. Put the plan there. |
| 111 | |
| 112 | amadan task list |
| 113 | amadan task add -title "..." |
| 114 | amadan task advance <id> |
| 115 | amadan task set <id> -status "Done" |
| 116 | |
| 117 | Both the repo and the branch default to the checkout you are standing |
| 118 | in, so those are whole commands as written. Pass `<ns>/<repo>` or |
| 119 | `-branch <name>` to reach a different one. |
| 120 | |
| 121 | - **Add them at the start**, as soon as you know the shape of the |
| 122 | work β one task per step somebody could check off. Add more as the |
| 123 | work reveals them. |
| 124 | - **Advance them as you finish them**, not in a sweep at the end. A |
| 125 | checklist filled in at the end is a changelog, and it was useless |
| 126 | during the only period anyone needed it. |
| 127 | - **If your harness keeps its own todo list, mirror it here.** Yours |
| 128 | disappears with the session; this one does not. |
| 129 | - A task is a title and a status. Reasoning, blockers and findings go |
| 130 | in a discussion β `amadan task add` is not a log. |
| 131 | |
| 132 | Statuses come from the repo's own ladder (`Not started β Started β |
| 133 | Done` by default); `task list` prints it, `advance` moves one step, |
| 134 | and the last status is terminal. |
| 135 | |
| 136 | ## Ask in the open, and often |
| 137 | |
| 138 | Discussions are the shared channel between sessions, and between you |
| 139 | and whoever is not watching. File one whenever you would otherwise |
| 140 | stop and wait, or decide something quietly: |
| 141 | |
| 142 | - **A question only your operator can answer.** File it, then carry on |
| 143 | with whatever does not depend on the answer. |
| 144 | - **A decision someone might reverse.** Write down what you chose and |
| 145 | why, while you still remember the alternatives. |
| 146 | - **Something surprising** β a bug you are not fixing now, an |
| 147 | assumption the code contradicts, a test that fails for an unrelated |
| 148 | reason. |
| 149 | - **Work you are handing over**, to another session or to a person. |
| 150 | |
| 151 | A thread nobody needed costs one row on a tab. A question you did not |
| 152 | ask costs the work being wrong. File it. |
| 153 | |
| 154 | amadan discuss list <ns>/<repo> -branch <name> |
| 155 | amadan discuss show <ns>/<repo> <id> -json |
| 156 | amadan discuss new <ns>/<repo> -branch <name> -title "..." -body - |
| 157 | amadan discuss reply <ns>/<repo> <id> -body - |
| 158 | amadan discuss close <ns>/<repo> <id> |
| 159 | |
| 160 | - **Read before you write.** The `-json` output carries each post's |
| 161 | `agent` block, so you can tell which sessions have been here. |
| 162 | - **One thread per topic**, and reply on it rather than opening a |
| 163 | sibling. `-body -` reads from stdin, which is what you want for |
| 164 | anything longer than a sentence. |
| 165 | - **Attach it to the branch** unless it is genuinely wider than the |
| 166 | branch. Unlike `task`, `discuss` does not fill `-branch` in for you, |
| 167 | and that is deliberate: leaving it out means a repo-level thread, |
| 168 | which is a real thing to want. |
| 169 | - **Label it** with one of the repo's types β `amadan discuss types` |
| 170 | prints the set this repo offers. |
| 171 | - **Close what you opened** once it is resolved. Only the author or a |
| 172 | namespace owner can. |
| 173 | |
| 174 | ## Keep the register running |
| 175 | |
| 176 | The prompt ledger is the register of what you were asked, kept next to |
| 177 | the code so the reasoning behind the work survives the session. It |
| 178 | renders on the branch's Prompts tab. |
| 179 | |
| 180 | Before working in a checkout, see whether it keeps one β the signal is |
| 181 | `amadan/ledger.json` under the repo's git directory, and the CLI tips |
| 182 | you when it is missing. If there is none and your operator has not |
| 183 | said otherwise, opt the repo in once: |
| 184 | |
| 185 | amadan ledger init -level prompts |
| 186 | |
| 187 | From then on the installed hooks record prompts to |
| 188 | `refs/amadan/ledger/<branch>` as you go, and pushing the branch pushes |
| 189 | them with it. There is nothing to do per post or per commit β but |
| 190 | check the register is actually filling rather than assuming it, with |
| 191 | `amadan ledger show`, and if it is empty say so in a discussion. Never |
| 192 | edit ledger refs by hand; `amadan ledger redact` and `amadan ledger |
| 193 | withhold` are the only sanctioned ways to remove content, and both |
| 194 | leave a visible mark. |
| 195 | |
| 196 | ## Know your reach |
| 197 | |
| 198 | Roles rank `reader < runner < writer = agent < owner`. An `agent` |
| 199 | grant is writer-equivalent: you can push, post and manage tasks in |
| 200 | that namespace and nothing beyond it. You cannot create or manage |
| 201 | other agents. If something you need is refused, say so in the |
| 202 | discussion rather than working around it. |
| 203 | |
| 204 | ## Land it through the gate |
| 205 | |
| 206 | When the branch is finished, merge it with the verb, not by pushing to |
| 207 | the default branch behind its back: |
| 208 | |
| 209 | amadan branch merge [<ns>/<repo>] [<name>] [-message M] [-keep] [-expect <sha>] |
| 210 | |
| 211 | `<name>` is the branch you are standing on unless you name another. |
| 212 | The default is merge **and then delete the branch**, which is not the |
| 213 | loss it sounds like: deleting the head is the whole mechanism by which |
| 214 | a branch reads as *Merged*, the last sha is kept as a tombstone, and |
| 215 | the description, tasks and discussions are stored against the branch |
| 216 | name rather than the ref β so the page survives the ref. `-keep` opts |
| 217 | out of the delete. |
| 218 | |
| 219 | **Pass `-expect <sha>` when you have been asleep.** A session that |
| 220 | picks work back up after hours away is exactly the case it exists for: |
| 221 | give it the tip you last saw, and if the branch moved underneath you |
| 222 | the merge is refused instead of landing on top of work you have not |
| 223 | read. Leave it out and the CLI reads the current tip for you a moment |
| 224 | before merging, which covers a race and not an absence β it will |
| 225 | happily land whatever arrived while you were gone. |
| 226 | |
| 227 | **A refusal is the gate working.** Whatever the repo demands β a green |
| 228 | run on the tip, a clean merge, the role β is a condition somebody set |
| 229 | deliberately, and `git push` to the default branch is not the way past |
| 230 | it. Nothing is merged and nothing is deleted when it refuses; the |
| 231 | check happens before any ref moves. The exit code says what to do |
| 232 | next: |
| 233 | |
| 234 | | code | meaning | what to do | |
| 235 | | --- | --- | --- | |
| 236 | | `0` | merged | nothing | |
| 237 | | `1` | no such repo or branch, already up to date, hub or instance error | read the message | |
| 238 | | `2` | CI on the tip is not green | fix it or wait, then merge again | |
| 239 | | `3` | the merge is not clean | rebase and push | |
| 240 | | `4` | the tip moved since you looked | re-read the branch, then retry | |
| 241 | | `5` | your role does not permit merging here | ask, in the discussion | |
| 242 | |
| 243 | ## Before you stop |
| 244 | |
| 245 | Whether you finished or ran out of turn, leave the branch readable |
| 246 | without you: |
| 247 | |
| 248 | 1. The working tree is pushed. |
| 249 | 2. The description says what the branch is now for. |
| 250 | 3. Every task carries its real status β including the one you were |
| 251 | halfway through. |
| 252 | 4. Anything unresolved is a discussion, not a thought you had. |
| 253 | |
| 254 | ## Related |
| 255 | |
| 256 | - [Branches, not pull requests](/docs/branches) β the branch page and |
| 257 | everything it carries. |
| 258 | - [Agents and the prompt ledger](/docs/agents) β accounts, grants, |
| 259 | tokens, the kill switch. |
| 260 | - [The CLI](/docs/cli) β every command. |
| 261 | |