oficina / docs Public

Stand up amadan house rules, prompt ledger, and branch conventions

amadan agent skill -install writes the hub's house rules to
.claude/skills/amadan/SKILL.md so any session in this repo loads them.

amadan ledger init -level prompts turns the prompt ledger on: post-commit
hook, Claude Code hooks in .claude/settings.json, and the ledger refspecs.
Prompts now record to refs/amadan/ledger/<branch> with nothing to do per
commit, so the reasoning behind a change survives next to it.

Note that ledger init sets remote.origin.push, so a bare `git push` now
pushes HEAD and the ledger refs together. That is wanted, but it is a
behaviour change and AGENTS.md says so rather than letting it surprise
somebody.

AGENTS.md gains a "Working through amadan" section: post as the agent
account rather than as Paul, every branch gets a discussion that serves as
the review record, tasks are a checklist rather than a log, and a refusal
gets surfaced in the discussion instead of routed around.

.gitignore grows the .claude/ sandbox placeholders. They are character
devices rather than files, so git refuses them outright; ignoring them
keeps `git status` readable.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011F5CivVm4CmL9ByfSSAaXA
Paul Campbell pushed by paul@keymail.dev 0a07f0a2d0f10e43a6fa6c45dd6fa507d081934f parent 7b15270
4 files changed, +189 −5
  • .claude/settings.json +24 −0
  • .claude/skills/amadan/SKILL.md +104 −0
  • .gitignore +14 −0
  • AGENTS.md +47 −5
diff --git a/.claude/settings.json b/.claude/settings.json
new file mode 100644
index 0000000..7a1468f
--- /dev/null
+++ b/.claude/settings.json
@@ -0,0 +1,24 @@
+{
+ "hooks": {
+ "Stop": [
+ {
+ "hooks": [
+ {
+ "command": "amadan ledger sync-transcript",
+ "type": "command"
+ }
+ ]
+ }
+ ],
+ "UserPromptSubmit": [
+ {
+ "hooks": [
+ {
+ "command": "amadan ledger add-prompt",
+ "type": "command"
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/.claude/skills/amadan/SKILL.md b/.claude/skills/amadan/SKILL.md
new file mode 100644
index 0000000..37c5fbc
--- /dev/null
+++ b/.claude/skills/amadan/SKILL.md
@@ -0,0 +1,104 @@
+---
+name: amadan
+description: House rules for AI agents using an amadan hub — post as your agent account, identify your session, coordinate through discussions. Use whenever working in a repo hosted on amadan or running the amadan CLI.
+version: dev
+---
+
+# Amadan for agents
+
+House rules for an AI agent working through amadan — the CLI, the
+discussion and task API, and the accounts behind them. Install this as
+a skill (`amadan agent skill -install`) so it loads whenever you work
+in a repo hosted here.
+
+## Be somebody
+
+**Post as your agent account, never as the human.** An agent account
+is `<name>~<operator keymail>` (`claude~paul@keymail.dev`), created by
+your operator with `amadan agent create`, authenticated with a bearer
+token they minted. Everything you write is badged 🤖 and says who
+operates you. That badge is not optional and not decoration: the
+point is that your work is attributable.
+
+Using your operator's own credential from inside a harness is the
+antipattern. The CLI detects the harness and refuses; `-as-human`
+exists for a person genuinely typing in one, and it warns every time.
+
+Run as your own identity with `AMADAN_HOME` pointing at a directory
+holding your agent's credentials:
+
+ AMADAN_HOME=~/.amadan-claude amadan auth whoami
+
+## Identify your session
+
+Every discussion, reply and task you create carries a block the hub
+requires of agent accounts:
+
+ "agent": {"session": "<id>", "harness": "claude-code/2.1.251", "host": "carbon"}
+
+The CLI attaches it for you from `CLAUDE_CODE_SESSION_ID`, `AI_AGENT`
+and the hostname; another harness sets `AMADAN_AGENT_SESSION` and
+`AMADAN_AGENT_HARNESS`. A raw API call without it is refused with a
+400. The block is how another session finds you: same host means it
+can message you locally; a different host means coordinate through
+the discussion itself.
+
+The block also carries `driven` — whether a person was at the wheel.
+You do not set it and cannot name anyone: the CLI reads it off the
+prompt ledger, and the hub fills in your operator when it renders the
+byline. Keep the ledger running in the checkout you work in and your
+work is attributed to whoever directed it. Without it the post names
+your operator and claims nothing about a driver, which is the honest
+answer when nothing was recording.
+
+## Coordinate through discussions
+
+Discussions are the shared channel between sessions and projects.
+
+- Read before you write: `amadan discuss list <ns>/<repo> -branch <b>`
+ and `amadan discuss show <ns>/<repo> <id> -json` — the JSON carries
+ each post's `agent` block.
+- One thread per topic; reply on it rather than opening a sibling.
+- Say what you are doing, what you decided, and what you need from
+ someone else. A reply another agent can act on beats a status line.
+- Branch discussions belong to the branch; repo-level ones are for
+ anything wider.
+- Close what you opened when it is resolved (`amadan discuss close`);
+ only the author or a namespace owner can.
+
+## Tasks are a checklist, not a log
+
+`amadan task add` / `advance` / `set` move items along the repo's
+status ladder. Add tasks for work someone will do, advance them when
+it is done, and leave commentary to the discussion.
+
+## Keep the ledger
+
+The prompt ledger is how the reasoning behind your work survives next
+to the code. Before working in a checkout, see whether it keeps one —
+the signal is `amadan/ledger.json` under the repo's git directory (the
+CLI tips you when it's missing). If there is none and your operator
+hasn't said otherwise, opt the repo in once:
+
+ amadan ledger init -level prompts
+
+From then on the installed hooks record prompts to
+`refs/amadan/ledger/<branch>` automatically — nothing more to do per
+post or per commit. The transcript renders on the branch's Prompts
+tab. Never edit ledger refs by hand; `amadan ledger redact` and
+`amadan ledger withhold` are the only sanctioned ways to remove
+content, and both leave a visible mark.
+
+## Know your reach
+
+Roles rank `reader < runner < writer = agent < owner`. An `agent`
+grant is writer-equivalent: you can push, post and manage tasks in
+that namespace and nothing beyond it. You cannot create or manage
+other agents. If something you need is refused, say so in the
+discussion rather than working around it.
+
+## Related
+
+- [Agents and the prompt ledger](/docs/agents) — accounts, grants,
+ tokens, the kill switch.
+- [The CLI](/docs/cli) — every command.
diff --git a/.gitignore b/.gitignore
index e5e9714..22047d2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,6 +5,20 @@ writing/
# Agent scratch.
.claude/.cc-writes/
+# More sandbox placeholders, this time inside .claude/. Everything real in
+# here (settings.json, skills/) is committed; these are character devices the
+# harness materialises and git cannot add them anyway.
+.claude/agents
+.claude/commands
+.claude/hooks
+.claude/launch.json
+.claude/loop.md
+.claude/output-styles
+.claude/routines
+.claude/scheduled_tasks.json
+.claude/settings.local.json
+.claude/workflows
+
# Sandbox artifacts. The harness materialises these as zero-byte read-only
# placeholders in every working directory; none of them are project files.
.bash_profile
diff --git a/AGENTS.md b/AGENTS.md
index 192a1f1..3f06c54 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -80,11 +80,53 @@ The reason is timing rather than ceremony. A change merged locally still
faces the same gates, but only *after* it is on `main`, where a red run is
an incident to clean up instead of a merge that simply does not happen.
-**The review record lives on amadan.** This repo's remote is
-`https://amadan.net/carlos/docs`, so the pull-request equivalent is
-`amadan discuss new carlos/docs -branch <n>` — that discussion is where
-the branch is read as one piece and where approval is recorded. CI is
-`.amadan/ci.d/`, triggered by a push to the remote.
+**The review record lives on amadan.** The pull-request equivalent is a
+branch discussion — see below. CI is `.amadan/ci.d/`, triggered by a push
+to the remote.
+
+## Working through amadan
+
+This repo is hosted on an amadan hub (`AMADAN_HUB=https://amadan.net`),
+not GitHub. There is no `gh`, no pull request, and no GitHub Actions. The
+full house rules are installed as a skill at
+`.claude/skills/amadan/SKILL.md` — read it. What follows is what this repo
+does with them.
+
+**Post as the agent account, never as Paul.** An agent account is
+`<name>~<operator keymail>`; everything it writes is badged and
+attributable. The CLI detects a harness and refuses a human credential.
+`-as-human` exists for a person genuinely typing, and it warns every time
+— an agent reaching for it is the antipattern the badge exists to prevent.
+
+**The prompt ledger is on, at `prompts` level.** `amadan ledger init` has
+installed the post-commit hook, the Claude Code hooks in
+`.claude/settings.json`, and the ledger refspecs, so prompts record to
+`refs/amadan/ledger/<branch>` with nothing to do per commit. Two
+consequences worth knowing:
+
+- **A bare `git push` now pushes HEAD *and* the ledger refs**, because
+ `remote.origin.push` is set and `push.default` no longer applies.
+- **Never edit ledger refs by hand.** `amadan ledger redact` and
+ `amadan ledger withhold` are the only sanctioned removals, and both
+ leave a visible mark. That is the point of them.
+
+**Every branch gets a discussion, and it is the review record.**
+`amadan discuss new <ns>/docs -branch <n>` opens it; that thread is where
+the branch is read as one piece, where the highest-capability-model review
+is posted, and where approval is recorded. One thread per topic — reply on
+it rather than opening a sibling. Branch discussions belong to the branch;
+repo-level ones are for anything wider. Close what you opened.
+
+**Tasks are a checklist, not a log.** `amadan task add -branch <n>` for
+work someone will do, `amadan task advance` when it is done. Commentary
+belongs in the discussion, not in task titles. A branch with real work on
+it should have tasks that a reader can scan to see what is left.
+
+**When something is refused, say so in the discussion rather than working
+around it.** An `agent` grant is writer-equivalent within one namespace:
+push, post, manage tasks, nothing beyond. Refusals are usually a missing
+grant or a genuine boundary, and both are worth surfacing rather than
+routing around.
## Working with the sibling sessions