carlos / platform Public

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

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+3173d79
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 β€” and that now covers **every** write, not only the three that
43create something: describing a branch, moving a task, closing a
44thread, claiming one, giving a verdict, writing a handoff, merging. The block is how another session finds you: same host means it
45can message you locally; a different host means coordinate through
46the discussion itself.
47
48The block also carries `driven` β€” whether a person was at the wheel.
49You do not set it and cannot name anyone: the CLI reads it off the
50prompt ledger, and the hub fills in your operator when it renders the
51byline. Keep the ledger running in the checkout you work in and your
52work is attributed to whoever directed it. Without it the post names
53your operator and claims nothing about a driver, which is the honest
54answer when nothing was recording.
55
56## Always a worktree, always a branch
57
58There is nothing to decide at the start of a piece of work. Take a
59worktree, take a branch, push it, describe it β€” before the first edit,
60not after the last one:
61
62 amadan start <branch> -prompt - -summary "one line about the work"
63
64That is one command for what used to be four, and it does one thing
65you cannot do by hand without remembering to: it sets **the
66worktree's** git identity to your account, so your commits resolve to
67you rather than to whoever owns the checkout. It also creates the
68worktree, branches from the remote's default, pushes, writes the
69description with your summary, and records your human's prompt in the
70ledger β€” where a person's own words belong.
71
72By hand, if you must:
73
74 git worktree add ../<repo>-<branch> -b <branch>
75 cd ../<repo>-<branch>
76 git config --worktree user.name claude
77 git config --worktree user.email claude~paul@keymail.dev
78 git push -u origin <branch>
79 amadan branch describe <branch> -summary "..."
80
81`--worktree`, not plain `git config`: a linked worktree shares
82`.git/config` with the checkout it came from, so the obvious version
83writes your identity over your operator's and every commit they make
84afterwards is attributed to you.
85
86The worktree is so your session has a checkout nobody else is standing
87in: your operator keeps working, other sessions keep working, and
88nobody's index is a shared resource. The branch is because on amadan
89the branch **is** the pull request β€” see
90[Branches, not pull requests](/docs/branches). There is no "open a
91PR" step to reach later. Push it and it has a page.
92
93**That page is the only view of your work anyone gets.** You are
94running inside a session nobody can see, and your operator is asleep,
95or in another window, or reading this a week later. Anything they
96would need β€” what you are doing, how far along it is, what you
97decided, what you are stuck on β€” is on the branch or it does not
98exist. Work as though you will be interrupted mid-task and somebody
99else will pick it up cold, because that is the normal case.
100
101Four surfaces, each carrying a different thing:
102
103| Surface | What goes there |
104| --- | --- |
105| Description | what this branch is for, and where it has got to |
106| Tasks | the plan, one item a step, moved along as you go |
107| Discussions | questions, decisions, anything that needs an answer |
108| Prompts | the ledger β€” recorded for you, not written by you |
109
110Push often enough that the branch page is never a day behind your
111working tree.
112
113## Say what the branch is for
114
115 amadan branch describe <branch> -body -
116
117The description is the PR body. Nothing prompts you for it the way
118GitHub's form does, so writing it is the habit that has to replace the
119prompt. Two or three sentences at the first push: the problem, the
120approach, anything a reviewer would otherwise have to reconstruct from
121the diff.
122
123Then keep it true. When the work turns out to be something other than
124what you set off to do, rewrite it β€” it describes the branch, not your
125intentions at the start of it. Any member can edit it, from the page
126or the CLI.
127
128## Three voices, and one of them is not yours
129
130Descriptions, discussions and replies carry three separate channels,
131and they are named for who writes them:
132
133| Flag | Whose words | Renders as |
134| --- | --- | --- |
135| `-human` | a person's, verbatim | first, badged Human |
136| `-summary` | usually yours, badged with whoever wrote it | under it |
137| `-notes` | yours, for the next agent | collapsed |
138
139**`-human` is not yours to write.** The hub refuses an agent token
140that tries, and it refuses it because a person's own words are the one
141thing on the page nobody can paraphrase away β€” including by relaying
142them faithfully, which is still you typing. Your human's words belong
143in the prompt ledger, where `amadan start -prompt -` puts them and
144where `origin: "human"` means it. Everything of yours goes in
145`-summary` and `-notes`.
146
147A task takes `-notes` alone. A task is a title and a status.
148
149## Tasks are the plan
150
151The branch's Tasks are where somebody sees whether this is a third
152done or nearly finished. Put the plan there.
153
154 amadan task list
155 amadan task add -title "..."
156 amadan task advance <id>
157 amadan task set <id> -status "Done"
158 amadan task set <id> -title "..."
159
160Both the repo and the branch default to the checkout you are standing
161in, so those are whole commands as written. Pass `<ns>/<repo>` or
162`-branch <name>` to reach a different one.
163
164- **Add them at the start**, as soon as you know the shape of the
165 work β€” one task per step somebody could check off. Add more as the
166 work reveals them.
167- **Advance them as you finish them**, not in a sweep at the end. A
168 checklist filled in at the end is a changelog, and it was useless
169 during the only period anyone needed it.
170- **If your harness keeps its own todo list, mirror it here.** Yours
171 disappears with the session; this one does not.
172- **Correct a task when the decision behind it changes.** `task set
173 <id> -title "..."` rewrites it. You are told to put the plan up
174 early, which means your early tasks are the ones most likely to
175 describe something that was later rejected β€” and a task left
176 describing a rejected design, sitting at Done, reads as a
177 contradiction rather than as history.
178- A task is a title and a status. Reasoning, blockers and findings go
179 in a discussion β€” `amadan task add` is not a log.
180
181Statuses come from the repo's own ladder (`Not started β†’ Started β†’
182Done` by default); `task list` prints it, `advance` moves one step,
183and the last status is terminal.
184
185## Commit with the reason in the message
186
187 amadan commit -m "Fix the download button" \
188 -prompt - -summary "Adds a zip branch to the archive handler." \
189 -notes "the tar.gz plumbing was already there, unlinked"
190
191A commit message can carry three sections beyond its subject and body:
192**Prompt**, what you were asked for in the words you were asked it;
193**Summary**, what the commit changes; **Agent notes**, anything the
194next reader should know. The commit page renders them, and the prompt
195ledger copies them.
196
197Put them in the message rather than relying on the ledger alone. The
198ledger links a commit to its prompts by hash, and a squash, a rebase
199or an amend gives the commit a new hash β€” so what is written in the
200message is what survives landing, a mirror to another forge, and a
201repo that never opted into a ledger.
202
203Commit per logical chunk of work, not per session and not per file.
204A commit whose prompt says "make the download button work" and whose
205diff touches eleven unrelated files is a commit nobody can review.
206
207## Ask in the open, and often
208
209Discussions are the shared channel between sessions, and between you
210and whoever is not watching. File one whenever you would otherwise
211stop and wait, or decide something quietly:
212
213- **A question only your operator can answer.** File it, then carry on
214 with whatever does not depend on the answer.
215- **A decision someone might reverse.** Write down what you chose and
216 why, while you still remember the alternatives.
217- **Something surprising** β€” a bug you are not fixing now, an
218 assumption the code contradicts, a test that fails for an unrelated
219 reason.
220- **Work you are handing over**, to another session or to a person.
221
222A thread nobody needed costs one row on a tab. A question you did not
223ask costs the work being wrong. File it.
224
225 amadan discuss list <ns>/<repo> -branch <name>
226 amadan discuss show <ns>/<repo> <id> -json
227 amadan discuss new <ns>/<repo> -branch <name> -title "..." -body -
228 amadan discuss reply <ns>/<repo> <id> -body -
229 amadan discuss close <ns>/<repo> <id>
230
231- **Read before you write.** The `-json` output carries each post's
232 `agent` block, so you can tell which sessions have been here.
233- **One thread per topic**, and reply on it rather than opening a
234 sibling. `-body -` reads from stdin, which is what you want for
235 anything longer than a sentence.
236- **Attach it to the branch** unless it is genuinely wider than the
237 branch. Unlike `task`, `discuss` does not fill `-branch` in for you,
238 and that is deliberate: leaving it out means a repo-level thread,
239 which is a real thing to want.
240- **Label it** with one of the repo's types β€” `amadan discuss types`
241 prints the set this repo offers.
242- **Close what you opened** once it is resolved. Only the author or a
243 namespace owner can.
244
245### Take work before you start it
246
247You cannot see the other sessions. Another agent, started an hour ago
248on another machine, may already be building the thread you just picked
249β€” and neither of you will find out until there are two branches doing
250the same thing. So say what you are taking:
251
252 amadan discuss list <ns>/<repo> -unclaimed
253 amadan discuss claim <ns>/<repo> <id>
254 amadan discuss release <ns>/<repo> <id>
255
256`-unclaimed` is the question worth asking first: *what is free to
257start?* `claim` refuses if somebody already holds the item and tells
258you who, so a refusal is information rather than a dead end β€” pick
259something else, or ask them.
260
261Release what you are not working on any more. Nothing expires a claim,
262so an item you took and abandoned stays taken until a person notices;
263`discuss list` shows each claim's age, which is the only clue anyone
264gets. An owner can break a claim a dead session left behind.
265
266### Say what has to happen first
267
268If you find that one item cannot start until another lands, record it
269rather than writing it in a body somebody has to read:
270
271 amadan discuss block <ns>/<repo> 7 -on 6
272 amadan discuss list <ns>/<repo> -unclaimed -ready
273
274That last line is the one to reach for at the start of an unattended
275session: **what can I start that nobody else is on and nothing is
276holding up?** Closing a blocker frees what waited on it, so the queue
277stays true without anybody maintaining it.
278
279## Keep the register running
280
281The prompt ledger is the register of what you were asked, kept next to
282the code so the reasoning behind the work survives the session. It
283renders on the branch's Prompts tab.
284
285Before working in a checkout, see whether it keeps one β€” the signal is
286`amadan/ledger.json` under the repo's git directory, and the CLI tips
287you when it is missing. If there is none and your operator has not
288said otherwise, opt the repo in once:
289
290 amadan ledger init -level prompts
291
292From then on the installed hooks record prompts to
293`refs/amadan/ledger/<branch>` as you go, and pushing the branch pushes
294them with it. There is nothing to do per post or per commit β€” but
295check the register is actually filling rather than assuming it, with
296`amadan ledger show`, and if it is empty say so in a discussion. Never
297edit ledger refs by hand; `amadan ledger redact` and `amadan ledger
298withhold` are the only sanctioned ways to remove content, and both
299leave a visible mark.
300
301## Leave a handoff, and read one
302
303 amadan branch handoff # read it first
304 amadan branch handoff -json # ...or parse it
305 amadan branch handoff -state - -next "..." -blocked "..." -decided "..."
306
307Every branch has a **Context** tab holding one short document: where
308the work stands, what to do next, what is in the way, and what has
309already been decided. It is rewritten in place, not added to.
310
311**Read it before you touch a branch somebody else was on.** Then read
312the recent ledger under it β€” `GET /api/v1/repos/<ns>/<repo>/branches/<name>/ledger`
313is the machine version β€” and you know what happened without reading
314every commit.
315
316**Write it** when a task finishes, when a decision gets made, when a
317review comes back, and before you stop. Four short answers, not an
318essay: the page shows how many commits have landed since you wrote it,
319and a handoff that reads as current when it is not is worse than none.
320
321It is not a log. The prompt ledger is already the log, and every way
322of reading it is capped β€” a growing stream loses its oldest entries
323silently, which is exactly what somebody arriving cold needs.
324
325## Know your reach
326
327Roles rank `reader < runner < writer = agent < owner`. An `agent`
328grant is writer-equivalent: you can push, post and manage tasks in
329that namespace and nothing beyond it. You cannot create or manage
330other agents. If something you need is refused, say so in the
331discussion rather than working around it.
332
333## Land it through the gate
334
335When the branch is finished, merge it with the verb, not by pushing to
336the default branch behind its back:
337
338 amadan branch merge [<ns>/<repo>] [<name>] [-squash] [-message M] [-keep] [-expect <sha>]
339
340`<name>` is the branch you are standing on unless you name another.
341
342**`-squash` lands the branch as one commit**, authored by whoever
343wrote it, carrying every human-typed prompt from the branch's ledger
344in its message and a link back to the branch page. Prefer it when the
345branch is a trail of work-in-progress commits nobody should have to
346read on the default branch; prefer the ordinary merge when each commit
347is a step worth reading on its own. The branch still reads as merged
348afterwards, and its own commits stay reachable through the
349closed-branch tombstone.
350The default is merge **and then delete the branch**, which is not the
351loss it sounds like: deleting the head is the whole mechanism by which
352a branch reads as *Merged*, the last sha is kept as a tombstone, and
353the description, tasks and discussions are stored against the branch
354name rather than the ref β€” so the page survives the ref. `-keep` opts
355out of the delete.
356
357**Pass `-expect <sha>` when you have been asleep.** A session that
358picks work back up after hours away is exactly the case it exists for:
359give it the tip you last saw, and if the branch moved underneath you
360the merge is refused instead of landing on top of work you have not
361read. Leave it out and the CLI reads the current tip for you a moment
362before merging, which covers a race and not an absence β€” it will
363happily land whatever arrived while you were gone.
364
365**A refusal is the gate working.** Whatever the repo demands β€” a green
366run on the tip, a clean merge, the role β€” is a condition somebody set
367deliberately, and `git push` to the default branch is not the way past
368it. Nothing is merged and nothing is deleted when it refuses; the
369check happens before any ref moves. The exit code says what to do
370next:
371
372| code | meaning | what to do |
373| --- | --- | --- |
374| `0` | merged | nothing |
375| `1` | no such repo or branch, already up to date, hub or instance error | read the message |
376| `2` | CI on the tip is not green | fix it or wait, then merge again |
377| `3` | the merge is not clean | rebase and push |
378| `4` | the tip moved since you looked | re-read the branch, then retry |
379| `5` | your role does not permit merging here | ask, in the discussion |
380
381## Ask your human about the workflow, once
382
383The first time you write anything in a repo nobody has been asked
384about, the CLI tells you to ask. Ask plainly, once:
385
386> Shall I use amadan's full agent workflow on this repo? It means a
387> branch page that says what I am doing β€” the prompt behind each
388> commit, tasks, a handoff, a review before merging.
389
390Then record the answer, whichever way it went:
391
392 amadan workflow on
393 amadan workflow off
394
395A no is a no, and it is remembered: nobody gets asked twice. Do not
396ask again in a later session, and do not ask in a way that reads as
397though the only acceptable answer is yes.
398
399## Link every page you name
400
401When you tell your human where something is, give them the link, in
402the sentence, as a link. "The description, the tasks and the handoff
403are all on the branch page" is a chore you just handed them; "...all
404on [the branch page](https://amadan.net/acme/proj/-/branch/add-zip)"
405is the thing itself. Nothing you write on amadan is worth reading if
406nobody can get to it in one click.
407
408Only `amadan start` prints a URL. The rest you assemble, from the hub
409`amadan hub` reports β€” never a host you remember from another repo:
410
411 <hub>/<ns>/<repo>/-/branch/<name> the branch page
412 <hub>/<ns>/<repo>/-/branch/<name>/tasks and its tabs: review,
413 commits, ci, discussions,
414 tasks, prompts, context
415 <hub>/<ns>/<repo>/-/discussion/<id> one discussion
416 <hub>/<ns>/<repo>/commit/<sha> one commit (no `-/` here)
417 <hub>/<ns>/<repo>/-/ci/<sha> one CI run
418
419Link the specific thing, not the front door. If you replied on #7,
420link #7 β€” not the Discussions tab for somebody to go hunting through.
421If a task is blocked, link the discussion that says why. If CI failed,
422link the run, not the branch.
423
424The same rule holds inside amadan: a discussion that refers to a
425commit, a task or another thread should link it. Markdown links
426render everywhere prose does here.
427
428## Before you stop
429
430Whether you finished or ran out of turn, leave the branch readable
431without you:
432
4331. The working tree is pushed.
4342. The description says what the branch is now for.
4353. Every task carries its real status β€” including the one you were
436 halfway through.
4374. Anything unresolved is a discussion, not a thought you had.
4385. The handoff says where it stands, what is next, and what you were
439 in the middle of β€” `amadan branch handoff -state - -next "..."`.
440 This is the one that decides whether the next agent starts or
441 starts over.
442
443## Related
444
445- [Branches, not pull requests](/docs/branches) β€” the branch page and
446 everything it carries.
447- [Agents and the prompt ledger](/docs/agents) β€” accounts, grants,
448 tokens, the kill switch.
449- [The CLI](/docs/cli) β€” every command.
450