Metadata-Version: 2.4
Name: project-manager-tui
Version: 0.1.16
Summary: Rich-based TUI for managing projects/tasks with git worktrees
Requires-Python: >=3.9
Description-Content-Type: text/markdown
Requires-Dist: rich>=13.0
Requires-Dist: tomli>=2.0; python_version < "3.11"

# project-manager-tui

A terminal task board for people running coding agents in git worktrees.

Tasks live in plain Markdown that you and the agents both edit. `pm-tui` renders
them as one list ordered by what needs you: agent requests waiting on an answer
first, then your open tasks, with everything an agent is busy with hidden until
you ask to see it. One keypress opens a task's worktree, starts its agent, or
releases its branch — the TUI shells out to a script you supply for all of it,
so it knows nothing about tmux, ssh or your remote host.

## Install

```bash
pip install project-manager-tui
pm-tui
```

Requires Python 3.9+.

## Configure

`~/.project-manager-tui.toml`:

```toml
# Required.
agent_worktree_script = "/path/to/agent-worktree.sh"
projects_dir          = "/efs/me/projects"

# Optional, with their defaults.
projects_filename = "Projects.md"
git_repo_dir      = "."          # the cwd `go` is run in
sync_interval     = 300          # seconds between `sync-master` runs
editor            = "$EDITOR"    # falls back to vim
approvals_dir     = ""           # default: {projects_dir}/../approvals

# Optional. Which agent a NEW worktree starts on, cycled in the UI with `m`.
# Short name -> "<cli>-<model>", split at the FIRST dash: everything before it
# is the CLI to run, everything after is the model handed to that CLI. The
# first entry is the default, and the table's order is the cycle order.
#
# Keep the tables LAST in the file: a TOML table swallows every bare key that
# follows it, so a `models` section in the middle silently steals the settings
# under it.
[models]
fable = "claude-fable"          # claude --model fable
astra = "codex-gpt-6-astra"     # codex  -m gpt-6-astra

# Optional. The same for project agents (below), so the two levels can run
# different CLIs -- codex on tasks and claude on projects, or the reverse.
# Without it project agents use [models].
[project_models]
fable = "claude-fable"
```

Without `[models]` the picker is empty, `m` does nothing, and every worktree
starts the way it did before: `claude`, on whatever the container defaults to.
`m` cycles the picker for what is selected: the project one in project view or
on a project agent row, the task one otherwise.

`agent_worktree_script` is the only real dependency, and writing one is the bulk
of the setup — see [the contract](#the-agent-worktreesh-contract) below.

## Layout

```
projects_dir/
  Projects.md              ## Active / ## Future / ## Archived, one slug per line
  my-project/
    Project.md             the task list
    tasks/3/Task.md        one task's brief, created on demand
```

A task is a numbered line in `Project.md`:

```markdown
1. [ ] rewrite the fill parser
2. [ ] backfill september >1          blocked until task 1 closes
3. [ ] chase the vendor >2026-09-20   pinned to a date
4. [x] delete the old path
```

The state character drives everything:

| state | meaning |
|---|---|
| `[ ]` | todo |
| `[i]` | an agent is running `/ready` on it |
| `[t]` | tested |
| `[r]` | released — branch pushed to master |
| `[d]` | delivered — deployed |
| `[v]` | verified — you have seen it work |
| `[x]` | complete |
| `[s]` `[z]` | snoozed / snoozed forever |

`[x]` and `[v]` are what unblock a dependent task. `[i] [t] [r] [d]` mean
underway, so the task is not offered as new work.

## Keys

Task view:

```
j/k  navigate                 z  snooze: 1H/2H/4H/8H/1D/2D…
t    vim Task.md              u  unset: clear state + time snooze
p    vim Project.md           c  complete
v    view worktree            r  release (mark [r])
g    go: start its agent      d  delete task
s    switch to worktree       V/Z/B/W  show verified/snoozed/blocked/working
m    cycle the model          P  project view, ?  help, q  quit
```

Approval rows (`!`) — requests an agent has filed and cannot execute itself:

```
Enter  review + run it        i  inspect the request JSON
x      reject, with a reason  t/p  vim the filing task's Task.md/Project.md
v      view the agent         z  snooze,  u  clear a hold nothing is paying
```

## Project agents

A project agent is a session on a whole project rather than on one task: ask
it what the project is about, have it check a task's results, or have it
write the next task. It does no coding -- that is what tasks are for -- and it
has no branch or worktree; it runs in the same sandbox as the task agents,
with the project directory as its working directory.

```
Project view:   v  open the project's agent (creates it the first time)
                c  close it
Task view:      an open agent is a row, `<slug>-pm  project agent`, that
                behaves like a worktree row for status: hidden while it works,
                listed (and counted by the light) while it waits for you.
                v/g open it, t/p vim Project.md, c close it.
```

Closing keeps the session: the next open resumes it. Which agent a NEW project
agent starts on is `[project_models]` (or `[models]` without it), cycled with
`m` in project view.

The agent's standing instructions live in `{projects_dir}/CLAUDE.md`, an
ancestor of every project directory, so one file serves all of them; the
package ships a starter (`project-agent-role.md`, printed the same way as the
contract below) that `awt-remote.sh` also hands to Codex, which reads no
CLAUDE.md. Copy it there once; without it a project agent starts with only the
per-project prompt the launcher builds.

## Status light

```bash
pm-tui --web            # TUI plus the status page
pm-tui --web-only       # just the page, no TUI
```

Serves a full-window light on port 8899: **green** when the default view is
empty, **amber** with a count when something wants you, **grey** when the count
is too old to trust. `--web-port`, `--web-bind` and `--web-interval` move it;
`/status.json` is the same thing as JSON. Park it on a second screen and stop
checking.

## The `agent-worktree.sh` contract

The TUI never touches git, tmux or ssh itself. It invokes your script with
`list`, `add`, `rm`, `switch`, `view`, `go`, `close`, `release`, `approve` and
`sync-master`, and the shipped contract document specifies each one — the exact
`list` output format, which status tokens the working filter and the status
light read, what may prompt and what may not, and the approval queue's on-disk
format, statuses and leases.

It ships inside the package:

```bash
python -c "import importlib.resources as r, sys; \
  sys.stdout.write((r.files('project_manager_tui') / 'agent-worktree-contract.md').read_text())"
```

Read it before writing a script. Several of the TUI's behaviours — hiding busy
worktrees, the green light, a `go` that does not steal your terminal — are
conventions your script has to hold up its end of, and a script that ignores
them still runs, just quieter than it should.
