23 earlier entries · 4 – 19 Aug
Self-hosted issue tracker
A cairn is a stack of stones left on a trail so whoever comes next knows the way. Every task here carries a note for whoever picks it up, human or agent.
Then open http://127.0.0.1:7777. That is the whole install.
All builds & checksums
v0.2.2One file, ~5MBNo runtime, no dependenciesSQLiteFrontend embeddedWorks airgappedApache-2.0
Designed human-first, then agent access is bolted on afterwards as a third-party add-on wrapping the public API. The agent is a robot pretending to be a user: it posts comments, it moves cards, and the schema has no idea it exists. Nothing in the data model distinguishes a decision a person made from a step a process took.
Agent behaviour is in the schema and in the rules. Agents are named actors with their own tokens. Two transitions are reserved for the human and cannot be made by an agent at all — deciding what gets worked on, and deciding something is finished. Everything else an agent does, it does as a first-class user of the same server.
This is the whole idea. One is the note on top of the cairn — small, current, overwritten every time. The other is the trail behind it — append-only, never edited, never deleted.
Need read access to the archive bucket — the 2022 exports are not in the repo.
The importer parses the 2019 format but chokes on the 2021 header row, which added a currency column in the middle rather than at the end. Rewrote the column mapping to be name-based instead of positional.
Get a sample file from the 2022 exports and confirm the header names did not change again before finishing the mapper.
Three fields, one byline, no history. An agent picking the task up reads this and nothing else. So does the human, at a glance, from the board.
23 earlier entries · 4 – 19 Aug
Read the 2019 importer end to end and wrote a fixture from the sample file in testdata.
Fixture parses. The column mapping is positional, which is going to break on any header change.
Ran the mapper against every file in testdata and diffed row counts against the old importer.
Identical for 2019, 41 rows short for 2021 — all of them rows where the currency column is blank.
Looked for the 2022 exports in the repo and in the fixtures directory.
Not there, and not in any branch. They are in the archive bucket, which this machine has no credentials for.
What was tried, what happened, and the status change it came with. Nothing here is ever edited or deleted, so the record of how a task got where it is survives the agent that wrote it.
Register the agent in the web UI, copy the token once, paste it into the
agent's MCP config. Streamable HTTP at /mcp, same server, same
database. The agent never sees the web interface — that is yours.
{
"mcpServers": {
"cairn": {
"type": "http",
"url": "http://127.0.0.1:7777/mcp",
"headers": {
"Authorization": "Bearer cairn_7fJq…3uQg"
}
}
}
}
Queue a task from the backlog, or mark anything done. Those two transitions are the human's, enforced on the server rather than by prompt. You decide what gets worked on and you decide when it is finished.
One file with the frontend inside it. Nothing to install alongside, nothing to point at a database, no runtime to provision.
checksums.txt.linux/amd64 and linux/arm64, built FROM scratch and running as an unprivileged uid.git clone, then Go 1.25+ and Node 24+ and make build && ./cairn.Open the root URL and pick a username and a password. No email, no confirmation step, no account. This is your server — the name you pick is the one that appears next to every task you touch.
There is no reset email and never will be. If you forget it, run
cairn --reset-password on the machine it runs on.
Give it a name — claude, codex — and Cairn
issues a token. It is shown exactly once and stored only as a hash.
Paste it into that agent's MCP config and it starts filing its own
worklog.
This is a closed list, not a roadmap. Every one of them is a deliberate omission, and the tool is smaller and faster because of it.
Ganttcalendar viewsaved viewsdue datesremindersrecurring taskslabelstagsprioritiesestimatessprintscyclesmilestonesattachmentscommentssubtaskstask hierarchydependenciesCalDAVSMTPnotificationstoastsmobile appdesktop appteamsrolesinvitationssharingassignee pickersmentionsactivity feeds
There is one user. There is no one to notify, no one to assign to, and no one to share with.
Use it, fork it, run it inside a company. The whole point is that it is yours once it is on your machine — there is no hosted tier to upsell you to and no telemetry to switch off.
Go on the server, Vue 3 on the frontend, no CSS framework and no icon library — every dependency ends up in the binary and in the supply chain of a security-adjacent self-hosted tool. Read the list above before proposing a feature.