Metadata-Version: 2.5
Name: adrs4ai-pneumatic
Version: 0.4.0
Summary: Cross-vendor AI-crew session tooling: read messages, classify seat health, wake/launch seats across tmux — extensible via hooks, not forks.
Project-URL: Homepage, https://github.com/ADRs4AI/pneumatic
Project-URL: Repository, https://github.com/ADRs4AI/pneumatic
Project-URL: Design record, https://github.com/ADRs4AI/pneumatic/blob/main/docs/adr/0001-pneumatic-hooks-extension-without-forking.md
Author-email: Jérémie Lumbroso <lumbroso@seas.upenn.edu>
License: MIT
License-File: LICENSE
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: POSIX
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Build Tools
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: click>=8.1
Requires-Dist: pluggy>=1.0
Requires-Dist: rich>=13.0
Requires-Dist: structlog>=24.0
Provides-Extra: dev
Requires-Dist: mypy>=1.8; extra == 'dev'
Requires-Dist: pytest-cov>=4.0; extra == 'dev'
Requires-Dist: pytest>=7.0; extra == 'dev'
Requires-Dist: typing-extensions>=4.0; (python_version < '3.11') and extra == 'dev'
Description-Content-Type: text/markdown

# pneumatic

Cross-vendor AI-crew session tooling: read recent messages from an agent's session, classify seat health (stale / error / credits-wall / permission-stall / …), wake and launch seats across tmux — for crews of AI agents (Claude Code, Codex CLI, and others) coordinating on a shared project via [ADRs, seeds, and the inbox protocol](https://github.com/ADRs4AI/human-ai-collaboration-template-A).

**Status**: real and installable, today, from source — `0.1.0`, MIT-licensed, 47 tests and `mypy --strict` clean, both run in CI on every push. The PyPI distribution name will be **`adrs4ai-pneumatic`** (the bare name belongs to someone else; import and CLI stay `pneumatic`) — **not yet published to PyPI**, deliberately: that's its own open decision. Design record: [ADR-0001](docs/adr/0001-pneumatic-hooks-extension-without-forking.md), eight iterations deep, all seven design questions answered (the last, a narrow `message_filter` hook for `cmd_last`'s message-selection step, designed and awaiting implementation). Lineage: HQ's [ADR-0015](https://github.com/ADRs4AI/initial-meta-repository/blob/main/docs/adr/0015-cross-vendor-seat-support-harness-abstraction-and-modularization-backdoor.md).

## Install

```bash
git clone https://github.com/ADRs4AI/pneumatic
cd pneumatic
pip install -e .          # editable install; CLI entry point included
```

A `python -m build --wheel` + clean-venv install has been verified working end to end. When the PyPI decision lands: `pip install adrs4ai-pneumatic`.

## What it does, in six commands

| Command | What you get |
|---|---|
| `pneumatic pulse` | One-line health check across every registered seat — stale, error, credits-wall, permission-stall, all detected |
| `pneumatic last <seat>` | A seat's recent messages, **with per-message model attribution** — catches silent model substitutions |
| `pneumatic wake <seat> -m "..."` | Nudge a seat's tmux session (guards included: mid-turn refusal, cooldown — they warn, never hard-block) |
| `pneumatic launch <seat>` | Start a seat's session from the registry |
| `pneumatic rescue <seat>` | Free a seat stuck on a permission dialog — per-instance human consent, never automatic approval |
| `pneumatic doctor` | Hook discovery and load diagnostics |
| `pneumatic hooks inventory` | Machine-readable JSON of which hooks a project implements — for fleet-wide visibility tooling |

Every action takes a verb — `click`-based subcommands as of 0.2 (ADR-0003; the pre-0.2 flag surface was hard-cut at adoption-zero, and recognized old flags print a signpost naming the new form). A bare seat name gets a *teaching* error, not silent sugar.

## Hooks are the point, not a feature

Anything pneumatic's core does that you'd otherwise fork the source to change, you do instead in a local **`hooks.py`** — a file you write and own, that survives every upgrade. Dispatch is via [pluggy](https://pluggy.readthedocs.io/) (pytest's own plugin engine), and pneumatic's **own built-in behavior registers through the identical call path** — there is no separate hardcoded version to drift away from what's hookable. Nine named hooks across three dispatch shapes (additive, override-with-fallback, collecting-with-context). Start at **[HOOKS.md](HOOKS.md)** for the authoring reference; [ADR-0001](docs/adr/0001-pneumatic-hooks-extension-without-forking.md) for why it's built this way.

## Why this exists

`git blame` doesn't tell you which AI session touched a file. A crew of AI agents working the same project needs a way to check on each other — is a seat still active, stuck on a permission dialog, out of credits, mid-turn? — without a human relaying status by hand.

It started as a single script inside one project. By the time this repo was created, a sweep of one machine's `~/Programming` found **33 independent, hand-copied forks** of that script across unrelated projects — 319 to 1,992 lines each, almost none byte-identical. Forking was the only way to customize it, so every local need cost the fork its entire connection to upstream. This package is the fix: real package, hookable, instead of fork-to-customize.

## Design principle

*"This is a blank canvas. We are scaffolding all the obvious stuff we could think about, but you're probably going to extend this in wonderful ways that will never be deprecated through our updates. We want to empower people to create their own version of pneumatic while still benefiting from our updates."*

## Honest state of play

- **Adoption is zero so far** — the 33-fork sweep classified 16 of 23 forked projects as pure-adoption candidates and 7 as needing real hook-writing, and none has migrated yet, including this tool's own origin project. The fix exists; its first migration is the next proof.
- **Stability contract covers the hook contract only.** Anything you import directly from the package (`classify_seat`, `resolve_jsonl`, …) has no stability promise yet — that contract is explicitly deferred, on record.

## Methodology

This repo is scaffolded from [`human-ai-collaboration-template-A`](https://github.com/ADRs4AI/human-ai-collaboration-template-A) — decisions are committed to ADRs (`docs/adr/`) immediately, not left to live only in conversation. See `CLAUDE.md` and `docs/METHODOLOGY.md` for the full framework.

---

Feedback: lumbroso@seas.upenn.edu
