{"id":50434251,"url":"https://github.com/forjd/runtrail","last_synced_at":"2026-05-31T16:03:08.813Z","repository":{"id":359591472,"uuid":"1246418519","full_name":"forjd/runtrail","owner":"forjd","description":"Portable event trails for agentic dev workflows: commands, repo diffs, browser QA, CI failures, and repair prompts.","archived":false,"fork":false,"pushed_at":"2026-05-22T15:34:08.000Z","size":99,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-22T20:17:33.854Z","etag":null,"topics":["agentic-workflows","browser-automation","ci","cli","debugging","developer-tools","event-log","github-actions","jsonl","observability","qa","repair-prompts","rust"],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/forjd.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-22T07:10:23.000Z","updated_at":"2026-05-22T15:34:12.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/forjd/runtrail","commit_stats":null,"previous_names":["forjd-hermes-bot/compact-event-log","forjd-hermes-bot/runtrail"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/forjd/runtrail","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/forjd%2Fruntrail","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/forjd%2Fruntrail/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/forjd%2Fruntrail/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/forjd%2Fruntrail/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/forjd","download_url":"https://codeload.github.com/forjd/runtrail/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/forjd%2Fruntrail/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33737692,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-31T02:00:06.040Z","response_time":95,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["agentic-workflows","browser-automation","ci","cli","debugging","developer-tools","event-log","github-actions","jsonl","observability","qa","repair-prompts","rust"],"created_at":"2026-05-31T16:03:07.704Z","updated_at":"2026-05-31T16:03:08.808Z","avatar_url":"https://github.com/forjd.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# runtrail\n\n[![CI](https://github.com/forjd/runtrail/actions/workflows/ci.yml/badge.svg)](https://github.com/forjd/runtrail/actions/workflows/ci.yml)\n[![Release](https://img.shields.io/github/v/release/forjd/runtrail?include_prereleases\u0026sort=semver)](https://github.com/forjd/runtrail/releases)\n[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)\n\n**Portable event trails for agentic dev workflows.**\n\n`runtrail` is a tiny Rust CLI and JSONL event format for recording command evidence, browser QA steps, repository snapshots/diffs, CI context, test results, and agent notes in one local, diffable stream.\n\nThink of it as a cheap black-box recorder for coding agents and CI failures: append structured evidence while work happens, then turn the trail into summaries, diffs, or an agent-ready repair prompt.\n\n## Why runtrail?\n\nCoding agents are most useful when failures arrive with portable context instead of a vague “CI failed”. `runtrail` keeps that context close to the repo:\n\n- **Local-first**: writes plain JSONL to `.runtrail/events.jsonl` by default.\n- **Shell-friendly**: inspect with `tail`, `jq`, `lnav`, or normal diffs.\n- **Agent-ready**: summarise failures and generate focused repair prompts.\n- **CI-safe**: captures only an allowlist of GitHub Actions metadata.\n- **Small and boring**: no daemon, database, hosted service, or custom query language required.\n\n## Install\n\nInstall an immutable release tag from GitHub releases:\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/forjd/runtrail/main/install.sh \\\n  | RUNTRAIL_INSTALL_TAG=runtrail-v0.4.0 bash\n```\n\nThe installer detects OS/architecture, downloads the matching release asset, requires `SHA256SUMS` verification by default, and installs to `~/.local/bin`.\n\nOptional environment variables:\n\n```bash\nRUNTRAIL_INSTALL_TAG=runtrail-v0.4.0 bash install.sh         # required release tag\nRUNTRAIL_INSTALL_DIR=/usr/local/bin bash install.sh          # install directory\nRUNTRAIL_INSTALL_REPO=forjd/runtrail bash install.sh         # alternate repo\nRUNTRAIL_INSTALL_TAG=latest RUNTRAIL_INSTALL_ALLOW_LATEST=1 bash install.sh\nRUNTRAIL_INSTALL_SKIP_CHECKSUM=1 bash install.sh             # explicit integrity opt-out\n```\n\nBuild from source:\n\n```bash\ncargo build --release\n./target/release/runtrail --help\n```\n\n## Quick start\n\nCapture a command run:\n\n```bash\nruntrail run -- cargo test\n```\n\nAdd repository context:\n\n```bash\nruntrail repo snapshot\nruntrail repo diff\n```\n\nSummarise the trail:\n\n```bash\nruntrail summarise --file .runtrail/events.jsonl\n```\n\nGenerate a repair prompt for an agent:\n\n```bash\nruntrail repair-prompt --file .runtrail/events.jsonl \u003e repair.md\n```\n\nCapture a GitHub Actions repair fixture:\n\n```bash\nruntrail ci capture --file .runtrail/events.jsonl\nruntrail repair-prompt --file .runtrail/events.jsonl \u003e .runtrail/repair.md\n```\n\nSee [`docs/github-actions.md`](docs/github-actions.md) for a copy-paste workflow that uploads enumerated runtrail repair files on CI failure.\n\nA typical failure-capture flow looks like this:\n\n```bash\nruntrail repo snapshot\nruntrail run -- cargo test\nruntrail repo diff\nruntrail repair-prompt --file .runtrail/events.jsonl \u003e repair.md\n```\n\n## What gets recorded?\n\nEach line in the log is one compact JSON object:\n\n```json\n{\"schema\":\"runtrail.v1\",\"id\":\"01KS...\",\"seq\":1,\"ts\":\"2026-05-22T12:34:56Z\",\"event\":\"agent.note\",\"level\":\"info\",\"src\":\"runtrail\",\"attrs\":{},\"body\":{\"message\":\"Investigating failing CI\"}}\n```\n\nRequired envelope fields:\n\n| Field | Meaning |\n| --- | --- |\n| `schema` | Schema identifier. Current schema is `runtrail.v1`. |\n| `id` | 26-character event ULID. |\n| `seq` | Positive sequence number within the log file. |\n| `ts` | RFC3339 UTC timestamp. |\n| `event` | Dotted event name, for example `command.end`. |\n\nAdditional envelope fields:\n\n| Field | Meaning |\n| --- | --- |\n| `level` | Required severity: `trace`, `debug`, `info`, `warn`, or `error`. |\n| `src` | Optional event source, for example `runtrail`, `hermes-agent`, or `github-actions`. |\n| `attrs` | Required small structured metadata object useful for filtering. Use `{}` when empty. |\n| `body` | Required event-specific JSON payload. Use `{}` when empty. |\n| `trace_id`, `span_id`, `parent_span_id` | Optional trace correlation fields. |\n| `duration_ms` | Optional duration in milliseconds. |\n\nSee [`docs/schema-v1.md`](docs/schema-v1.md) for full schema notes and conventions.\n\nExample logs:\n\n- [`examples/browser-qa.jsonl`](examples/browser-qa.jsonl)\n- [`examples/ci-failure.jsonl`](examples/ci-failure.jsonl)\n- [`examples/agent-session.jsonl`](examples/agent-session.jsonl)\n\n## Command guide\n\n### Append an event\n\n```bash\nruntrail log --event agent.note --message \"Investigating failing CI\"\n```\n\nDefault log file:\n\n```text\n.runtrail/events.jsonl\n```\n\nWith attributes and a JSON body:\n\n```bash\nruntrail log \\\n  --event command.run \\\n  --attr tool.name=terminal \\\n  --attr exit_code=0 \\\n  --body '{\"cmd\":\"cargo test\"}'\n```\n\n### Run a command and capture evidence\n\n```bash\nruntrail run -- cargo test\nruntrail run --file .runtrail/events.jsonl --cwd . --preview-bytes 4096 --env CI -- npm test\n```\n\n`runtrail run` emits:\n\n- `command.start`\n- `command.end`\n\nThe wrapper logs `command.start` before spawning the child and exits with the child command's exit code. Stdout/stderr are streamed into bounded previews so logs stay portable.\n\n### Capture repository evidence\n\n```bash\nruntrail repo snapshot\nruntrail repo diff\nruntrail repo diff --patch\n```\n\n`repo snapshot` captures branch, HEAD, dirty state, and `git status --porcelain` file entries.\n\n`repo diff` captures staged and unstaged diff stats by default. Use `--patch` only when full patch content is safe to store.\n\n### Capture GitHub Actions context\n\n```bash\nruntrail ci github-context --file .runtrail/events.jsonl\nruntrail ci capture --file .runtrail/events.jsonl\n```\n\nThis records only a safe allowlist of environment variables. For full CI failure capture and artifact upload, see [`docs/github-actions.md`](docs/github-actions.md) and [`examples/github-actions-repair.yml`](examples/github-actions-repair.yml).\n\n- `GITHUB_WORKFLOW`\n- `GITHUB_RUN_ID`\n- `GITHUB_RUN_NUMBER`\n- `GITHUB_RUN_ATTEMPT`\n- `GITHUB_JOB`\n- `GITHUB_ACTION`\n- `GITHUB_ACTOR`\n- `GITHUB_EVENT_NAME`\n- `GITHUB_REF`\n- `GITHUB_SHA`\n- `GITHUB_REPOSITORY`\n- `RUNNER_OS`\n- `RUNNER_ARCH`\n\n### Tail recent events\n\n```bash\nruntrail tail --lines 5\nruntrail tail --lines 5 --json\n```\n\n### Summarise a log\n\n```bash\nruntrail summarise --file .runtrail/events.jsonl\n```\n\nThe summary includes:\n\n- total events\n- first/last timestamps\n- counts by event and level\n- warnings/errors\n- recent events\n\n### Diff two logs\n\n```bash\nruntrail diff before.jsonl after.jsonl\n```\n\nThe diff reports count deltas, added/removed/changed event IDs, and newly introduced warnings/errors.\n\n### Generate an agent repair prompt\n\n```bash\nruntrail repair-prompt --file .runtrail/events.jsonl\n```\n\nThe prompt includes failure evidence, recent command results, repository context when present, suspected causes, and safe commands to try.\n\n### Build an index, inspect, and replay\n\n```bash\nruntrail index --file .runtrail/events.jsonl\nruntrail inspect --file .runtrail/events.jsonl --lines 20\nruntrail replay --file .runtrail/events.jsonl\n```\n\n`index` emits compact JSON query fields, `inspect` shows recent human-readable events, and `replay` prints conservative command hints.\n\n### Validate a log\n\n```bash\nruntrail validate --file .runtrail/events.jsonl\nruntrail validate --file .runtrail/events.jsonl --strict\n```\n\nValidation checks JSONL framing, required fields, schema version, sequence numbers, timestamp parsing, levels, and trace/span ID format. Strict mode also requires each event's `seq` to match its physical JSONL line number, which is useful for CI format hardening before sharing a trail.\n\n### Generate shell completions\n\n```bash\nruntrail completions bash \u003e runtrail.bash\nruntrail completions zsh \u003e _runtrail\nruntrail completions fish \u003e runtrail.fish\n```\n\n## Event examples\n\n```bash\nruntrail log --event command.run --body '{\"cmd\":\"cargo test\",\"exit_code\":0}'\nruntrail log --event browser.navigate --attr browser.url=https://example.com\nruntrail log --event browser.assert --body '{\"text\":\"Dashboard loaded\",\"ok\":true}'\nruntrail log --event test.result --body '{\"runner\":\"cargo test\",\"passed\":21,\"failed\":0}'\nruntrail log --event repo.change --body '{\"files\":[{\"path\":\"src/main.rs\",\"status\":\"M\"}]}'\nruntrail log --event ci.status --attr github.run_id=123 --body '{\"conclusion\":\"success\"}'\nruntrail log --event agent.note --message \"Failure likely caused by missing env var\"\n```\n\nEvent names are intentionally conventional rather than enforced. Producers can add their own dotted names while keeping the same envelope.\n\n## Interoperability\n\nBecause logs are JSONL, they work with normal shell tools:\n\n```bash\njq 'select(.event == \"repo.change\")' .runtrail/events.jsonl\njq 'select(.level == \"error\")' .runtrail/events.jsonl\nlnav .runtrail/events.jsonl\n```\n\nUse `runtrail validate` when you want stricter checks before storing or sharing a log.\n\n## Safety and privacy\n\n`runtrail` records what you ask it to record. A few guardrails are built in:\n\n- command stdout/stderr are captured as bounded previews, not unbounded logs;\n- command argv, attrs, and string body values receive best-effort redaction for common token/password patterns;\n- GitHub Actions context uses a fixed safe allowlist;\n- repo diff stores stats by default, and `--patch` is an explicit full-patch opt-in;\n- logs are local files, so you decide if and where to upload them.\n\nBefore sharing logs publicly, review `.runtrail/events.jsonl` for secrets, tokens, proprietary patches, or sensitive paths.\n\n## Development\n\n```bash\ncargo fmt --check\ncargo clippy --locked --all-targets -- -D warnings\ncargo test --locked\nscripts/perf-smoke.sh 10000\n```\n\nRelease automation is handled by Release Please and GitHub Actions. Binary builds are published for Linux, macOS, and Windows release targets.\n\n## Design notes\n\nResearch and planning docs live in:\n\n- [`docs/research/`](docs/research/)\n- [`docs/mvp-spec.md`](docs/mvp-spec.md)\n- [`docs/plans/`](docs/plans/)\n\nThe MVP is intentionally JSONL-first. Binary export, indexes, richer replay, and deeper CI fixture capture are future work.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fforjd%2Fruntrail","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fforjd%2Fruntrail","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fforjd%2Fruntrail/lists"}