Skip to main content

chitra

License: MIT Python 3.12+ PyPI

chitra is a set of systemd-supervised daemons that deterministically deliver text into tmux-hosted AI-agent sessions, record what happened, and watch their state. Its core dispatch, ledger, rate-limit, and routing paths are Python control loops, not an LLM deciding what to send or where to send it.

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 gates external harnesses such as Claude and Codex against clearly defined goals.

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 — one who records, verifies what is recorded, and reports to the decision-maker, but does not act on that decision-maker's behalf. That remains this package's contract: it observes, verifies against frozen goals and cited artifacts, gates release, and relays without doing an agent session's work for it. 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 twelve command-line entrypoints backed by a set of small, single-purpose modules. dispatchd and triaged are the always-on daemons; the rest are periodic or ad-hoc tools.

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.watchd — emits tmux pane-change and turn-end events 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.

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 a write-once enrolled done-condition, guarded by flock.
  • chitra.goal_enforcement / chitra.completion_gate / chitra.close_gate — review a session's completion claim against its frozen goal and cited evidence; spend, credentials, and irreversible actions stay operator-gated.

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 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 same transcript-grep check, not a blind second paste.
  • 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

dispatchd and triaged run continuously. chitra-rate-limit-guard is a one-shot CLI meant to run on a timer. Example systemd units, with placeholder paths and service user, 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_STATE_DIR /var/lib/chitra Base directory for the queue, ledger, and ledger key
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

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

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, or Concepts to understand chitra's architecture.

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.8.2.8.tar.gz (362.3 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.8.2.8-py3-none-any.whl (234.7 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for chitra_monitor-0.8.2.8.tar.gz
Algorithm Hash digest
SHA256 dd9ba536e31296b90cbbfe02f89f800c063592e47aa7d3a65b9e40fbf515a6bb
MD5 26bd069dd7083f4d2b987b385ba64ad0
BLAKE2b-256 161620795a39ae76c53ca9a6f86322e6d8c4fa73d09a464d1329d6b514c61167

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for chitra_monitor-0.8.2.8-py3-none-any.whl
Algorithm Hash digest
SHA256 3d545c8d7657130c415434cf29915b01203a09fa430d4d6ecdc52c2818a60dce
MD5 b76152b691e68a7ce60e8a7aef5dfac5
BLAKE2b-256 b8befcf5b35c0cdcb493641d63c3ac61323dd8b5378416e751a2f890eace222b

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page