shout/CLAUDE.md
Chris Wanstrath 9943641c02 Allow @def directives in setup files and fix macro precedence
User macros now correctly override setup macros instead of
last-write-wins. Also hardens @def continuation parsing to reject
trailing backslash at EOF, blank lines, and comment lines.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 13:24:37 -07:00

80 lines
4.1 KiB
Markdown

# shout
Transcript-based shell integration test runner. Bun + TypeScript.
## Commands
- `bun test` — run unit tests
- `bunx tsc --noEmit` — type check
- `bun run src/cli/index.ts test [files...]` — run shout CLI
- `-u, --update` — rewrite `.shout` files with actual output
- `-k, --keep` — keep temp directories after run
- `--clean-env` — start with empty environment
- `--path <path>` — prepend to `$PATH` (repeatable)
- `--timeout <dur>` — per-command timeout (default `10s`)
- `-t, --filter <pattern>` — only run files whose path contains `<pattern>`
- `-v, --verbose` — print each command as it runs
- `--port-from <n>` — auto-assign `$PORT` starting from n (default `5400`)
- `--parallel` — run files in parallel
## Architecture
- `src/parse.ts` — parses `.shout` files into `ShoutFile` (list of `Command`)
- `src/run.ts` — executes commands via `Bun.spawn(["/bin/sh"], { detached: true })`, captures output with sentinels
- `src/match.ts` — wildcard-aware output matching and diff generation
- `src/format.ts` — evaluates pass/fail, formats failures and summary
- `src/update.ts` — rewrites `.shout` files with actual output (`--update` mode)
- `src/utils.ts` — shared utilities (`trimTrailingEmpty`, `escapeRegex`)
- `src/duration.ts` — parses duration strings (`10s`, `500ms`, `1m`)
- `src/cli/index.ts` — CLI entry point via `commander`
- `src/index.ts` — barrel exports
- `web/index.html` — web documentation page
## .shout file format
- `$ ` prefix = command to execute
- Lines between commands = expected output (stdout+stderr merged)
- `...` on its own line = multi-line wildcard (matches zero or more lines)
- `...` inline = matches any characters on that line
- `[N]` on last line of expected output = assert exit code N
- `[*]` = assert any non-zero exit code; default expects 0
- `$#` comment line = not executed, no output expected (e.g. `$# start the server`)
- `#` after a command = comment (stripped); `#` in expected output is literal
- `@env KEY=VALUE` before first command = set environment variable
- `@teardown <command>` before first command = run command after all test commands
- Runs regardless of pass/fail
- Teardown failures produce warnings but don't affect test results
- Can appear in both `.shout` files and setup files
- `@setup path.shout` before first command = prepend commands (and `@env`) from another file
- Setup files use a plain format: each line is a command (no `$ ` prefix), `#` lines are comments, blank lines ignored
- Setup files can contain `@env`, `@teardown`, and `@def` directives but not `@setup` (no nesting)
- User file `@env` overrides setup file `@env`
- Setup command failures abort the test with an error
- `@def name body` before first command = define a macro
- If a command matches `name` exactly, `body` is substituted before execution
- Backslash `\` at end of line continues the body onto the next line
- Allowed in both `.shout` files and setup files
- User file `@def` overrides setup file `@def` with the same name
- Each file runs in a fresh temp dir with a single `/bin/sh` session
- `$HOME` and `$SHOUT_DIR` are set to the temp dir automatically
- `$SHOUT_SOURCE_DIR` is set to the directory containing the `.shout` file
- `$SHOUT_PROJECT_DIR` is set to `cwd` where `shout` was invoked
- stdout and stderr are merged (`exec 2>&1`)
## New feature checklist
1. `src/parse.ts` — update types (`Directive`, `ShoutFile`, `Command`) and both parsers (`parse` + `parseSetup`)
2. `src/parse.test.ts` — unit tests for parsing the new syntax in both `.shout` and setup file contexts
3. `src/cli/index.ts` — wire up the parsed result in `runOne` (directive resolution, command merging, result handling)
4. `test/*.shout` — integration test file exercising the feature end-to-end
5. `CLAUDE.md` — update `.shout file format` section
6. `README.md` — update Directives section
7. `web/index.html` — add or update a section on the website
8. Run `bun test` and `bun run src/cli/index.ts test test/` to verify
## Style
- Strict TypeScript, Bun runtime
- No classes — plain functions and types
- Tests in `src/*.test.ts`, example `.shout` files in `test/`