diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..ef42892 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,104 @@ +# Agent Guide + +## Project Overview + +patterm is a Go terminal orchestration TUI. It runs as one foreground process that owns: + +- the host TUI chrome +- child PTYs +- headless `libghostty-vt` emulators for rendered-grid snapshots +- the in-process MCP server +- per-project scratchpads and command-preset trust state + +There is no daemon or attach/detach model. Closing the patterm process tears down every child process it spawned. + +Core packages: + +- `cmd/patterm`: main binary, including `mcp-stdio` and `debug-harness` subcommands. +- `internal/app`: TUI/session state, palette, child lifecycle, rendering, MCP tool host. +- `internal/pty`: thin wrapper around `github.com/creack/pty`. +- `internal/vt`: `libghostty-vt` backed emulator wrapper. +- `internal/mcp`: JSON-RPC MCP socket server and tool surface. +- `internal/preset`: XDG-loaded agent/process presets. +- `internal/trust`: per-project command-preset trust grants. +- `internal/harness`: black-box PTY/MCP test harness. + +## Build Prerequisites + +The normal build depends on the vendored `libghostty-vt` static library and headers under `third_party/libghostty-vt/install`. + +If that install tree is missing, run: + +```sh +make deps +``` + +This fetches the pinned Ghostty commit and builds `libghostty-vt` with Zig. The Makefile currently requires `zig` on `PATH` with a compatible version. + +Common checks: + +```sh +go test ./... +go build -o ./bin/patterm ./cmd/patterm +``` + +## Harness Testing + +The harness is the preferred way to test patterm end-to-end without a human watching a terminal. + +It starts a real patterm child process in a PTY, feeds its output through the same `internal/vt` emulator used for child panes, and talks to the child patterm process over its per-PID MCP Unix socket. Scenarios are JSON files under: + +```text +internal/harness/scenarios/ +``` + +Useful harness commands: + +```sh +go test ./internal/harness/... +go test -race ./internal/harness/... +go test -count=10 ./internal/harness/... +``` + +Run one scenario through the CLI: + +```sh +go build -o ./bin/patterm ./cmd/patterm +./bin/patterm debug-harness --scenario internal/harness/scenarios/spawn_process_via_palette.json +``` + +Harness scenarios create hermetic XDG/config/data/runtime directories, write scenario-local presets and fake scripts, and set `PATTERM_HARNESS=1`. They must not read or write the user's real patterm config. + +Failure artifacts are written under: + +```text +internal/harness/.artifacts/ +``` + +That directory is gitignored. Artifacts include rendered grid text, raw PTY bytes, serialized VT state, MCP snapshots, the resolved environment, and an annotated scenario. + +### Harness Environment Notes + +The harness and patterm MCP server create Unix sockets and spawn PTYs. In restricted sandboxes this can fail with errors such as: + +```text +listen unix ... setsockopt: operation not permitted +``` + +When that happens, rerun the harness tests or `debug-harness` command in an environment that permits Unix sockets and PTYs. + +When testing a specific binary, set: + +```sh +PATTERM_BIN=/absolute/path/to/patterm go test ./internal/harness/... +``` + +Without `PATTERM_BIN`, harness tests build the current checkout once into a temp location and test that binary. + +## Development Notes + +- Prefer existing package boundaries. MCP protocol shapes live in `internal/mcp`; runtime behavior usually belongs in `internal/app`. +- Keep terminal rendering changes covered by focused app tests or a harness scenario. +- Do not let child PTY output own host chrome. The app owns tab bar, sidebar, status line, and palette. +- Command-preset trust must be seeded before starting patterm in tests because the app opens the trust store during startup. +- If a scenario needs external CLIs such as `claude`, `codex`, or `opencode`, gate it behind an explicit opt-in environment variable. CI scenarios should use fake scripts/presets. diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..ef42892 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,104 @@ +# Agent Guide + +## Project Overview + +patterm is a Go terminal orchestration TUI. It runs as one foreground process that owns: + +- the host TUI chrome +- child PTYs +- headless `libghostty-vt` emulators for rendered-grid snapshots +- the in-process MCP server +- per-project scratchpads and command-preset trust state + +There is no daemon or attach/detach model. Closing the patterm process tears down every child process it spawned. + +Core packages: + +- `cmd/patterm`: main binary, including `mcp-stdio` and `debug-harness` subcommands. +- `internal/app`: TUI/session state, palette, child lifecycle, rendering, MCP tool host. +- `internal/pty`: thin wrapper around `github.com/creack/pty`. +- `internal/vt`: `libghostty-vt` backed emulator wrapper. +- `internal/mcp`: JSON-RPC MCP socket server and tool surface. +- `internal/preset`: XDG-loaded agent/process presets. +- `internal/trust`: per-project command-preset trust grants. +- `internal/harness`: black-box PTY/MCP test harness. + +## Build Prerequisites + +The normal build depends on the vendored `libghostty-vt` static library and headers under `third_party/libghostty-vt/install`. + +If that install tree is missing, run: + +```sh +make deps +``` + +This fetches the pinned Ghostty commit and builds `libghostty-vt` with Zig. The Makefile currently requires `zig` on `PATH` with a compatible version. + +Common checks: + +```sh +go test ./... +go build -o ./bin/patterm ./cmd/patterm +``` + +## Harness Testing + +The harness is the preferred way to test patterm end-to-end without a human watching a terminal. + +It starts a real patterm child process in a PTY, feeds its output through the same `internal/vt` emulator used for child panes, and talks to the child patterm process over its per-PID MCP Unix socket. Scenarios are JSON files under: + +```text +internal/harness/scenarios/ +``` + +Useful harness commands: + +```sh +go test ./internal/harness/... +go test -race ./internal/harness/... +go test -count=10 ./internal/harness/... +``` + +Run one scenario through the CLI: + +```sh +go build -o ./bin/patterm ./cmd/patterm +./bin/patterm debug-harness --scenario internal/harness/scenarios/spawn_process_via_palette.json +``` + +Harness scenarios create hermetic XDG/config/data/runtime directories, write scenario-local presets and fake scripts, and set `PATTERM_HARNESS=1`. They must not read or write the user's real patterm config. + +Failure artifacts are written under: + +```text +internal/harness/.artifacts/ +``` + +That directory is gitignored. Artifacts include rendered grid text, raw PTY bytes, serialized VT state, MCP snapshots, the resolved environment, and an annotated scenario. + +### Harness Environment Notes + +The harness and patterm MCP server create Unix sockets and spawn PTYs. In restricted sandboxes this can fail with errors such as: + +```text +listen unix ... setsockopt: operation not permitted +``` + +When that happens, rerun the harness tests or `debug-harness` command in an environment that permits Unix sockets and PTYs. + +When testing a specific binary, set: + +```sh +PATTERM_BIN=/absolute/path/to/patterm go test ./internal/harness/... +``` + +Without `PATTERM_BIN`, harness tests build the current checkout once into a temp location and test that binary. + +## Development Notes + +- Prefer existing package boundaries. MCP protocol shapes live in `internal/mcp`; runtime behavior usually belongs in `internal/app`. +- Keep terminal rendering changes covered by focused app tests or a harness scenario. +- Do not let child PTY output own host chrome. The app owns tab bar, sidebar, status line, and palette. +- Command-preset trust must be seeded before starting patterm in tests because the app opens the trust store during startup. +- If a scenario needs external CLIs such as `claude`, `codex`, or `opencode`, gate it behind an explicit opt-in environment variable. CI scenarios should use fake scripts/presets.