Metadata-Version: 2.4
Name: praetor-cli
Version: 1.0.0
Summary: Local-first task queue and DAG executor for coding agents
Author: Sid Valecha
License: MIT License
        
        Copyright (c) 2026 Sid Valecha
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
        
Project-URL: Homepage, https://github.com/sid-valecha/praetor
Project-URL: Repository, https://github.com/sid-valecha/praetor
Project-URL: Issues, https://github.com/sid-valecha/praetor/issues
Project-URL: Changelog, https://github.com/sid-valecha/praetor/releases
Keywords: ai,agents,coding-agents,claude-code,task-queue,dag,workflow,orchestration,loop-engineering
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: POSIX
Classifier: Operating System :: MacOS
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development
Classifier: Topic :: Software Development :: Build Tools
Classifier: Topic :: Utilities
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: typer>=0.12
Requires-Dist: pydantic>=2.7
Requires-Dist: python-frontmatter>=1.1
Requires-Dist: rich>=13.7
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == "dev"
Requires-Dist: ruff>=0.5; extra == "dev"
Dynamic: license-file

# Praetor

Praetor is a local-first task queue and DAG executor for coding agents; it is not another coding agent.

## Install

Praetor requires Python 3.11 or newer.

Primary install:

```bash
pipx install praetor-cli
```

Alternative install:

```bash
pip install praetor-cli
```

The PyPI package is `praetor-cli`; the installed binary is `praetor`.

## Quickstart

Sequential mode is the default. It runs one ready task at a time in your current checkout.

```bash
cd your-project
praetor init
praetor add --title 'Implement auth module' --verify 'pytest tests/test_auth.py'
praetor status
praetor run
```

## Quickstart: Parallel Mode

Parallel mode runs eligible ready tasks in per-task git worktrees. Use it when independent tasks can be verified separately and merged back through Praetor. It requires a git repository and a base branch named `main`, unless you pass `--base-branch`.

Replace the `--verify` commands below with commands that exist in your project:

```bash
cd your-project
praetor init
praetor add --title "Refactor user module" --verify "pytest tests/users"
praetor add --title "Refactor billing module" --verify "pytest tests/billing"
praetor run --max-parallel 4
praetor status
praetor merge --all
```

`praetor run --max-parallel 4` enables parallel mode. Ready tasks with `parallel_ok: true` may run concurrently; tasks with `parallel_ok: false` run alone after the active pool drains. The default is still `--max-parallel 1`, which preserves sequential v0 behavior.

Manual merge is the default in parallel mode. After an agent exits, Praetor runs the task's `verify` command in that task's worktree, commits the verified worktree state to `praetor/<task-id>`, and marks the task `pending_merge`. `praetor status` shows `pending_merge` when verified work is waiting for integration and `merge_failed` when an attempted merge failed and needs human recovery.

Merge all waiting tasks:

```bash
praetor merge --all
```

Merge selected tasks:

```bash
praetor merge implement-auth-module-a1b2c3d4
```

For an auto-merge run, opt in explicitly:

```bash
praetor run --max-parallel 4 --merge-strategy auto
```

## CLI Reference

| Command | Key options | Purpose |
|---|---|---|
| `praetor` | `--install-completion`, `--show-completion` | Root command; Typer also exposes shell completion helpers. |
| `praetor init` | none | Create `.praetor/` state in the current repository. |
| `praetor add` | `--title`, `--depends-on`, `--verify`, `--parallel-ok/--no-parallel-ok`, `--merge-strategy`, `--agent` | Create a task markdown file under `.praetor/tasks/`. |
| `praetor status` | none | Print task status, dependencies, and verify commands. |
| `praetor run` | `--adapter`, `--max-parallel`, `--base-branch`, `--merge-strategy` | Drain ready tasks with the selected agent adapter. `--max-parallel 1` runs sequentially; values greater than 1 use worktrees. |
| `praetor merge` | `TASK_ID...`, `--all`, `--retry`, `--base-branch` | Merge `pending_merge` tasks back to the base branch. With `--retry`, also retry `merge_failed` tasks. |
| `praetor logs <task-id>` | `<task-id>` | Print the saved log for one task. |

## Merge Strategy

Parallel mode separates "verified in a worktree" from "integrated into the base branch." Manual merge is the default because auto-merging AI-authored commits to `main` is an explicit trust decision, not a safe default.

Each task has a `merge_strategy` field:

- `manual` parks verified work as `pending_merge`; a human runs `praetor merge <task-id>` or `praetor merge --all`.
- `auto` merges the task branch automatically after verify passes.

The CLI `--merge-strategy` flag on `praetor run` overrides all tasks for that run, regardless of their per-task field. For example, `praetor run --max-parallel 4 --merge-strategy auto` attempts to auto-merge every task completed during that run, including tasks whose frontmatter says `merge_strategy: manual`.

The `--merge-strategy` flag is only valid in parallel mode; passing it with `--max-parallel 1` is rejected with a clear error.

`praetor merge` uses `git merge --no-ff --no-edit` from `praetor/<task-id>` into the base branch. It refuses to merge if the base repo has uncommitted changes, records conflicts in the task log, and leaves the task as `merge_failed` for retry.

## Worktrees

In parallel mode, each running task gets an isolated git worktree at:

```text
.praetor/worktrees/<task-id>/
```

Praetor records the task branch, base branch, and fork-point SHA in:

```text
.praetor/worktrees/<task-id>/.praetor-meta.json
```

Worktrees intentionally persist after task completion. They are needed for manual merge, conflict recovery, and post-mortem inspection. Disk-pressure cleanup is not implemented yet; it is tracked as [issue #7](https://github.com/sid-valecha/praetor/issues/7).

## Recovery Flows

If a task is `merge_failed`, inspect the task log and worktree, resolve the underlying conflict or base-branch issue, then retry:

```bash
praetor merge --retry <task-id>
```

If a previous runner crashed and left a task as `running`, `praetor run` fails closed with a stale-running error. Recovery UX is tracked as [issue #6](https://github.com/sid-valecha/praetor/issues/6). The current manual workaround is to inspect `.praetor/worktrees/<task-id>/` and `.praetor/logs/<task-id>.log`, then edit `.praetor/tasks/<task-id>.md` to set `status: pending` before running Praetor again.

## Task File Schema

Tasks live in `.praetor/tasks/<id>.md`. The markdown body is the prompt given to the agent; the frontmatter is Praetor's task metadata.

```markdown
---
id: implement-auth-module-a1b2c3d4
status: pending
depends_on: []
parallel_ok: true
agent: claude
verify: pytest tests/test_auth.py
review: off
merge_strategy: manual
created: 2026-06-08T14:22:00Z
---

# Implement auth module

## What to do
Add the authentication module and wire it into the existing app.

## How to verify
Run `pytest tests/test_auth.py` and confirm it passes.

## Proof when complete
Summarize the files changed and include the verify output.
```

| Field | Description |
|---|---|
| `id` | Stable task id; also used as the task filename stem. |
| `status` | Persisted values are `pending`, `running`, `done`, `failed`, `blocked`, `pending_merge`, or `merge_failed`. The DAG resolver and `praetor status` derive readiness from `pending` tasks whose dependencies are all `done`; readiness is not a persisted status. |
| `depends_on` | List of task ids that must be `done` before this task can run. |
| `parallel_ok` | Whether this task may run concurrently with other ready tasks. Default: `true`. Set `false` for cross-cutting or exclusive work. |
| `agent` | Intended agent for this task. Default: `claude`. `praetor run --adapter` selects the runtime adapter for the run. |
| `verify` | Shell command run after the agent exits. A non-zero exit keeps the task from completing. |
| `review` | v1+: reviewer mode, one of `off`, `lenient`, or `strict`. Present in v0 files for forward compatibility. |
| `merge_strategy` | Parallel-mode merge behavior, one of `manual` or `auto`. Default: `manual`. `praetor run --merge-strategy` overrides this field for all tasks in that run. |
| `created` | UTC timestamp for task creation. |
| `body` | Markdown body after the frontmatter. It is parsed into the task model and passed to the agent; it is not written as a frontmatter field. |

## How It Works

Praetor stores state as files under `.praetor/`: task markdown in `.praetor/tasks/`, per-task logs in `.praetor/logs/`, per-task worktrees in `.praetor/worktrees/`, and global run metadata in `.praetor/state.json`. The DAG resolver computes the ready set from `pending` tasks whose dependencies are all `done`.

With `--max-parallel 1`, Praetor runs one ready task at a time in the current checkout. After the agent exits, the task's `verify` command gates whether the task is marked `done` or `failed`.

With `--max-parallel > 1`, Praetor creates a worktree and branch for each dispatched task, runs the agent and verify command inside that worktree, commits the verified result, then either parks it as `pending_merge` or merges it automatically depending on the effective merge strategy.

## Limitations

v1 parallel execution is functional, but these items are intentionally not implemented yet:

- Dispatch-time conflict detection for overlapping task scopes: [issue #4](https://github.com/sid-valecha/praetor/issues/4)
- Post-merge verification on the base branch: [issue #5](https://github.com/sid-valecha/praetor/issues/5)
- Stale-running recovery command such as `praetor reset`: [issue #6](https://github.com/sid-valecha/praetor/issues/6)
- Worktree cleanup flag for disk-pressure management: [issue #7](https://github.com/sid-valecha/praetor/issues/7)
- Multi-OS CI: [issue #8](https://github.com/sid-valecha/praetor/issues/8)

## Docker / Sandboxed Runs

Build the image:

```bash
docker build -t praetor-cli .
```

Run Praetor against the current repository:

```bash
docker run --rm -it -v "$PWD:/repo" -w /repo praetor-cli praetor run --adapter claude
```

Use the container as the trust boundary for permission-bypassing agent runs such as `--dangerously-skip-permissions`; run that bypass inside the container, not on the host.

```bash
docker run --rm -it -v "$PWD:/repo" -w /repo praetor-cli \
  claude --dangerously-skip-permissions
```

## Roadmap

[v1 parallel execution](roadmap.md#roadmap) adds worktrees, a worker pool, concurrent execution for eligible DAG siblings, and manual or automatic merge integration. [v1.1 MCP + Claude Code plugin](roadmap.md#roadmap) adds the MCP server and plugin distribution. v2 adds planner mode; v3 adds the meta loop and a GUI over the same file-based state.

## License

See [LICENSE](LICENSE).
