AGENTS.md · git:20260818.85c8a47 · 2026-08-18 · sha256 c96f44cb59f230bd

AGENTS.md git:20260818.85c8a47A

Immutable. This exact content is served forever at /api/v1/blob/c96f44cb59f230bd.

# autorun Marketplace

`CLAUDE.md` and `GEMINI.md` here are symlinks to this file. Edit `AGENTS.md`.

## 1. Development isolation is MANDATORY

Many harness sessions run on this machine at once and share the live daemon,
`~/.autorun`, and the installed trees (`~/.agents`, `~/.claude`, `~/.codex`,
`~/.gemini`, `~/.qwen`, `~/.pi`, `~/.prime`, `~/.config/opencode`). A live
install or daemon restart reaches all of them; one such install left other
sessions looping and burned ~12% of a week's tokens (2026-08-15).

1. **Every install, uninstall, dry run, status probe, self-check, test, and
   dogfood run happens in a sandbox** (`HOME`/`USERPROFILE`, `AUTORUN_HOME`,
   `AUTORUN_TEST_STATE_DIR` redirected to a short path) or in Docker.
   `pytest` isolates itself via `plugins/autorun/conftest.py`; nothing else does.
   Keeping the sandbox working is part of every change.
2. **NEVER touch the live installation without the user's explicit written
   instruction in the current conversation naming the action**: `autorun
   --install`/`--uninstall`/`--restart-daemon`/`--restart-all-daemons`,
   `claude plugin install|update`, `uv tool install` of autorun, or any hand
   edit, link, or deletion under the live config directories. Your own task
   list, an `/ar:ok` grant for something else, or "to verify the fix" is not
   that instruction. Report what a sandboxed `--install-dry-run` shows instead.
3. **Prove isolation** by snapshotting the live trees before and after; a
   sandboxed hook that says `autorun CLI timed out` usually means the socket
   path is too long.

```bash
SB=/tmp/arsb; mkdir -p "$SB/home" "$SB/ar-home" "$SB/state"
env HOME="$SB/home" USERPROFILE="$SB/home" PI_CODING_AGENT_DIR="$SB/home/.pi/agent" \
    AUTORUN_HOME="$SB/ar-home" AUTORUN_TEST_STATE_DIR="$SB/state" \
    UV_CACHE_DIR="$(uv cache dir)" \
    uv run --project plugins/autorun python -m autorun --install --force
```

Details, Docker recipe, socket-length trap, snapshot recipe:
[`plugins/autorun/docs/RUNTIME_STATE_ISOLATION.md`](plugins/autorun/docs/RUNTIME_STATE_ISOLATION.md);
installer-specific traps: [`plugins/autorun/src/autorun/installer/AGENTS.md`](plugins/autorun/src/autorun/installer/AGENTS.md).

### Operational one-liners

- **Configure an isolated run:** `SB=$(mktemp -d /tmp/arsb.XXXXXX) && mkdir -p "$SB/home" "$SB/ar-home" "$SB/state" "$SB/uv-cache" && env HOME="$SB/home" USERPROFILE="$SB/home" PI_CODING_AGENT_DIR="$SB/home/.pi/agent" AUTORUN_HOME="$SB/ar-home" AUTORUN_TEST_STATE_DIR="$SB/state" UV_CACHE_DIR="$SB/uv-cache"`
- **Launch the checkout CLI:** `uv run --project plugins/autorun python -m autorun --status`; restart only its daemon with `uv run --project plugins/autorun python -m autorun --restart-daemon`.
- **Install a local development CLI:** `uv tool install --force --editable plugins/autorun && autorun --install`; the editable install is for the developer CLI/daemon, not the live hook venv.
- **Install a published release:** `uv tool install --force autorun && autorun --install` (use the git or marketplace commands below when the release is not on PyPI).
- **Repair the live Claude cache after refreshing assets:** `CACHE="$HOME/.claude/plugins/cache/autorun/ar/1.0.0rc1" && uv run --project plugins/autorun python -m autorun --install --force && uv venv --clear --python 3.13 "$CACHE/.venv" && uv pip install --python "$CACHE/.venv/bin/python" --reinstall "$PWD/plugins/autorun" && uv run --project plugins/autorun python -m autorun --restart-daemon`. Use this only after explicit current-turn approval; refresh first, repair the cache venv second, and restart last.
- **Cache invariant:** the hook interpreter must import from `"$CACHE/.venv/lib/python*/site-packages"`; install it with `uv pip install --python "$CACHE/.venv/bin/python" --reinstall ...`, never `--editable`, so checkout edits cannot change the live hook between repairs.

## 2. Rules that hold everywhere

- Tests set `AUTORUN_HOME` and `AUTORUN_TEST_STATE_DIR` before any autorun
  import; they never touch the live daemon socket, PID, locks, logs, or history.
- Hook code never prints outside CLI entry points: stdout is the hook response,
  and any stderr disables every hook. Log via `logging_utils.get_logger()`.
- Daemon paths use `EventContext.state_get/state_set/state_update`; wrap
  legacy persistence in `state_synchronize`.
- Never hide persistent-state I/O or lock failures by raising hook timeouts,
  and never weaken a concurrency, protocol, or isolation assertion to make a
  test pass.
- Commits follow `plugins/autorun/skills/commit/SKILL.md` (`<files>:` or
  `type(scope):` subject; previous behavior, exact changes, why, verification).
  Read the full staged diff before every commit.

## 3. What is here

UV workspace with two harness plugins: **autorun** (`/ar:` — autonomous
execution with three-stage verification, file policies, safety guards, task
tracking, plan export) and **pdf-extractor** (`/pdf-extractor:extract`,
`extract-pdfs`). `gemini` in code and docs means the Qwen Code / Antigravity
family; standalone Gemini CLI is retired but installable with `--gemini`.

| Path | What |
|------|------|
| `plugins/autorun/src/autorun/` | Package: `config.py` (all CONFIG), `__main__.py` (CLI + hook routing), `plugins.py` (command handlers), `core.py`/`session_manager.py` (daemon state), `installer/` (install walk), `task_lifecycle.py`, `plan_export.py`, `cache_guard.py`, `integrations.py` |
| `plugins/autorun/{commands,skills,agents,hooks}/` | Slash commands, skills, tmux agents, `hooks/hook_entry.py` + `hooks.json` |
| `plugins/autorun/AGENTS.md` | Plugin development guidance: hook error prevention, feature lessons, bug-workaround policy, harness families |
| `plugins/pdf-extractor/` | Manifests, command, skill, `CLAUDE.md` (full docs), and `src/pdf_extraction` (symlinked into `plugins/autorun/src/` so it ships in the `autorun` distribution; backends beyond `pdftotext` need the `pdf` extra) |
| `README.md` | User documentation: installation, every `/ar:` command, three-stage markers, safety-guard defaults, tmux integration, troubleshooting |

`/ar:help` lists every command in the current harness's spelling. Stage
markers: `AUTORUN_INITIAL_TASKS_COMPLETED` →
`CRITICALLY_EVALUATING_PREVIOUS_WORK_AND_CONTINUING_TASKS_AS_NEEDED` →
`AUTORUN_ALL_TASKS_COMPLETED_AND_VERIFIED_SUCCESSFULLY` (`config.py`).

## 4. Testing

```bash
uv run --project plugins/autorun pytest plugins/autorun/tests/test_unit_simple.py -q   # quick
uv run --project plugins/autorun pytest plugins/autorun/tests/ -q                       # full
```

Paid model calls are off unless you export
`AUTORUN_ENABLE_TESTS_THAT_COST_REAL_MONEY=1`, and every such test carries the
`real_money` marker, so which ones they are is a query rather than a claim:

```bash
uv run --project plugins/autorun pytest plugins/autorun/tests/ -m real_money --collect-only -q   # list what would cost money
uv run --project plugins/autorun pytest plugins/autorun/tests/ -m "not real_money" -q            # run with none of it collected
```

A module name proves nothing here: most tests in `test_*_e2e_real_money.py`
are free hook subprocesses, and paid tests also live in modules whose names
say nothing about cost. `tests/e2e_support.py:requires_real_money` is the only
gate; `tests/test_real_money_gate.py` fails if a second copy appears.

## 5. Installing for real (end users)

`autorun` is one published distribution; `autorun --install` then publishes
every detected harness's native assets. In priority order:

```bash
uv tool install --force autorun && autorun --install                                      # PyPI release
uv tool install --force 'git+https://github.com/ahundt/autorun.git#subdirectory=plugins/autorun' && autorun --install   # git
git clone https://github.com/ahundt/autorun.git && cd autorun && uv tool install --force --editable plugins/autorun && autorun --install   # local clone
```

Claude Code alone can instead use the marketplace: `claude plugin marketplace
add https://github.com/ahundt/autorun.git && claude plugin install ar@autorun`.
Full options, extras (`autorun[pdf]`), and verification: `README.md`. Inside a
development session these commands fall under section 1.