{
  "markdown": "# trail\n\nLocal stdout/stderr capture for AI coding agents.\n\nRun any process under `trail`, then ask Codex, Claude Code, Cursor, Windsurf, or another MCP-capable agent to query the captured logs without pasting terminal output into chat.\n\nSingle static binary. Plain JSONL files on disk. No daemon, no database, no cloud.\n\n## Guided Debugging At A Glance\n\n\nTrail is most useful when the agent needs to move beyond \"read the last error\" and run a disciplined debugging loop: inspect captured logs, keep a ledger, add temporary probes only when needed, wait for the dev server to restart, reproduce the issue, verify the fix, and remove every probe.\n\n![Trail guided debugging workflow: Codex queries Trail MCP, adds temporary probes, waits for restart, reproduces the issue, fixes it, and cleans up](docs/guided-debugging-flow.svg)\n\nThe important constraint is cleanup. Every temporary log line carries a unique `TRAIL-DEBUG-<id>` marker, and the workflow is not done until the agent verifies that marker is gone from the repo.\n\n## Fast Setup\n\nAll integrations need the `trail` binary on your `PATH` first:\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/Pratham-Mishra04/trail/main/install.sh | sh\ntrail version\n```\n\nThen add the integration for your agent.\n\n### Codex\n\n```bash\ncodex plugin marketplace add Pratham-Mishra04/trail --ref main\ncodex plugin add trail@pratham\n```\n\nStart a new Codex thread, then ask:\n\n```text\nUse Trail to list my captured sessions.\n```\n\n### Claude Code\n\n```text\n/plugin marketplace add Pratham-Mishra04/trail\n/plugin install trail@pratham\n/reload-plugins\n```\n\nVerify by asking:\n\n```text\nWhat skills are available?\n```\n\nYou should see `pratham:trail:debug-with-trail`.\n\n### Other MCP Agents\n\nUse the manual MCP config in [Editor Setup](#editor-setup). You will get the `list_sessions` and `get_logs` tools, but not the bundled Codex/Claude guided debugging skill.\n\n![trail architecture: an app wrapped by `trail run` writes stdout/stderr to a JSONL session file on local disk; `trail mcp` reads that file and serves it over stdio MCP to Codex, Claude Code, Cursor, Windsurf, or Claude Desktop](docs/architecture.png)\n\n## First Capture\n\nWrap the process you want to debug:\n\n```bash\ntrail run -- npm run dev\n```\n\nTrail prints a session id and file path, then forwards your app's stdout/stderr normally while also capturing every line:\n\n```text\ntrail: capturing \"npm run dev\" -> 39f6875e-3417-4146-867b-c430971b7489 (file: /Users/you/.config/trail/sessions/39f6875e-3417-4146-867b-c430971b7489.jsonl)\n```\n\nNow ask your agent:\n\n```text\nList my Trail sessions, then show me the errors from the most recent one.\n```\n\nOr query from the terminal:\n\n```bash\ntrail sessions\ntrail logs --session 39f6875e-3417-4146-867b-c430971b7489 --level error\ntrail logs --session 39f6875e-3417-4146-867b-c430971b7489 --query \"ECONNREFUSED\"\n```\n\nThe agent calls `list_sessions` and `get_logs` over MCP. Trail filters the logs in the Go process and returns structured results instead of a wall of text.\n\n## What Trail Gives You\n\n- **Process capture:** `trail run -- <cmd>` wraps any command, captures stdout/stderr, forwards signals, and mirrors the child's exit code.\n- **Docker capture:** `trail docker <container>` captures `docker logs -f` for an already-running container.\n- **Agent tools:** `trail mcp` exposes `list_sessions` and `get_logs` over stdio MCP.\n- **Human tools:** `trail sessions` and `trail logs --session <id>` expose the same query surface in the terminal.\n- **Local files:** captured logs are plain JSONL under `~/.config/trail/sessions/`.\n\n## Guided Debugging Workflow\n\nThe Codex and Claude Code plugins ship a `debug-with-trail` skill for runtime debugging. It turns Trail into a repeatable agent workflow for server crashes, failing tests, silent failures, and \"what happened in the logs?\" investigations.\n\nAsk in plain English:\n\n```text\nMy Express server returns 500 on POST /orders. Use Trail to debug it.\n```\n\nThe skill walks the agent through:\n\n1. **Prerequisites:** verify `trail` is installed and the relevant process is being captured.\n2. **Read existing logs first:** query errors, recent output, and relevant terms before touching code.\n3. **Instrument only when needed:** add temporary targeted log lines with a unique `TRAIL-DEBUG-<id>` marker.\n4. **Verify the fix:** query the marker output after the change, not just static code.\n5. **Clean up:** remove every temporary log line and verify `rg TRAIL-DEBUG-<id>` returns nothing.\n\nThe cleanup rule is the important part: every added probe carries a unique marker, and the agent is instructed to remove the whole log statement after the fix is verified.\n\nRead the exact skill instructions:\n\n- [Codex skill](integrations/codex/skills/debug-with-trail/SKILL.md)\n- [Claude Code skill](integrations/claude-code/skills/debug-with-trail/SKILL.md)\n\n## Use Cases\n\n- **Debugging a running app:** wrap `npm run dev`, `python manage.py runserver`, `go run .`, or any other server and let the agent query only the relevant logs.\n- **Investigating long test runs:** `trail run -- go test -v ./...`, `trail run -- pytest -v`, or `trail run -- npm test`, then ask what failed and why.\n- **Build, lint, and typecheck output:** capture long compiler or linter output once, then filter by level, file name, symbol, or regex.\n- **Comparing flaky runs:** capture a passing run and a failing run, then ask the agent what changed.\n- **Long-running scripts and migrations:** keep a permanent, queryable local record instead of relying on terminal scrollback.\n- **Noisy Docker containers:** use `trail docker <name>` to make container logs queryable without flooding the agent context.\n\nIn every case, the pattern is the same: attach terminal output to your agent by handing it a session id, instead of piping logs through prompts.\n\n## Editor Setup\n\nThe Codex and Claude Code plugins are the recommended setup because they include both MCP wiring and the guided debugging skill.\n\nFor manual MCP setup, make sure `trail` is on the `$PATH` of the shell that launches your editor. macOS GUI apps do not always inherit your shell path; if the MCP server fails to start, check `which trail` from the editor's terminal.\n\n### Claude Code Without The Plugin\n\n```bash\nclaude mcp add trail -s user -- trail mcp\n```\n\nThis path wires up the raw MCP tools (`list_sessions`, `get_logs`) only — it does not include the bundled `debug-with-trail` skill.\n\n### Cursor\n\n`.cursor/mcp.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"trail\": {\n      \"command\": \"trail\",\n      \"args\": [\"mcp\"]\n    }\n  }\n}\n```\n\n### Windsurf\n\nSettings -> MCP:\n\n```json\n{\n  \"mcpServers\": {\n    \"trail\": {\n      \"command\": \"trail\",\n      \"args\": [\"mcp\"]\n    }\n  }\n}\n```\n\n### Claude Desktop\n\n`claude_desktop_config.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"trail\": {\n      \"command\": \"trail\",\n      \"args\": [\"mcp\"]\n    }\n  }\n}\n```\n\n## Install Options\n\n### One-liner\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/Pratham-Mishra04/trail/main/install.sh | sh\n```\n\nThe installer detects your OS/arch, downloads the matching prebuilt binary from the latest GitHub Release, verifies its SHA-256 checksum, and installs `trail` to `~/.local/bin/trail`.\n\nIf `~/.local/bin` is not on your `$PATH`, the installer prints the exact `export` line to add. Override the destination with `BIN_DIR=/usr/local/bin` or pin a version with `VERSION=v0.1.0`.\n\n`wget` works too:\n\n```bash\nwget -qO- https://raw.githubusercontent.com/Pratham-Mishra04/trail/main/install.sh | sh\n```\n\n### Manual Download\n\n```bash\nARCHIVE=trail_darwin_arm64.tar.gz\nBASE=https://github.com/Pratham-Mishra04/trail/releases/latest/download\n\nwget \"$BASE/$ARCHIVE\"\nwget \"$BASE/checksums.txt\"\ngrep \" $ARCHIVE\\$\" checksums.txt | shasum -a 256 -c -\n\ntar xzf \"$ARCHIVE\"\nsudo mv trail /usr/local/bin/\n```\n\nAvailable archives:\n\n- `trail_darwin_arm64.tar.gz`\n- `trail_darwin_amd64.tar.gz`\n- `trail_linux_arm64.tar.gz`\n- `trail_linux_amd64.tar.gz`\n\n### Go Install\n\n```bash\ngo install github.com/Pratham-Mishra04/trail@latest\n```\n\nGo's `go install` does not inject release metadata, so `trail version` may print `trail dev (commit none, built unknown)`. The binary still works normally.\n\n### Build From Source\n\n```bash\ngit clone https://github.com/Pratham-Mishra04/trail\ncd trail\nmake install\n```\n\nThis runs `go install` with version metadata baked in. The binary lands at `$(go env GOPATH)/bin/trail`.\n\n### Supported Platforms\n\nmacOS and Linux on amd64/arm64. Windows is not supported.\n\n## Why Server-side Queries\n\nWhen an agent reads raw log files into its context to filter them, every query pays for re-loading the file's tokens through the LLM. Trail filters in the Go process and returns only matching entries.\n\nThis means:\n\n- The agent does not burn context on log lines that will not matter.\n- Regex and level filters are deterministic.\n- Latency is bounded by the filter work, not token generation speed.\n\n## What It Captures\n\n| Source | Command | Notes |\n|---|---|---|\n| Wrapped command | `trail run -- <cmd>` | Wraps any binary; separate stdout/stderr pipes preserve stream attribution. |\n| Docker container | `trail docker <name>` | Wraps `docker logs -f`; passes `--since` through. |\n\nBoth commands accept `--name <label>` to override the auto-derived session name and `--ephemeral` to delete the session file when the capturer exits cleanly. The file survives a `SIGKILL`; only graceful shutdown triggers cleanup.\n\nTrail does not capture:\n\n- A bare PID you did not start under Trail. That would require `ptrace` or `eBPF`.\n- Arbitrary log files written to disk by another tool. Use `tail`, `lnav`, or normal file tools for those.\n\n## Querying Captured Logs\n\n### From An Agent\n\nThe MCP server exposes two tools:\n\n- **`list_sessions(active_only?, limit?)`:** returns session metadata including the absolute file path of each session JSONL file, ordered active-first.\n- **`get_logs(session_id, filters?)`:** returns matching entries.\n\n`get_logs` filters include:\n\n- `limit`, `page`, and `order`\n- `query` as a case-insensitive regex\n- `level`: `error`, `warn`, `info`, `debug`, `unknown`, or `all`\n- `start_time` / `end_time` as RFC3339 timestamps\n- `duration` as a Go-style duration, such as `\"10m\"` or `\"2h\"`\n- `start_line` / `end_line`\n\nTime-window, duration, and line-range filters are mutually exclusive. Combining them returns an error.\n\nIf a result looks incomplete, the response includes the absolute `file_path` and the agent can read the JSONL file directly with its file tools.\n\n### From The Terminal\n\n```bash\ntrail sessions                                       # table\ntrail sessions --json                                # JSON for scripting\ntrail sessions rm <id>                               # delete one\ntrail sessions rm --all                              # delete all\n\ntrail logs --session <id>                            # last 100, pretty\ntrail logs --session <id> -n 50                      # last 50\ntrail logs --session <id> --level error              # errors only\ntrail logs --session <id> --query \"ECONNREFUSED\"     # case-insensitive regex\ntrail logs --session <id> --format json              # raw JSON entries\n```\n\n`trail logs --session` is required. There is no implicit \"most recent\" default; the MCP tool follows the same rule.\n\n## How It Works\n\n- **Two-process model:** capture processes (`trail run` / `trail docker`) own session files. The MCP server is read-only and spawned by the editor on demand; it never starts, modifies, or stops captures.\n- **One JSONL file per session:** files live at `~/.config/trail/sessions/<uuid>.jsonl`. The first line is a meta header; every subsequent line is one captured entry.\n- **Append-only writes + tolerant reader:** entries are appended to a regular file (`os.OpenFile(O_APPEND)`); `maxRawLen` caps the `Raw`/`Message` fields but not the whole marshaled JSON line, so concurrent reads rely on the reader being tolerant of malformed or partial trailing lines (see `internal/store/reverse.go` and `TestRead_TolerantOfPartialLastLine`) rather than on kernel-level atomicity.\n- **Server-side filtering:** cheap filters run before full JSON decode; eligible newest-first queries (`Order=newest`, `Limit>0`, `Page≤1`, no time/line bounds) use a reverse scan from the end of the file.\n- **Conservative log-level detection:** Trail only assigns a level when there is clear evidence, such as a JSON `level` field, logfmt `level=`, or an anchored prefix like `ERROR:`.\n\n## License\n\nMIT\n",
  "bytes": 12432,
  "sha": "9348f39e110cdffdcc1f23eedf8c9cb184e02dc618bb1a3917c56a53a5834538",
  "repo_slug": "pratham-mishra04/trail",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/plg_pratham_mishra04_trail_trail_d3eec48a/readme"
}