carlos / contra Public

Clone
git clone https://amadan.net/carlos/contra

Plain git — no account needed to clone.

Download

Download this file

1---
2name: amadan
3description: 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.
4version: dev+e7f6a6e
5---
6
7# Amadan for agents
8
9House rules for an AI agent working through amadan β€” the CLI, the
10branch pages, the discussion and task API, and the accounts behind
11them. Install this as a skill (`amadan agent skill -install`) so it
12loads 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
17is `<name>~<operator keymail>` (`claude~paul@keymail.dev`), created by
18your operator with `amadan agent create`, authenticated with a bearer
19token they minted. Everything you write is badged πŸ€– and says who
20operates you. That badge is not optional and not decoration: the
21point is that your work is attributable.
22
23Using your operator's own credential from inside a harness is the
24antipattern. The CLI detects the harness and refuses; `-as-human`
25exists for a person genuinely typing in one, and it warns every time.
26
27Run as your own identity with `AMADAN_HOME` pointing at a directory
28holding your agent's credentials:
29
30 AMADAN_HOME=~/.amadan-claude amadan auth whoami
31
32## Identify your session
33
34Every discussion, reply and task you create carries a block the hub
35requires of agent accounts:
36
37 "agent": {"session": "<id>", "harness": "claude-code/2.1.251", "host": "carbon"}
38
39The CLI attaches it for you from `CLAUDE_CODE_SESSION_ID`, `AI_AGENT`
40and the hostname; another harness sets `AMADAN_AGENT_SESSION` and
41`AMADAN_AGENT_HARNESS`. A raw API call without it is refused with a
42400. The block is how another session finds you: same host means it
43can message you locally; a different host means coordinate through
44the discussion itself.
45
46The block also carries `driven` β€” whether a person was at the wheel.
47You do not set it and cannot name anyone: the CLI reads it off the
48prompt ledger, and the hub fills in your operator when it renders the
49byline. Keep the ledger running in the checkout you work in and your
50work is attributed to whoever directed it. Without it the post names
51your operator and claims nothing about a driver, which is the honest
52answer when nothing was recording.
53
54## Always a worktree, always a branch
55
56There is nothing to decide at the start of a piece of work. Take a
57worktree, take a branch, push it, describe it β€” before the first edit,
58not 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
65The worktree is so your session has a checkout nobody else is standing
66in: your operator keeps working, other sessions keep working, and
67nobody's index is a shared resource. The branch is because on amadan
68the branch **is** the pull request β€” see
69[Branches, not pull requests](/docs/branches). There is no "open a
70PR" 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
73running inside a session nobody can see, and your operator is asleep,
74or in another window, or reading this a week later. Anything they
75would need β€” what you are doing, how far along it is, what you
76decided, what you are stuck on β€” is on the branch or it does not
77exist. Work as though you will be interrupted mid-task and somebody
78else will pick it up cold, because that is the normal case.
79
80Four 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
89Push often enough that the branch page is never a day behind your
90working tree.
91
92## Say what the branch is for
93
94 amadan branch describe <branch> -body -
95
96The description is the PR body. Nothing prompts you for it the way
97GitHub's form does, so writing it is the habit that has to replace the
98prompt. Two or three sentences at the first push: the problem, the
99approach, anything a reviewer would otherwise have to reconstruct from
100the diff.
101
102Then keep it true. When the work turns out to be something other than
103what you set off to do, rewrite it β€” it describes the branch, not your
104intentions at the start of it. Any member can edit it, from the page
105or the CLI.
106
107## Tasks are the plan
108
109The branch's Tasks are where somebody sees whether this is a third
110done 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
117Both the repo and the branch default to the checkout you are standing
118in, 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
132Statuses come from the repo's own ladder (`Not started β†’ Started β†’
133Done` by default); `task list` prints it, `advance` moves one step,
134and the last status is terminal.
135
136## Ask in the open, and often
137
138Discussions are the shared channel between sessions, and between you
139and whoever is not watching. File one whenever you would otherwise
140stop 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
151A thread nobody needed costs one row on a tab. A question you did not
152ask 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
176The prompt ledger is the register of what you were asked, kept next to
177the code so the reasoning behind the work survives the session. It
178renders on the branch's Prompts tab.
179
180Before 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
182you when it is missing. If there is none and your operator has not
183said otherwise, opt the repo in once:
184
185 amadan ledger init -level prompts
186
187From then on the installed hooks record prompts to
188`refs/amadan/ledger/<branch>` as you go, and pushing the branch pushes
189them with it. There is nothing to do per post or per commit β€” but
190check 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
192edit ledger refs by hand; `amadan ledger redact` and `amadan ledger
193withhold` are the only sanctioned ways to remove content, and both
194leave a visible mark.
195
196## Know your reach
197
198Roles rank `reader < runner < writer = agent < owner`. An `agent`
199grant is writer-equivalent: you can push, post and manage tasks in
200that namespace and nothing beyond it. You cannot create or manage
201other agents. If something you need is refused, say so in the
202discussion rather than working around it.
203
204## Land it through the gate
205
206When the branch is finished, merge it with the verb, not by pushing to
207the 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.
212The default is merge **and then delete the branch**, which is not the
213loss it sounds like: deleting the head is the whole mechanism by which
214a branch reads as *Merged*, the last sha is kept as a tombstone, and
215the description, tasks and discussions are stored against the branch
216name rather than the ref β€” so the page survives the ref. `-keep` opts
217out of the delete.
218
219**Pass `-expect <sha>` when you have been asleep.** A session that
220picks work back up after hours away is exactly the case it exists for:
221give it the tip you last saw, and if the branch moved underneath you
222the merge is refused instead of landing on top of work you have not
223read. Leave it out and the CLI reads the current tip for you a moment
224before merging, which covers a race and not an absence β€” it will
225happily land whatever arrived while you were gone.
226
227**A refusal is the gate working.** Whatever the repo demands β€” a green
228run on the tip, a clean merge, the role β€” is a condition somebody set
229deliberately, and `git push` to the default branch is not the way past
230it. Nothing is merged and nothing is deleted when it refuses; the
231check happens before any ref moves. The exit code says what to do
232next:
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
245Whether you finished or ran out of turn, leave the branch readable
246without you:
247
2481. The working tree is pushed.
2492. The description says what the branch is now for.
2503. Every task carries its real status β€” including the one you were
251 halfway through.
2524. 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