Skip to main content

chitra

License: MIT Python 3.12+ PyPI

chitra persistently supervises tmux-hosted AI-agent sessions against exact frozen goals. It records transcript evidence, detects drift and stalls, publishes crash-safe corrective orders, investigates unresolved routine questions, and independently verifies completion. dispatchd remains the sole terminal writer.

It was built to manage large parallel sessions with LLM coding agents, allowing the user to do more while chitra handles delivery and state tracking, applies optional LLM-backed judgment gates, and keeps Claude and Codex sessions pursuing clearly defined goals. See Persistent supervision for the lane lifecycle and recovery contract.

Scope

chitra delivers messages to LLM-driven sessions in tmux and observes their state. Delivery, queueing, routing, rate limiting, ledger writes, and state tracking are deterministic; routing is config lookup, not content judgment.

LLM judgment is layered on deliberately for specific gates: goal nudging, completion-claim review, and interview functionality. Chitra also dispatches to and gates external coding-agent harnesses such as Claude via claude-code and Codex; those agents do the content work, while chitra records, routes, reviews, and releases according to its own ledgers and policies.

Quickstart

pip install chitra-monitor  # or: pip install git+https://github.com/ReticleWorks/chitra.git@<tag>

Replace <tag> with a released version from the tags page, or drop @<tag> to install from the default branch.

Requires Python 3.12+ and tmux on the host. See Install for local development setup, Configuration for environment variables, and Delivering into a tmux pane for what chitra actually does to a pane.

Why "chitra"

The name is a short form of Chitragupta, a figure from Hindu tradition described as the divine registrar and keeper of a complete, accurate ledger of deeds. That remains this package's contract: it observes, verifies against frozen goals and cited artifacts, and takes goal-scoped supervisory action without silently changing the frozen goal or its autonomy policy. The name is used respectfully as a functional reference, not as religious imagery.

BrowserStack's chitragupta-node and chitragupta-rails are open-source SDKs that use the same name for structured JSON (JavaScript Object Notation) logging — attaching metadata to log lines rather than relaying or signing them. Different tool, same naming logic: the name attaches to something that records and structures what happened, not something that decides what should happen.

What's in this repo

chitra installs command-line entrypoints backed by small, single-purpose modules. monitord and dispatchd are the current always-on daemons. watchd, triaged, and sweepd remain available for older deployments but are deprecated.

Delivery

  • chitra.dispatch / chitra.dispatchd — drain a JSON order queue and deliver each message into a tmux session via bracketed paste, confirming delivery by grepping the session's own transcript. One writer per session (LaneLock); idempotent and crash-safe (see Delivery guarantees).
  • chitra.ledger — an append-only, HMAC-signed log of every delivered message.

Monitoring

  • chitra.monitord / chitra.supervisor / chitra.supervision — bind transcripts to exact goals, persist corrective actions across restart, investigate unresolved routine questions, pursue successive actions, prove delivery consumption, and continue until enrolled completion evidence verifies.
  • chitra.watchd — derives semantic pane status from authoritative lifecycle reports or declarative screen manifests, serves the local coordination socket, and runs a completion audit on each finished turn.
  • chitra.triaged / chitra.sweepd — deduplicated state-change events and a compact fleet-state feed for downstream monitors.
  • chitra.draft_scanner — flags unsubmitted drafts left sitting in a tmux input box.
  • chitra.agent_cli (chitra-agent) — reports lifecycle state, explains status evidence, waits for semantic state, and prints the socket API schema.

PR review

  • chitra.pr_review / chitra.pr_reviewd (chitra-pr-review) — deterministic blast-radius/diff-size pre-checks plus an isolated multi-reviewer security pass over one pull request's diff, logged to a signed ledger and reported as a plain PR comment. Never merges, approves, requests changes, or fails a required check by default; see the pr_reviewd module docstring and PRReviewPolicy.block_on_findings. Stock trigger: .github/workflows/pr-security-review.yml.

Goals and completion

  • chitra.goals — a per-lane goal store with atomic interview enrollment and frozen structured done items, guarded by flock.
  • chitra.goal_enforcement / chitra.completion_gate / chitra.close_gate — require exact named, validator-bearing receipts for every frozen done item; each goal also freezes an AutonomyPolicy with typed grants and limits for pursuit.

Rate limiting

  • chitra.usage / chitra.rate_limit_guard / chitra.account_registry — read account usage and pause/resume lanes on provider limits or host load pressure, over a durable, crash-safe transaction. See docs/pause-recovery.md.

Rendering

  • chitra.board / chitra.convlog — a terminal roster of goals and open asks, and an append-only operator-brief conversation log.

Other shipped modules

  • chitra.artifacts, chitra.capabilities, chitra.goals_cli, and chitra.replay_eval — operator tools for artifact state, capability control, goals, and replay checks.
  • chitra.ownership, chitra.ownership_provider, and chitra.petra — read-only ownership lookup, a fail-closed provider, and an observe-only pressure authority.
  • chitra._fsio, chitra.board_updater, chitra.lane_activity, chitra.lane_read, chitra.lexicon, chitra.load_shed, chitra.orders, chitra.outcomes, and chitra.rate_limit_state — shared queue, state, lane, and load-shed primitives.
  • chitra.policy_config, chitra.reasoned_dispatch, chitra.reasoning, chitra.recovery, chitra.routing_config, chitra.state_paths, and chitra.taxonomy — policy, reasoning, recovery, routing, state-path, and taxonomy primitives.

Delivering into a tmux pane

Delivery into a live tmux session follows one path:

  1. tmux display-message -p -t <target> '#{pane_in_mode}' — if 1, the pane is in copy-mode (which silently swallows input); run tmux send-keys -X cancel and wait briefly.
  2. printf '%s' "$text" | tmux load-buffer -b <name> -
  3. tmux paste-buffer -p -b <name> -t <target> — the -p flag is mandatory; without it, newlines act as Enter keypresses and the message can self-submit early.
  4. tmux send-keys -t <target> Enter
  5. Confirm delivery by grepping the target session's transcript for the delivered text. "Looks sent" is not evidence.

For a remote target, each command is the same, ssh-wrapped to run on the actual target host. Checking the local tmux server's state, or grepping local transcripts, when the target is remote reports on the wrong host.

Delivery guarantees

  • Single writer. dispatchd holds a LaneLock per session id across each delivery, so two writers can't race to paste into the same session and corrupt its next turn.
  • Idempotent. Once a ledger-proven result file exists for an order, it is never redispatched, even across a restart. A crash between paste and result is reconciled with a send-nonce marker plus the exact bound-transcript check, not a blind second paste. A pre-existing SENT result cannot create its own proof.
  • Authenticated. Every successful delivery appends an HMAC-SHA256-signed record to an append-only JSONL ledger; a reader with the signing key can prove a given message was delivered. Append-only behavior is a convention backed by file permissions, not a hash chain or counter, so a reader cannot detect ledger truncation or edits. Under the trusted-host assumption, "not in the ledger" suggests no chitra delivery; it is not proof of non-delivery. See chitra.ledger.verify_delivery.

Running the daemons

Trailhead installs one chitra Debian package built with fpm. The package contains one released application virtual environment at /opt/chitra/venv, the service account, and five core systemd unit files: four shared daemons and the chitra@.service session-anchor template. Build it with CHITRA_VENV_SOURCE=/path/to/released-venv packaging/build-deb.sh 0.9.4 /path/to/chitra.deb.

The package daemons read /etc/chitra/lanes.yaml. Each declaration supplies the lane identity, account, roots, tmux socket and credential bindings. The declaration has no model field. chitra-lane-anchor selects the backend and model at launch. It supports Claude, Codex, and OpenCode models such as opencode/x-preview-f-free. It refuses unless the Tophand lane has a passing goal-ingestion record and no active usage pause. See docs/governed-tmux-lanes.md.

At launch, each governed Claude or Codex lane receives instructions to maintain one AgentTrail-compatible PLAN.md in its declared worktree. The plan records stable task IDs, dependencies, file scopes, intermediate status, and completion evidence. It is a shared progress view; Chitra's frozen goal and verified receipts remain authoritative. The governed-lane guide defines the exact format and update rules.

Provider routing remains upstream of Chitra. oss-step task metadata selects OpenRouter through Crush, the anonymous OpenCode free route, or authenticated OpenCode Zen. Chitra receives only the allowlisted executable backend and passes one provider/model value as one argument. It never accepts a free-form shell command or stores a provider secret in the lane manifest.

Watchd also owns a mode-0600, newline-delimited JSON socket at /run/chitra/chitra.sock. Supervised agents receive their lane, session, tmux-pane, target, and socket identity as CHITRA_* variables. A replacement Watchd process can use --handoff-from /run/chitra/chitra.sock to transfer verified semantic state and socket ownership without restarting the tmux pane processes. See the agent-status design and the status migration guide.

The host role enables the shared units once. Adding a lane uses one command:

sudo systemctl enable --now chitra@<lane>.service

chitra-rate-limit-guard remains a one-shot CLI meant to run on a timer. Example timer units live under packaging/systemd/:

sudo cp packaging/systemd/chitra-rate-limit-guard.service.example /etc/systemd/system/chitra-rate-limit-guard.service
sudo cp packaging/systemd/chitra-rate-limit-guard.timer.example /etc/systemd/system/chitra-rate-limit-guard.timer
sudoedit /etc/systemd/system/chitra-rate-limit-guard.service   # fill in placeholders
sudo systemctl daemon-reload
sudo systemctl enable --now chitra-rate-limit-guard.timer

Configuration

Each entrypoint is configured with CLI flags (--help on any command lists them) and a small set of environment variables. The most common:

Env var Default Notes
CHITRA_LANES_FILE /etc/chitra/lanes.yaml One rendered lane declaration read by the shared daemons.
CHITRA_STATE_DIR /var/lib/chitra Base directory for the queue, ledger, and ledger key
CHITRA_SOCKET_PATH /run/chitra/chitra.sock Local semantic-status, subscription, wait, and handoff socket.
CHITRA_AGENT_MANIFEST_DIR ${XDG_CONFIG_HOME:-~/.config}/chitra/agent-detection Local agent-detection manifests; a local file replaces the bundled file for that agent.
REMOTE_DISPATCH_HOSTS (empty) Comma-separated allowlist of hosts dispatch may target over ssh
CHITRA_CLAUDE_PROJECTS ~/.claude/projects Root, or os.pathsep-separated list of roots, searched locally for transcript-grep delivery verification. List more than one root when a local session runs under a non-default CLAUDE_CONFIG_DIR (e.g. a dedicated persona/harness identity) — its transcripts live under that root's projects/, not the default
CHITRA_ROUTING_CONFIG (unset) Optional task_type → routing-hint config; see docs/routing.yaml.example
CHITRA_POLICY_CONFIG (unset) Optional completion-gate and dispatch policy; see docs/policy.yaml.example
CHITRA_SHARED_DIR /var/lib/polyphony-chitra-coordination Shared advisory presence and peer inbox root.

The full set — ssh options, triage log paths, transcript globs — is documented per-command via --help.

chitra-presence using <instance> <resource> appends to that instance's own presence file and prints peers already using the same resource. It never waits, claims, expires, steals, or grants authority. Use released to append an explicit release and list to merge all instance files. chitra-peer say <instance> <text> enqueues a real dispatch order for the named peer's session so dispatchd delivers it with its own verification receipts; chitra-peer inbox reads a non-authoritative mirror of what was asked, never proof that it arrived.

Routing. A caller can tag a DispatchOrder with an opaque task_type. If a routing config is set, dispatchd maps that to a routing_hint (a model/harness preference the caller's system uses); an explicit routing_hint always wins. chitra carries both fields through DispatchResult and, for a successful delivery, the signed ledger; it does not make routing decisions beyond the configured lookup.

Install

Requires Python 3.12+ and tmux (chitra shells out to the tmux binary; there is no Python tmux dependency).

pip install chitra-monitor  # or: pip install git+https://github.com/ReticleWorks/chitra.git@<tag>

chitra-monitor is published on PyPI and the recommended installation method.

For local development:

git clone https://github.com/ReticleWorks/chitra.git
cd chitra
pip install -e '.[test]'
pytest

Documentation

For comprehensive guides, API reference, and daemon documentation, see the docs/. Start with Getting Started for install and first dispatch, Concepts for the architecture, or Semantic agent status for lifecycle reports, manifests, waits, and live handoff.

Getting help

Questions and bug reports: open an issue. See CONTRIBUTING.md before opening a nontrivial PR; security reports go through SECURITY.md.

Authors

Trey (Reticle Works) with Claude and Codex.

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

chitra_monitor-0.19.2.tar.gz (805.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

chitra_monitor-0.19.2-py3-none-any.whl (519.9 kB view details)

Uploaded Python 3

File details

Details for the file chitra_monitor-0.19.2.tar.gz.

File metadata

  • Download URL: chitra_monitor-0.19.2.tar.gz
  • Upload date:
  • Size: 805.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for chitra_monitor-0.19.2.tar.gz
Algorithm Hash digest
SHA256 f05840e3a9de7e7c24205f8879c20452726b19f9f5fa6a053a696bea8a721c2c
MD5 99d19abee0d03ce65334faacd6f40051
BLAKE2b-256 a6187a33fe2b3e791ed11b2672da3654e4a588edf90c072137bd475bd69448a8

See more details on using hashes here.

File details

Details for the file chitra_monitor-0.19.2-py3-none-any.whl.

File metadata

  • Download URL: chitra_monitor-0.19.2-py3-none-any.whl
  • Upload date:
  • Size: 519.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for chitra_monitor-0.19.2-py3-none-any.whl
Algorithm Hash digest
SHA256 25cf04d962a16b87989b1d8f566189298ed60eadc3cc206a492d8f0b895ffebe
MD5 7e476b2c289f746da85e2a4d74938090
BLAKE2b-256 3a86683bb102299e676b688c483475d47a9dab810cb11b752a327efdd6e78329

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.19.2 This release

2 files

0.19.1

2 files

0.19.0

2 files

0.17.0

2 files

0.15.0

2 files

0.14.8

2 files

0.12.2

2 files

0.12.1

2 files

0.11.0

2 files

0.10.2

2 files

0.10.1

2 files

0.10.0

2 files

0.9.11

2 files

0.9.10

2 files

0.9.9

2 files

0.9.8

2 files

0.9.7

2 files

0.9.6

2 files

0.9.5

2 files

0.9.4

2 files

0.9.3

2 files

0.9.2

2 files

0.9.1

2 files

0.9.0

2 files

0.8.2.8

2 files

0.8.2.7

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page