chitra
chitra is a session monitor for AI coding agents. It watches tmux-hosted
Claude and Codex sessions ("lanes"), enrolls each one against a goal through
a short interview, and doggedly pursues that goal: it delivers corrective
nudges, investigates stuck questions, and only calls a lane done once it has
independently checked the evidence.
Goals
- Reliable. Delivery, queueing, and state tracking are deterministic
code, not model judgment. One process (
dispatchd) owns writing into a session, so two writers can never race and corrupt a lane's next turn. - Persistent. A lane does not get to coast. chitra keeps steering a session toward its enrolled goal, escalating corrective nudges as problems recur, until it can prove completion — a clean-looking pane or an agent's own "done" claim is not enough.
- Autonomous. Where a stuck lane needs a decision, a foreground chitra agent investigates and acts using live tool access, inside limits frozen at enrollment. A human is pulled in only when a permission is missing, expired, or a frozen goal itself needs to change.
Components
The daemon set. Four daemons run as templated systemd instances, one
instance per monitor (for example a monitor named monitor or one named
boomtown), each with its own state root under /var/lib/polyphony-chitra*:
watchd (semantic pane status), triaged (deduplicated state-change
events), dispatchd (the sole process allowed to write into a session), and
sweepd (a compact fleet-state digest). watchd, triaged, and sweepd
are deprecated in favor of the supervisor below; dispatchd stays the sole
terminal writer for both the older set and the newer one.
The supervisor. Added in 0.19.2, monitord is the persistent-goal-pursuit
engine: it binds a transcript to one frozen goal, runs deterministic
detectors for drift and stalling, and pushes findings through a response
ladder that only escalates after a prior nudge has actually landed — not
after time passes. An operator can put a goal on an explicit hold and resume
it later; chitra never silently drops or times out an unfinished goal. See
Persistent supervision.
Interview-based intake. A lane is not enrolled by a free-text
description. chitra-goals set returns four typed interview questions;
answering them, with evidence, freezes a structured set of done items, each
naming its own validator. This is the chitra.goals.v3 schema, and it is
what lets chitra check completion against real receipts instead of an
agent's say-so. See Design notes.
boardd — the fleet board
boardd (0.21.0) is the one Chitra board; an older board published as a
claude.ai Artifact is deprecated. It auto-discovers every monitor instance
on a host — by reading the four daemons' systemd units and by globbing
/var/lib/polyphony-chitra* for a goals.json — so there is no map to keep
in sync as monitors come and go.
The board is a pan/zoom canvas of session cards — one per lane, showing the
goal, the marker, and what the lane is doing right now — with a stack of
red-bordered escalation cards down the right edge. Every lane that needs
an operator decision appears there: any open question, plus lanes in a
disputed-completion, done-pending-verification, unverified-turn, or blocked
state, oldest first. Clicking one opens a panel with the context, the
question, a recommendation, and a box to answer it. Sending an answer writes
back through the existing chitra-goals command-line tool, so boardd never
becomes a second writer of goal state.
The page itself is agenttrail, a vendored open-source UI, run as its own
supervised process and reached only through a same-origin allowlisted proxy
inside boardd — the underlying process is never exposed directly, and its
/spawn route is refused. boardd feeds it from chitra goal state rather
than describing that state in a second dashboard of its own. It also
installs as a mobile web app (add to home screen, offline for the shell
only), where the same escalation stack becomes the full-width review queue.
Deploy: boardd runs as a systemd service bound to 127.0.0.1:8480 and is
reached over the tailnet through Tailscale Serve — never a public listener.
Run it locally:
pip install -e '.[boardd]'
BOARDD_DEV=1 BOARDD_STATE_ROOTS=monitor=tests/fixtures/boardd_state \
uvicorn boardd.app:app --port 8480
BOARDD_DEV=1 swaps real discovery for the fixture state directory checked
into this repo, so it works without a live monitor. See
docs/boardd.md for the full endpoint list and configuration.
Quick start
git clone https://github.com/ReticleWorks/chitra.git
cd chitra
pip install -e '.[test]'
pytest
On macOS, some tests open a Unix domain socket, and macOS caps that socket's path length well below Linux's. pytest's default temp directory is often too deep, so run tests with a short base path instead:
pytest --basetemp=/tmp/ct -q
To try boardd against the fixture state, see the boardd section above. For running the daemons themselves against a real lane, start at docs/daemons/README.md.
Release
The version lives in one place, pyproject.toml. Cutting a release:
- Bump the version in
pyproject.tomland add aCHANGELOG.mdentry. - Tag the commit
vX.Y.Zand publish a GitHub Release from that tag — publishing the Release is the human gate; nothing builds or ships before it. - The
publish.ymlworkflow then builds and uploads to PyPI. That workflow is currently blocked by an organization-wide setting that disables GitHub Actions, so until that is lifted, publish by hand from the tag instead:python -m build && twine upload dist/*. - A release notifies the fleet repository, which opens its own pull request
to bump the pinned
chitra-monitorversion for deployed hosts.
Documentation
Start at docs/README.md, or jump straight to Getting started, Concepts, or Persistent supervision.
Getting help
Questions and bug reports: open an issue. See CONTRIBUTING.md before opening a nontrivial PR; security reports go through SECURITY.md.
License
MIT © 2026 Reticle Works. See LICENSE for the full text.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file chitra_monitor-0.21.1.tar.gz.
File metadata
- Download URL: chitra_monitor-0.21.1.tar.gz
- Upload date:
- Size: 917.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3aaecbc9486bc61b4bebe9d9eb55047cdb83098598084b702be453c0dbe06383
|
|
| MD5 |
a7065cf0938625cc10d349026d6366ad
|
|
| BLAKE2b-256 |
3732d8643db5e81486d85f8d897e6c419e41765a4a76d956e156345597fe2218
|
File details
Details for the file chitra_monitor-0.21.1-py3-none-any.whl.
File metadata
- Download URL: chitra_monitor-0.21.1-py3-none-any.whl
- Upload date:
- Size: 612.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2b5a84c524cb1b065f5923da9c4232a9a7f5ea3a00105b4dd618c181b6c9ffed
|
|
| MD5 |
2edd7fa0aa7ffaa35d54a189c8cc3c46
|
|
| BLAKE2b-256 |
0760de5e93603733ee4cbb4c35a166db9cecd48a79fff171ab05bb9517033a7b
|