1# lazyopenspec23A lazygit-style terminal viewer for [OpenSpec](https://github.com/Fission-AI/OpenSpec) repos, built on4[Bubble Tea v2](https://github.com/charmbracelet/bubbletea). Leave it open in a split while agents work and watch5changes, task progress, and spec deltas update as files land on disk, with a running feed of what was touched.6789## Install1011```sh12go install src.rest/cat/lazyopenspec@latest # needs Go 1.27+13```1415Or download a binary for macOS, Linux, or Windows from16[Releases](https://github.com/FelineStateMachine/lazyopenspec/releases).1718## Run1920```sh21lazyopenspec # finds openspec/ in the current directory or any parent22lazyopenspec ~/code/repo # or point it at a repo23lazyopenspec --follow # jump to whatever the agents touch next24lazyopenspec --portrait always # stack panels above the main pane: auto (default), always, never25lazyopenspec --interval 1s # poll less often (default 400ms)26```2728It only reads files. `git` is optional; without it you lose the uncommitted markers and the diff view.2930## What it shows3132- **Changes**: every active change under `openspec/changes/`. `PDST` lights up as the proposal, design, spec33 deltas, and tasks appear. The progress bar counts top-level checkboxes the way `openspec list` does, so the34 numbers match the CLI.35- **Specs**: the main specs with requirement counts. `Δ2` means two active changes have a delta against that spec;36 open the spec and press `]` to read them next to it.37- **Archive**: archived changes, newest first.38- **Activity**: new changes, added, edited, or removed files, task progress (`tasks 4/10 → 5/10`), requirement39 count changes, and archives, newest first. `enter` jumps to the item.40- **Main pane**: the selected file rendered as markdown, one tab per artifact. `d` switches to `git diff HEAD` for41 that file, so you see what an agent changed since its last commit.4243A bright `●` means edited in the last 15 seconds and a dim one the last 2 minutes. `M` and `+` mark uncommitted and44untracked files.4546## Follow mode4748`f` (or `--follow`) moves the selection to whatever changed most recently and opens the file that changed, so the49main pane always shows what the agents are doing right now. Scroll position is kept per file, so an edit to the50file you're reading doesn't send you back to the top.5152## Vertical stack (portrait) mode5354This works like lazygit's `portraitMode`. In a tall, narrow pane (84 columns or fewer and 46 rows or more,55lazygit's defaults), the panels stack on top and take a third of the height, and the main pane gets the rest at56full width. `--portrait always` or `never` overrides that, and `v` flips the layout while it runs.5758When the panels are short on space, the focused one expands and the others shrink to their selected row, or to59just their title if space is very tight. Tab between panels to open each one in turn.6061## Keys6263| Key | Action |64|---|---|65| `tab` / `shift+tab`, `1`-`4`, `0` | switch panel (`0` is the main pane) |66| `j` `k` / arrows, `g` `G` | move the selection, or scroll when the main pane is focused |67| `enter` / `l`, `esc` / `h` | focus the main pane, back to the list |68| `J` `K`, `ctrl+d` `ctrl+u` | scroll the main pane from anywhere |69| `[` `]` | previous / next file tab |70| `d` | git diff against HEAD |71| `f` | follow mode |72| `s` | sort changes by name or by most recent edit |73| `z` | zoom the main pane |74| `v` | toggle the vertical stack layout |75| `e` | open the file in `$VISUAL` or `$EDITOR` |76| `c` | clear the activity feed |77| `r` | reload |78| `?` | help |79| `q` | quit |8081The mouse wheel scrolls the pane under the pointer, and clicking selects a row.8283## How it works8485- **Polling, not fsnotify.** It stats every file under `openspec/` every `--interval` and re-parses only when86 something changed. On macOS, fsnotify holds a file descriptor open per watched file, and agents save files by87 writing a temp file and renaming it, which polling handles without special cases.88- **Reads the files directly.** It doesn't call the `openspec` CLI, which takes about 100 ms per call and can't read89 archived changes. The parsers follow the CLI's rules; [docs/openspec-format.md](docs/openspec-format.md) has the90 format notes they're based on.91- **Stays out of git's way.** Git runs with `GIT_OPTIONAL_LOCKS=0`, so the viewer never takes `.git/index.lock`92 while agents are committing.9394## Try it without agents9596`scripts/swarm-sim.sh` copies the test fixture to a temp repo and runs three simulated agents that draft changes,97check off tasks, add requirements, and archive finished work:9899```sh100scripts/swarm-sim.sh /tmp/lazyopenspec-demo # ctrl+c to stop101lazyopenspec /tmp/lazyopenspec-demo --follow # in another pane102```103104## Development105106```sh107make check # gofmt, go vet, staticcheck, tests with -race108make build # bin/lazyopenspec109make demo # re-record docs/media/demo.gif with vhs110```111112## License113114[MIT](LICENSE)