Metadata-Version: 2.4
Name: chitra-monitor
Version: 0.8.2.8
Summary: Deterministic tmux relay/dedup daemons for AI-agent fleet monitoring
Project-URL: Homepage, https://github.com/ReticleWorks/chitra
Project-URL: Repository, https://github.com/ReticleWorks/chitra
Project-URL: Issues, https://github.com/ReticleWorks/chitra/issues
Project-URL: Changelog, https://github.com/ReticleWorks/chitra/blob/main/CHANGELOG.md
Author: Trey Herr
License-Expression: MIT
License-File: LICENSE
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Operating System :: MacOS
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: System :: Monitoring
Requires-Python: >=3.12
Requires-Dist: pydantic<3,>=2.13.4
Requires-Dist: pyyaml<7,>=6.0.3
Requires-Dist: structlog<27,>=26.1.0
Provides-Extra: boardd
Requires-Dist: fastapi<1,>=0.141.1; extra == 'boardd'
Requires-Dist: uvicorn<1,>=0.52.1; extra == 'boardd'
Requires-Dist: watchfiles<2,>=1.2.0; extra == 'boardd'
Provides-Extra: test
Requires-Dist: fastapi<1,>=0.141.1; extra == 'test'
Requires-Dist: httpx<1,>=0.28.1; extra == 'test'
Requires-Dist: mypy<3,>=2.2.0; extra == 'test'
Requires-Dist: pytest-cov>=7.1.0; extra == 'test'
Requires-Dist: pytest<9.2,>=9.1.1; extra == 'test'
Requires-Dist: ruff<0.16,>=0.15.21; extra == 'test'
Requires-Dist: types-pyyaml<7,>=6.0.12.20260518; extra == 'test'
Requires-Dist: uvicorn<1,>=0.52.1; extra == 'test'
Requires-Dist: watchfiles<2,>=1.2.0; extra == 'test'
Description-Content-Type: text/markdown

# chitra

[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE) [![Python 3.12+](https://img.shields.io/badge/python-3.12%2B-blue.svg)]() [![PyPI](https://img.shields.io/pypi/v/chitra-monitor.svg)](https://pypi.org/project/chitra-monitor/)

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

```bash
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](https://github.com/ReticleWorks/chitra/tags), or drop `@<tag>` to install from the default branch.

Requires Python 3.12+ and `tmux` on the host. See [Install](#install) for local development setup, [Configuration](#configuration) for environment variables, and [Delivering into a tmux pane](#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](#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`](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/`](packaging/systemd/):

```bash
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`](docs/routing.yaml.example) |
| `CHITRA_POLICY_CONFIG` | *(unset)* | Optional completion-gate and dispatch policy; see [`docs/policy.yaml.example`](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).

```bash
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:

```bash
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/](docs/README.md). Start with [Getting Started](docs/quickstart/README.md) for install and first dispatch, or [Concepts](docs/concepts/README.md) to understand chitra's architecture.

## Getting help

Questions and bug reports: [open an issue](https://github.com/ReticleWorks/chitra/issues). See [CONTRIBUTING.md](CONTRIBUTING.md) before opening a nontrivial PR; security reports go through [SECURITY.md](SECURITY.md).

## Authors

Trey (Reticle Works) with Claude and Codex.

## License

MIT © 2026 Reticle Works. See [LICENSE](LICENSE) for the full text.
