{"_id":"@eddiedao/ai-tunnel","_rev":"3-e0a78e402284888c765431cb8f8c6a7f","name":"@eddiedao/ai-tunnel","dist-tags":{"latest":"0.2.0"},"versions":{"0.1.0":{"name":"@eddiedao/ai-tunnel","version":"0.1.0","keywords":["github","webhook","automation","agent","orca","omp","ci","worktree"],"author":{"name":"eddydao"},"license":"MIT","_id":"@eddiedao/ai-tunnel@0.1.0","maintainers":[{"name":"eddiedao","email":"daokythanh@gmail.com"}],"bin":{"ait":"bin/ai-tunnel.js","ai-tunnel":"bin/ai-tunnel.js"},"dist":{"shasum":"a4f7a9da1eecd2201881a2a931164e2c8611c258","tarball":"https://registry.npmjs.org/@eddiedao/ai-tunnel/-/ai-tunnel-0.1.0.tgz","fileCount":28,"integrity":"sha512-Bpywf6a5+pMa3m9AC0o04ktg12779mxHTRFMyd6uBS+KQedbUBnIgjodSKNraGtovmbRUpVBQxWE+npcJiE/8Q==","signatures":[{"sig":"MEUCIQDKii864MKzze/uLNRcg5028sIbYX5eomi4l4Hm+DSDsgIgJ0vZ+W29wj7zt7ewkWjB1KfqjBsXPTuhGxRS0oZK5eI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":86073},"type":"commonjs","engines":{"node":">=22"},"gitHead":"3c2625379d4b2ae70754ec34e95c2949318508ad","scripts":{"dev":"tsc -p tsconfig.json --watch","build":"tsc -p tsconfig.json","clean":"rm -rf dist","start":"node bin/ai-tunnel.js serve","prepack":"npm run clean && npm run build"},"_npmUser":{"name":"eddiedao","email":"daokythanh@gmail.com"},"_npmVersion":"10.9.8","description":"Turn a labeled GitHub issue into an autonomous PR via a pluggable worktree environment (Orca) and coding harness (omp). Ships an interactive installer.","directories":{},"_nodeVersion":"22.23.2","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.5.0","@types/node":"^20.14.0"},"_npmOperationalInternal":{"tmp":"tmp/ai-tunnel_0.1.0_1788424707009_0.09514656094627916","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@eddiedao/ai-tunnel","version":"0.1.1","keywords":["github","webhook","automation","agent","orca","omp","ci","worktree"],"author":{"name":"eddydao"},"license":"MIT","_id":"@eddiedao/ai-tunnel@0.1.1","maintainers":[{"name":"eddiedao","email":"daokythanh@gmail.com"}],"bin":{"ait":"bin/ai-tunnel.js","ai-tunnel":"bin/ai-tunnel.js"},"dist":{"shasum":"26f064195365ecd8c528057bbf1520847ddce4c4","tarball":"https://registry.npmjs.org/@eddiedao/ai-tunnel/-/ai-tunnel-0.1.1.tgz","fileCount":28,"integrity":"sha512-jNZNuBX04ebkCG4WeVDEBbPOsYxx8eHj3TTAOYS/NlfT9MmlTr2Br4DHc42tUfz84+N1ayzk5NzmeLIoaWIvYg==","signatures":[{"sig":"MEYCIQDtcuMYlZDgx1Q40mdlOADUxsBxgHgU95hmmGWdDWS4RAIhAIERuOoAH9EXFPn3ibaK1aQQmHgqBL76N8hRfm9TrUD4","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":86165},"type":"commonjs","engines":{"node":">=22"},"gitHead":"4638ff62892a94dbea029c9f564b0abe7a8713b6","scripts":{"dev":"tsc -p tsconfig.json --watch","build":"tsc -p tsconfig.json","clean":"rm -rf dist","start":"node bin/ai-tunnel.js serve","prepack":"npm run clean && npm run build"},"_npmUser":{"name":"eddiedao","email":"daokythanh@gmail.com"},"_npmVersion":"12.0.2","description":"Turn a labeled GitHub issue into an autonomous PR via a pluggable worktree environment (Orca) and coding harness (omp). Ships an interactive installer.","directories":{},"_nodeVersion":"22.23.2","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.5.0","@types/node":"^20.14.0"},"_npmOperationalInternal":{"tmp":"tmp/ai-tunnel_0.1.1_1788514303749_0.2909242022840408","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@eddiedao/ai-tunnel","version":"0.2.0","description":"Turn a labeled GitHub issue into an autonomous PR via a pluggable worktree environment (Orca) and coding harness (omp). Ships an interactive installer.","keywords":["github","webhook","automation","agent","orca","omp","ci","worktree"],"license":"MIT","author":{"name":"eddydao"},"type":"commonjs","engines":{"node":">=22"},"bin":{"ai-tunnel":"bin/ai-tunnel.js","ait":"bin/ai-tunnel.js"},"scripts":{"build":"tsc -p tsconfig.json","clean":"rm -rf dist","prepack":"npm run clean && npm run build","start":"node bin/ai-tunnel.js serve","dev":"tsc -p tsconfig.json --watch"},"devDependencies":{"@types/node":"^20.14.0","typescript":"^5.5.0"},"publishConfig":{"access":"public"},"_id":"@eddiedao/ai-tunnel@0.2.0","gitHead":"7959b417bd239257e769bc20daf7ba6dfff62ffb","_nodeVersion":"22.23.2","_npmVersion":"10.9.8","dist":{"integrity":"sha512-ZjPGaSTGkGGo0ZzXP1WyDtUbQW0/HIInlLgui2eBreERyKag55IEkorc485W2U+xW6JG+x+m1cc/1cc1wZpWyw==","shasum":"24658ed7172c4596ee3a7ba80b8eab9b7b1ea51a","tarball":"https://registry.npmjs.org/@eddiedao/ai-tunnel/-/ai-tunnel-0.2.0.tgz","fileCount":29,"unpackedSize":88620,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQCkF1EHZh4qSWxFGMZaYmvXuT2Kh3JOmvemftPbLWiKEwIhAJOq9vvmXZT25dvTID5Bhn3DivLxZYwAe5d137AF4pxQ"}]},"_npmUser":{"name":"eddiedao","email":"daokythanh@gmail.com"},"directories":{},"maintainers":[{"name":"eddiedao","email":"daokythanh@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/ai-tunnel_0.2.0_1788769370186_0.7736901428868095"},"_hasShrinkwrap":false}},"time":{"created":"2026-09-03T08:38:26.794Z","modified":"2026-09-07T08:22:50.543Z","0.1.0":"2026-09-03T08:38:27.149Z","0.1.1":"2026-09-04T09:31:43.894Z","0.2.0":"2026-09-07T08:22:50.312Z"},"author":{"name":"eddydao"},"license":"MIT","keywords":["github","webhook","automation","agent","orca","omp","ci","worktree"],"description":"Turn a labeled GitHub issue into an autonomous PR via a pluggable worktree environment (Orca) and coding harness (omp). Ships an interactive installer.","maintainers":[{"name":"eddiedao","email":"daokythanh@gmail.com"}],"readme":"# @eddiedao/ai-tunnel\n\nTurn a labeled GitHub issue into an autonomous PR. A loopback webhook listener\nreceives GitHub `issues.labeled` events through a Cloudflare Tunnel, spins up a\nworktree in a pluggable **environment** (Orca today), launches a pluggable\ncoding **harness** (omp today), and drives it to open a PR — with per-repo HMAC,\na sender allowlist, private-only posture, dedup, and concurrency/daily caps.\n\n```\nlabel an issue \"AI handle\"\n      │  GitHub issues webhook (per-repo HMAC)\nCloudflare Tunnel  <your-host>  ─►  ai-tunnel serve  (127.0.0.1:PORT)\n      │  admission: HMAC · sender · private-only · not-a-PR · dedup · caps\n      ▼\nenvironment worktree off origin/<default>  →  verify plan at tip  →  run-harness.sh (repo-scoped PAT, no SSH)\n      ▼\nharness (omp: /ak:vibe --advice --ship --beta)  →  PR + optional Discord\n```\n\n## Requirements\n\n- **Node ≥ 22** (uses `Promise.withResolvers`).\n- **git**, **gh** (authenticated), **cloudflared** — and, on the host that runs\n  the agent: the selected **environment** (Orca) and **harness** (omp), both\n  installed and working. See `ai-tunnel doctor`.\n\n## Install\n\n```bash\nnpm install -g @eddiedao/ai-tunnel\n# or from a checkout:\nnpm install && npm run build && npm install -g .\n```\n\n## Quickstart\n\n```bash\nai-tunnel init      # interactive wizard: environment → harness → config → enroll → service\nai-tunnel doctor    # verify environment, harness, binaries, gh auth, config\nai-tunnel serve     # run the listener (or install it as a service)\n```\n\nThe wizard writes everything to a **config home** (default `~/.ai-tunnel`,\noverride with `--home` or `$AI_TUNNEL_HOME`):\n\n```\n~/.ai-tunnel/\n  .env             # config (mode 600)\n  creds            # fine-grained PAT (mode 600) — sourced by run-harness.sh\n  secrets.json     # per-repo webhook HMAC secrets (mode 600) — the allowlist\n  run-harness.sh   # env wrapper: PAT-over-HTTPS, SSH disabled\n  git-askpass.sh\n  .state/          # dedup, audit (dispatch.jsonl), logs\n```\n\nThen set up the Cloudflare Tunnel to route your hostname to\n`http://localhost:<PORT>` (the wizard prints the exact commands).\n\n## Commands\n\n| Command | Purpose |\n| --- | --- |\n| `ai-tunnel init` | Interactive setup wizard |\n| `ai-tunnel doctor` | Health report (environment/harness probes, binaries, gh auth, config) |\n| `ai-tunnel enroll <owner/name>` | Labels + per-repo HMAC secret + issues webhook |\n| `ai-tunnel serve` | Run the webhook listener (foreground) |\n| `ai-tunnel service install\\|uninstall\\|restart\\|status` | Background service (systemd on Linux, launchd on macOS) |\n| `--home <path>` | Override the config/state home for any command |\n\n## Trigger contract\n\n1. Commit and push a plan to the default branch under `plans/<...>/plan.md`.\n2. Put a marker in the issue **body**:\n   `<!-- plan=\"plans/<...>/plan.md\" -->` (a folder path ending `/` also works).\n3. As an allowed sender, apply the `AI handle` label.\n\nLabels flow `AI handle → AI in progress → AI done` (PR created) / `AI blocked`\n(needs a human). A branch that already has an **open PR** is never reused — a\nfresh worktree is forked so work never stacks onto a PR under review.\n\n## Extending it\n\nBoth layers are registries; add one file and register it.\n\n- **Environment** (`src/environments/`): implement the `Environment` interface\n  (worktree lifecycle, session launch, PR lookup) and add it to\n  `environments/index.ts`. Roadmap: `herd`.\n- **Harness** (`src/harnesses/`): implement the `Harness` interface (probe,\n  `buildLaunch`, `buildPrompt`) and add it to `harnesses/index.ts`. `claude` and\n  `codex` are registered as **coming soon** (visible in the wizard, not\n  selectable) until implemented.\n\n## Security\n\n- Listener binds `127.0.0.1` only; the sole ingress is the Cloudflare Tunnel.\n- Per-repo HMAC (`secrets.json`); the enrolled set **is** the allowlist\n  (fail-closed — `serve` refuses to start with zero repos / no senders).\n- Sender allowlist; private-repo-only unless `ALLOW_PUBLIC=true`.\n- Repo-scoped fine-grained PAT injected over HTTPS by `run-harness.sh`; SSH keys\n  disabled so the agent cannot act as you across all repos.\n- The approved plan is verified at the worktree tip before launch; issue/PR text\n  is treated as untrusted by the harness prompt.\n- `.env`, `creds`, `secrets.json` are mode `600` and never committed.\n\n## Publishing\n\n```bash\nnpm run build\nnpm publish        # publishConfig.access=public; scope must match your npm account/org\n```\n\n## License\n\nMIT\n","readmeFilename":"README.md"}