x‑hakt

x’s locker / bosun-x

a tool you install — not one that runs here

bosun‑x

Cross-agent handoff and task tracking for a set of projects you build with AI. The bosun is the hand who keeps the ship and crew in working order; bosun‑x does that for your projects — a record of what’s actually done, a clean starting point for the next session, and a task board that can’t drift.

A command-line tool and an MCP server over the same plain files. MIT.

the problem

If you build software with an AI assistant across more than one project, you know the tax. Every session starts cold — you re-explain what the project is, what’s done, what you were mid-way through, what not to touch. The record drifts: the assistant thinks a task is finished, the code says otherwise. Two assistants in two windows edit the same project, neither aware of the other. A session hits its limit mid-task and the next one has to guess what was already decided.

bosun‑x is the small amount of structure that fixes this — with no database, no web app, and no subscription. If you have one project and one assistant, you probably don’t need it. It earns its place once picking work back up has started to hurt.

how it works

When you start work, you open a handoff. As you go, you checkpoint what’s verified done, where things stand, and the one next action. Two files get written: an append-only log of everything, and a small fixed-size snapshot. The next session reads only the snapshot.

session one checkpoint HANDOFF.md every entry, kept forever HANDOFF.yml latest state, in full + a trail of the last 4 resume session two reads this, nothing else
A checkpoint writes both files. Resume reads only the bounded snapshot — the current state plus a trail of the last four one-liners, so a hasty checkpoint can’t erase the trajectory.

Writes go through one command that holds a per-project lock, so two assistants working the same project take turns instead of clobbering each other — and a checkpoint from the wrong one is rejected outright.

Claude Codex wrong turn → rejected bosun holds the lock the project’s files HANDOFF · tasks · STATUS plain YAML and Markdown
One writer at a time. A checkpoint from an assistant that doesn’t hold the current turn is refused, not merged.

the dashboard

On its own, bosun‑x is a CLI and an MCP server — the engine that keeps the log honest. The dashboard is the web application built on the same plain files: every project’s containers read live off the Docker socket, standards checked rather than claimed, the spec and handoff rendered and editable, the planning lifecycle, backup jobs watched for a missed run with a guided restore and a weekly restore-test for each store, whole servers across a fleet. The CLI is the discipline; the dashboard is where you look at all of it at once.

It’s fully responsive too — the sidebar folds behind a hamburger into an off-canvas drawer on a phone-width screen instead of a permanent desktop-only rail, so jotting a new idea down or checking a task doesn’t have to wait until you’re back at a desk.

The dashboard detail page for a demo project, showing its tasks, active handoff, and project documents.
One project’s page: the task board, the active handoff with a staleness clock, the linked spec and docs. The same plain files underneath. (Click to enlarge — this is a demo project.)

You point it at your own setup from a Settings page — timezone, who can sign in, which machines it watches, where your projects live. Every field has a default and an explanation; nothing is baked into the code.

The dashboard Settings page with the timezone field open, showing a filtered list of IANA zone names, plus the operators, host id and project-folder fields.
Settings: each option with its help text, the resolved value, and the default when it’s left blank — like the timezone picker here. Backed by one config.yml in the data folder, or run `bosun setup` in a terminal to write it. (Click to enlarge.)

The dashboard is open source too — github.com/x-hakt/bosun-x-dashboard. Same shape: plain files, nothing stored, self‑hosted behind your own auth. Clone it, point a docker compose at your data folder, done. It uses the CLI above as a dependency.

the client portal

bosun‑x is built for one pair of eyes — one operator who sees every project, every server, every note. The client portal is how someone you’re building for gets a window into their own work without seeing anyone else’s. It’s the same image deployed a second time with BOSUN_MODE=portal, themed as the client’s own brand, serving a per-client projection of the same plain files.

Nothing is shared by default. A project — or a planning idea — reaches a client only when it passes two gates, and every client-facing page reads through a single function that a lint rule forces it to use.

a project gate 1 portals: [acme] gate 2 shared_with: [bob] projection whitelist only → bob’s portal fail either → withheld, title and all
Both gates default closed. What the portal returns is built field-by-field from a whitelist in one function — host, path, repo, handoff logs and backups have no way through, and a build rule fails if any other portal file reads the store directly.

Sharing is granular. A shared project shows its status and its tech tags, but every task stays invisible — title and all — until you flag it for that client, and a project can default to sharing all of its tasks or none. Links are opt-in one at a time, so a monitoring URL on the same project stays operator-only. A PORTAL.md in the project folder gives the client a summary in your words in place of the generated one.

The client portal project page for a demo 'recipes-api' project, showing a summary, two shared tasks, a conversation thread with the client's own reply highlighted, and Post reply / Approve sign-off buttons.
One client's view of one shared project, themed as the studio's own brand: the plain-English summary, only the tasks flagged for them, and each task's thread with a reply box and a one-click sign-off. (Click to enlarge — this is the fictional demo data.)

It isn’t read-only. A client can reply into any idea or task thread you’ve shared and post a one-click approve / sign‑off; their replies land back on your side flagged — an amber card in the thread, a “new” badge on the board, a tile on the overview. Separately, every client gets one always-on direct message thread with you, unread badges both ways. The portal home greets a returning client with what moved since their last visit.

You drive all of it from Settings → Client portals: register a portal and the people in it, then preview the exact projection any one client receives — down to a list of what’s sitting in their portal that you haven’t shared yet. The build story is in Two gates and a fence; the setup reference is docs/portal.md in the dashboard repo.

if you don’t write code

Plenty of people build real apps now without writing the code themselves — they describe what they want and an AI assistant does the typing. If that’s you, bosun‑x is still for you, and you don’t run any of the commands on this page yourself.

You point your assistant at it once:

“Set up bosun‑x for this project — the repo is github.com/x-hakt/bosun-x. From now on, checkpoint your progress as you work, and when I say resume, pick up from the last checkpoint.”

After that, the difference is: you stop re-explaining your project every time you sit down. You open a session and say “resume the pricing page,” and the assistant already knows the three-tier layout is done, the toggle is half-built, and the next job is wiring the prices — because the last session wrote that down in a form the next one can read. You can also ask “what’s the state of everything?” and get a straight list across all your projects.

It’s a folder of plain text files in your project. Nothing is uploaded anywhere, nothing runs in the background, and you can open any of it in a normal text editor if you ever want to look.

get it

Node 20 or newer. Once it’s published to npm:

npm i -g bosun-x          # or run it ad-hoc with: npx bosun-x <command>

Until then, from source:

git clone https://github.com/x-hakt/bosun-x
cd bosun-x && npm install && npm link

Run bosun from the directory that holds your project data, or point $BOSUN_DATA at it. Projects live in <data>/projects/<slug>/.

configure

$BOSUN_DATAwhere the projects live (default: the current directory)
$BOSUN_TZtimezone for timestamps (default: the system zone). Or timezone in config.yml in the data folder.
$BOSUN_STALE_MINUTESwhen an open handoff is flagged stale (default: 30)

use it

The loop, once per project:

# starting work
bosun start pricing-page --agent Claude --summary "rebuild the pricing page" --task PP-1

# after every verified milestone, at least every 30 min, and before anything risky
bosun checkpoint pricing-page --agent Claude \
  --done "three-tier layout done, responsive to 360px" \
  --state "the annual/monthly toggle is stubbed, no real prices wired" \
  --next "pull prices from config and wire the toggle" \
  --task PP-2 --tests "visual check at 360/768/1200: clean"

# before you stop
bosun finish pricing-page --agent Claude --done "..." --state "..." --next "..." --task PP-2

On the next session, before touching anything:

And to see the whole fleet at a glance, or catch anything that’s drifted:

wire an AI to it

1. The convention, in the file your assistant reads. From inside a project:

bosun init

adds a short managed block — the checkpoint discipline in a few lines — to whichever of CLAUDE.md, AGENTS.md, .cursorrules or copilot-instructions.md is already there.

2. The MCP server, so your assistant has real tools instead of shelling out:

{
  "mcpServers": {
    "bosun-x": {
      "command": "bosun-mcp",
      "env": { "BOSUN_DATA": "/abs/path/to/your/data" }
    }
  }
}

Drop that into Claude Code’s .mcp.json, Claude Desktop’s config, or the same field in Cursor / Cline / Zed / Codex. It exposes project_brief (the session-start bundle), list_projects, list_tasks, the handoff verbs, set_task_status and create_task.

3. The skill (Claude Code) — skill/bosun/SKILL.md in the repo teaches the discipline and triggers on “resume”, “checkpoint”, “pick up work on”.

under the hood

One directory per project. Every file is meant to be read and edited by hand as comfortably as by the tool — grep is a first-class client.

projects/pricing-page/ project.yml name, stage, repo, host HANDOFF.md the full log, newest on top HANDOFF.yml the bounded resume snapshot tasks.yml the board: PP-1, PP-2, … STATUS.md your prose + a generated board
projects/<slug>/ — the whole contract. No database, no proprietary format.

Anything an incoming assistant reads has a token budget: the snapshot is bounded, the trail is clipped one-liners, and noisy work-in-progress is collapsed into one clean entry before you finish. The full technical reference — every command, the config, the MCP tool list — is in the README on GitHub.