Set up in ten minutes
For the person who owns the repository. It needs Python 3.9 or newer; a git repository needs git installed. On Subversion it runs without git installed, from the release archive, and each run says what it cannot verify there: commit signatures and server-authenticated authors.
1. Put the tool in the repository
git clone --branch v0.20.0 https://github.com/shoalmark/shoalmark ~/shoalmark # a release: the one this page ships with, a clean clone
cd <your repository>
python3 ~/shoalmark/shoalmark.py --vendor tools/shoalmark
tools/shoalmark/ is now a pinned copy: eight files and a PIN of their hashes, whose first line says which release
it came from. --vendor copies only a release, the whole tool at its tag with a clean tree, and refuses anything else
without writing a file. It never updates itself; you vendor again from a newer tag, and it prints what changed. On
Windows the command is python, not python3.
2. Initialise
python3 tools/shoalmark/shoalmark.py --init --key AP
AP is your id prefix — work items become AP-001, AP-002 … Choose something short that names the project, not a
kind of work. This writes shoalmark.toml, docs/work-tracker/TRIAGE.md, the agents' contract into AGENTS.md, and
a CLAUDE.md router. Nothing is overwritten.
In German? Copy the four files from examples/de/ first — shoalmark.toml (section names in German),
TEMPLATE.md, TRIAGE.md, brand/labels.yaml — and the board and every new work item come out German.
3. Wire the gate
python3 tools/shoalmark/shoalmark.py --install-hook
- git: plain hooks — the index is regenerated and checked on every commit; a work item that contradicts itself is refused.
- Subversion: the TortoiseSVN hook properties and
svn:ignorefor the board. Subversion's command line runs no client-side hook, so the contract tells agents to run the tool beforesvn commit.--checkafter the commit is what judges it.
4. Say who answers — and who the agents are
In shoalmark.toml:
``` owner = "[email protected] signed" # you, the Owner — not a seat: your answers are signed commits, see "Your answer is your commit"
[seats] planner = "planner@seat" # the agents' seats, one identity each builder = "builder@seat" reviewer = "reviewer@seat" ```
owner goes at the top of the file, before any table: a line written below a table header belongs to that table, and the
tool refuses it in any table but [seats], where owner still reads as the old spelling. Under Subversion the
Owner is your server account, without signed: the server authenticates you already. Each seat
commits under its own identity, set once in its own worktree (git config --worktree user.email builder@seat),
and holds only its own rights: the Owner answers; the planner asks, closes and triages; the reviewer triages; the
builder builds. The seats are planner and builder; principal and implementer, their former names, still read and hold the same. The older answerers = ["yourname"] still reads where there is no owner and no [seats]. A signed identity is an email address, verified by SSH (see "Your answer is your commit"); any other is refused when the configuration is read.
Sessions. Beside its seat, every agent's worktree carries seat.session, the run it belongs to, and the hook that
--install-hook wrote adds it to every commit as Session: <id>, with the worktree beside it. The gate refuses a
seat's commit without a session of its own seat; --sessions prints who ran what, where and when from those lines
alone, and the board lists who was at work in the last day. Your agents do this. Your own commits carry no session:
your signature is your id.
5. Write two things only you can
Open docs/work-tracker/TRIAGE.md. The intent — for · so that · never, in your words — and the current path:
what comes first. Agents read both before every judgement. Leave everything else to them.
6. Open the board
docs/work-tracker/index.html — it is git-ignored and rebuilt when the tool runs, on a commit that changes a work item, and
right after each of your answers and acts; on Subversion, on a commit through TortoiseSVN or when the tool runs. Nothing
rebuilds it after a checkout, a merge or an update: --html-only does. Its first line is what needs you. Set standup = "09:00" in shoalmark.toml for the time of your one sitting: see
The standup.
That is all. The agents file the work; you answer what only you can.
These pages, built with zensical build: open site/index.html directly for reading and links; search needs the served site: python3 -m http.server -d site 8000.