{"id":50126022,"url":"https://github.com/chekos/tunelito","last_synced_at":"2026-06-10T02:01:11.124Z","repository":{"id":359632250,"uuid":"1246874927","full_name":"chekos/tunelito","owner":"chekos","description":"Serve any local HTML page as a temporary live review room with injected comments.","archived":false,"fork":false,"pushed_at":"2026-06-05T04:33:37.000Z","size":54811,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-05T05:14:34.570Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://github.com/chekos/tunelito#readme","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/chekos.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-05-22T16:46:46.000Z","updated_at":"2026-06-05T04:32:33.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/chekos/tunelito","commit_stats":null,"previous_names":["chekos/tunelito"],"tags_count":11,"template":false,"template_full_name":null,"purl":"pkg:github/chekos/tunelito","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chekos%2Ftunelito","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chekos%2Ftunelito/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chekos%2Ftunelito/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chekos%2Ftunelito/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chekos","download_url":"https://codeload.github.com/chekos/tunelito/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chekos%2Ftunelito/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34133404,"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-06-10T02:00:07.152Z","response_time":89,"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":[],"created_at":"2026-05-23T20:00:59.504Z","updated_at":"2026-06-10T02:01:11.118Z","avatar_url":"https://github.com/chekos.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Tunelito\n\n[![CI](https://github.com/chekos/tunelito/actions/workflows/ci.yml/badge.svg)](https://github.com/chekos/tunelito/actions/workflows/ci.yml)\n\nTunelito turns any local HTML file or folder of HTML files into a temporary live review room.\n\nRun one command, share the printed URL on a call, and reviewers can select text, leave page notes, or leave site-wide notes. You keep editing the HTML in your normal editor; connected browsers reload when files change. Comments are saved as readable markdown beside the page or folder by default, or kept ephemeral with `--live`.\n\nTunelito is local-first: your files stay on your machine, the public URL is a temporary tunnel to your laptop, and edit access never leaves your editor.\n\n## Quickstart\n\nTunelito requires Node.js 22 or newer.\n\n```bash\nnpx --yes tunelito ./page.html\n```\n\nFor a folder-backed mini-site:\n\n```bash\nnpx --yes tunelito ./site\n```\n\nFolder reviews write one Markdown inbox beside the folder:\n\n```text\nsite/\nsite.comments.md\n```\n\nEach comment includes a scope, page path, and visible comment id, so Claude Code, Codex, or another local agent can watch that file, apply edits to the matching HTML file or the whole folder when a comment is site-wide, and continue larger comments across bounded follow-up passes.\n\nTo let a local agent handle comments while Tunelito runs:\n\n```bash\nnpx --yes tunelito ./site --agent codex\n```\n\nUse `--agent claude` for Claude Code, or `--agent-command \"\u003cyour command\u003e\"` for another local CLI. Tunelito sends prompts to that command on stdin and tracks handled comment IDs in `.tunelito/agent/state.json`.\n\nIf you are already inside Claude Code, Codex, or another agent session, use agent-session mode instead of spawning a child agent:\n\n```bash\nnpx --yes tunelito ./site --agent-session --no-tunnel --open\ntunelito inbox watch ./site\n```\n\n`inbox watch` waits for the next actionable comment, claims it in the shared ledger, prints a prompt for the current agent, and exits. After editing, record the result with `tunelito inbox record`.\n\nFrom a clone:\n\n```bash\nnpm install\nnpm link\ntunelito ./examples/simple-review.html\n```\n\nTunelito prints:\n\n```text\nTunelito is running\nLocal:   http://127.0.0.1:4317/?tunelito_key=...\nComments: /path/to/page.comments.md\nAccess:  review key required by the printed URLs\nPublic:  https://example.trycloudflare.com/?tunelito_key=...\n```\n\nShare the `Public:` URL with the person on your call. Open the `Local:` URL yourself if you want to watch the same session.\n\nTo label your own comments as the session owner:\n\n```bash\ntunelito ./page.html --owner \"Chekos\"\n```\n\nTunelito assigns everyone else a random editable display name, so comments from multiple reviewers are easy to tell apart.\n\nFor local-only work:\n\n```bash\ntunelito ./page.html --no-tunnel --open\n```\n\nFor in-meeting collaboration without writing comments to disk:\n\n```bash\ntunelito ./page.html --live\n```\n\n## What Reviewers Can Do\n\n- Select text on desktop or mobile.\n- Tap `Comment` and leave a note on the selected text.\n- Add a `Page note` without selecting text.\n- Add a `Site note` that appears on every page in a folder review.\n- Keep or edit their assigned display name before commenting.\n- See other comments appear live.\n- In `--live`, see peer cursors and live selection highlights when the browser can connect peer-to-peer.\n- In persistent sessions, open the generated markdown comments file from the panel.\n\n## What You Control\n\n- The source HTML files remain untouched.\n- Edits happen in your editor only.\n- Saved HTML changes trigger a live reload in connected browsers.\n- Comments persist to `\u003cpage-or-folder\u003e.comments.md` unless you choose another path with `--out`.\n- `--live` keeps comments in memory only; the session disappears when the local server exits.\n\n## CLI\n\n```text\nTunelito 0.10.0\n\nUsage: tunelito \u003cpage.html|folder\u003e [options]\n       tunelito inbox \u003cnext|watch|record\u003e \u003cpage.html|folder\u003e [options]\n       tunelito skill show\n\nOptions:\n  --port \u003cnumber\u003e       Port to listen on (default: first free from 4317)\n  --host \u003chost\u003e         Host to bind locally (default: 127.0.0.1)\n  --out \u003cpath\u003e          Markdown comments file (default: \u003cpage-or-folder\u003e.comments.md)\n  --owner \u003cname\u003e        Assign this editable owner name to the local viewer\n  --live                Use ephemeral live collaboration mode; do not write comments to disk\n  --agent \u003ccodex|claude|custom\u003e\n                        Run a local coding-agent worker for persistent comments\n  --agent-command \u003ccmd\u003e Custom shell command for --agent custom; prompt is sent on stdin\n  --agent-interval \u003cs\u003e  Agent fallback polling interval in seconds (default: 120)\n  --agent-policy \u003cmode\u003e Which comments the agent handles: all|mention|owner|owner-or-mention (default: all)\n  --agent-trigger \u003ctxt\u003e Marker for mention policies, or \"all\" (default: all)\n  --agent-instructions \u003ctxt\u003e\n                        Append host instructions to the built-in agent prompt\n  --agent-instructions-file \u003cpath\u003e\n                        Append host instructions from a file\n  --agent-prompt \u003ctxt\u003e  Replace the built-in agent behavior prompt\n  --agent-prompt-file \u003cpath\u003e\n                        Replace the built-in agent behavior prompt from a file\n  --agent-max-attempts \u003cn\u003e\n                        Stop retrying a comment after n attempts (default: 2)\n  --agent-max-passes \u003cn\u003e\n                        Stop continuing a multi-pass comment after n agent passes (default: 3)\n  --agent-state \u003cpath\u003e  Agent resolution ledger (default: \u003ctarget\u003e/.tunelito/agent/state.json)\n  --agent-session       Print active-agent inbox commands; do not spawn a worker\n  --no-tunnel           Only print the local URL; do not start Cloudflare Tunnel\n  --no-auth             Disable the generated review-key URL gate\n  --open                Open the local URL in your default browser\n  -v, --version         Show version\n  -h, --help            Show this help\n\nCommands:\n  inbox next            Claim the next pending comment and print an agent prompt\n  inbox watch           Wait for the next pending comment, then print an agent prompt\n  inbox record          Record the active agent's result for one comment\n  skill show            Print the distributable Tunelito agent skill (SKILL.md)\n                        for a coding agent to install\n```\n\n## Agent Skill\n\nTunelito ships an agent skill that teaches a coding agent (Claude Code, Codex, Cursor, and others) how to drive Tunelito: starting and sharing a review session safely, keeping sensitive pages local, and applying the comments from a `*.comments.md` inbox.\n\nThe stable installation path is to have your agent print the bundled skill and install that output however the agent expects:\n\n```bash\nnpx --yes tunelito skill show\n```\n\nFor Claude Code, for example:\n\n```bash\ntunelito skill show \u003e .claude/skills/tunelito/SKILL.md\n```\n\nOr tell your agent: \"run `npx --yes tunelito skill show` and install the skill it prints.\"\n\n## How It Works\n\nTunelito serves the HTML from disk and injects a small same-origin annotation client into the response. For folder targets, every served `.html` or `.htm` page gets the client and shares one comments inbox. Page-scoped comments appear only on their current page; site-scoped comments appear on every page in that folder session. The injected client handles selection, unanchored page/site notes, highlights, live sync, and reload notices. The original HTML files are not modified.\n\nThe server also:\n\n- serves sibling assets relative to the HTML file, or non-hidden files within the selected folder\n- writes comments to markdown atomically\n- restores prior comments from hidden Tunelito metadata in that markdown\n- can run an opt-in local agent worker against persistent comments\n- relays WebRTC signaling and live fallback events in `--live`\n- starts `cloudflared tunnel --url \u003clocal-url\u003e` when available\n- falls back to `npx cloudflared@latest` when `cloudflared` is not installed\n\nSet `TUNELITO_CLOUDFLARED_PACKAGE=cloudflared@\u003cversion\u003e` to pin the fallback package used by `npx` while keeping the default behavior on `cloudflared@latest`.\n\n## Access Model\n\nShared sessions include a generated `tunelito_key` in the printed URLs by default. The key is bearer access: anyone with the full URL can view the page and leave comments. The first valid request sets a short-lived, HTTP-only cookie so page assets and WebSocket sync keep working.\n\nWhen `--owner \u003cname\u003e` is set, the printed `Local:` URL also includes a separate owner key. Comments from that owner session are marked as owner-authored, and the local agent worker receives the owner name and each comment's author role. The owner key is a session label, not stronger authentication; anyone with the full owner URL can comment as the owner.\n\n`--no-auth` only removes the review-key gate; it does **not** disable the tunnel. A tunneled session started with `--no-auth` is a public, unauthenticated URL that anyone who finds it can open and edit. If you want no key you almost always want local-only too, so add `--no-tunnel`. Use `--no-auth` only for local demos or trusted networks.\n\n`--live` changes persistence, not exposure: it keeps comments in memory instead of writing them to disk, but the session is still served over the same tunnel and review key. For sensitive material, prefer `--no-tunnel` (optionally with `--live`) or avoid sharing the session link.\n\n## Comment Files\n\nBy default:\n\n```text\npage.html\npage.comments.md\n```\n\nFor folder targets, the default comments file is beside the folder:\n\n```text\nsite/\nsite.comments.md\n```\n\nThe markdown is meant to be readable in any editor:\n\n```markdown\n# Tunelito comments for `page.html`\n\n## Jane at 2026-05-22 18:00:00 UTC\n\n\u003e selected text\n\nThis sentence needs a clearer verb.\n\n_Context: scope: `page` · page: `/about.html` · path: `body \u003e main \u003e p` · text offset: 42 · id: `c_...`_\n```\n\nOwner comments add an owner marker:\n\n```markdown\n## Chekos (owner) at 2026-05-22 18:02:00 UTC\n\n\u003e selected text\n\nShip this version after the headline change.\n\n_Context: author role: `owner` · scope: `page` · page: `/` · path: `body \u003e main \u003e h1` · text offset: 0 · id: `c_...`_\n```\n\nUnanchored notes are stored without a selected quote:\n\n```markdown\n## Jane at 2026-05-22 18:05:00 UTC\n\n_Site note (no selected text)._\n\nUse the same heading rhythm across every itinerary page.\n\n_Context: scope: `site` · page: `/day-03.html` · id: `c_...`_\n```\n\nIf a site comment is created from selected text, Tunelito keeps the quote for context and highlights it on the origin page only.\n\nTunelito also stores hidden metadata comments so the live session can be restored after a restart.\n\nIn `--live`, comments are not written to markdown and are not restored after restart.\n\n## Agent Comment Loop\n\nThe persistent comments file is a practical inbox for Claude Code, Codex, or another local coding agent. Folder comments include `scope: ...`, `page: ...`, and `id: ...` in their visible context. When `--owner` is set, the worker prompt also includes the owner name and each comment's `authorRole`, so host instructions can ask the agent to prefer owner comments or wait for owner approval.\n\nIf you are already inside an agent session, let the current agent own the loop:\n\n```bash\ntunelito ./site --agent-session --owner \"Chekos\" --agent-policy owner-or-mention --agent-trigger \"@agent\"\n```\n\nTunelito prints an `Agent session:` command and writes `.tunelito/session.json` beside the served root. In the active agent session, run:\n\n```bash\ntunelito inbox watch ./site --agent-policy owner-or-mention --agent-trigger \"@agent\"\n```\n\n`inbox watch` waits for the comments markdown to change, keeps interval polling as a fallback, claims the next actionable comment in `.tunelito/agent/state.json`, prints a bounded prompt for the current agent, and exits. After editing the source files, record the outcome with the claim id from the printed command:\n\n```bash\ntunelito inbox record ./site --id c_... --claim claim_... --status resolved --summary \"Updated the hero copy.\" --file index.html\n```\n\nUse `tunelito inbox next ./site` for a non-waiting check. Use repeated `--file`, `--completed`, and `--remaining` flags when recording multi-file or `needs_followup` work. Run one active inbox watcher per served workspace; claim ids are local leases that prevent stale recordings and let abandoned claims expire, not a distributed lock for multiple simultaneous watchers. The same `--agent-policy`, `--agent-trigger`, `--agent-state`, `--agent-max-attempts`, and `--agent-max-passes` controls apply to inbox mode and the spawned worker.\n\nTunelito can run the local agent worker for you:\n\nExample:\n\n```bash\ntunelito ./site --agent codex\n```\n\nThe built-in provider presets reuse your local CLI auth:\n\n- `--agent codex` runs `codex exec` in workspace-write mode.\n- `--agent claude` runs `claude -p` with edit permissions.\n- `--agent-command \"\u003ccmd\u003e\"` runs a custom shell command with the prompt on stdin.\n\nBy default, the worker evaluates every comment and decides whether to edit, return `no-op`, or mark the comment `ignored`. It wakes when the comments markdown changes and keeps `--agent-interval` as a fallback.\n\nUse `--agent-trigger \"@agent\"` or another marker when you want stricter sessions:\n\n```bash\ntunelito ./site --agent codex --agent-trigger \"@agent\"\n```\n\nUse `--agent-policy owner` when only owner-authored comments should reach the worker:\n\n```bash\ntunelito ./site --owner \"Chekos\" --agent codex --agent-policy owner\n```\n\nFor the recommended owner-led workflow, let owner comments through automatically and let visitors opt in with a marker:\n\n```bash\ntunelito ./site --owner \"Chekos\" --agent codex --agent-policy owner-or-mention --agent-trigger \"@agent\"\n```\n\nMention-based policies require a non-`all` trigger marker.\n\nLarge actionable comments can span multiple agent passes. The agent can return `needs_followup` with `completedTasks` and `remainingTasks`; Tunelito queues the same comment again with that continuation context until it is `resolved`, `blocked`, `partial`, or reaches `--agent-max-passes`.\n\n```bash\ntunelito ./site --agent codex --agent-max-passes 5\n```\n\nAdd host-specific guidance without changing code:\n\n```bash\ntunelito ./site --agent codex --agent-instructions \"Keep copy concise and preserve the existing layout.\"\n```\n\nUse `--agent-instructions-file instructions.md` for longer guidance. Use `--agent-prompt` or `--agent-prompt-file` to replace the built-in behavior prompt; Tunelito still appends the workspace context, required JSON shape, and pending comments.\n\nHandled comments are recorded in `.tunelito/agent/state.json` with statuses like `resolved`, `needs_followup`, `no-op`, `ignored`, `blocked`, `partial`, and `stale`. That state file prevents the worker from repeating the same edit after the source text changes and the original highlight becomes stale, while still allowing a large inline, page, or site comment to continue from its saved remaining tasks. A readable run log is written to `.tunelito/agent/log.md`; Tunelito blocks both files from static serving and ignores `.tunelito` ledger writes for browser reloads.\n\nTreat `--agent` as trusted-session behavior: reviewer comments become instructions to a local process that can edit files.\n\nManual agent prompt for older builds:\n\n```text\nMonitor site.comments.md every 2 minutes. For each new actionable comment, edit the matching HTML file, then summarize the comment id and change made.\n```\n\nQuick walkthrough:\n\n1. Run `npx --yes tunelito ./site --agent codex --no-tunnel --open`.\n2. Select text in the browser and leave a comment.\n3. The local worker invokes Codex for new unresolved comments.\n4. Codex edits the source HTML file named by a page-scoped comment's `page: ...` context, or the relevant files for a site-scoped comment.\n5. If Codex returns `needs_followup`, Tunelito sends the same comment again with completed and remaining tasks on the next pass.\n6. Tunelito reloads connected browsers after saved HTML changes.\n\n## Live Mode\n\n`--live` is for in-the-meeting collaboration. Comments, cursors, and selection highlights stay in memory and disappear when the local server exits.\n\nTunelito uses WebRTC data channels between browsers when possible. The authenticated WebSocket connection remains open for room membership, WebRTC signaling, file-change reloads, and fallback relay if a peer-to-peer connection cannot be established. Tunelito does not configure third-party STUN or TURN servers, so some remote networks will use the relay fallback.\n\n## Pre-call Checklist\n\nBefore sharing a live session:\n\n1. Run `npx --yes tunelito ./page.html`.\n2. Wait for the `Public:` URL.\n3. Open that URL on your phone.\n4. Select text and submit a short comment.\n5. Add a short page note or site note from the comments panel.\n6. Confirm the terminal logs `Comment from ...`.\n7. Confirm `\u003cpage\u003e.comments.md` contains the comment with `scope: ...`.\n8. Edit and save the HTML file; the phone should reload.\n\nFor an ephemeral call, run with `--live` and skip the markdown-file check.\n\n## Packaging a Release Tarball\n\n```bash\nnpm run ci\nnpm pack\nnpm install -g ./tunelito-0.5.0.tgz\n```\n\nThe package includes the CLI, runtime source, examples, docs, changelog, license, and security policy.\n\n## Project Docs\n\n- [Security policy](./SECURITY.md)\n- [Release process](./docs/RELEASING.md)\n- [Agent playbooks](./docs/agents/START_HERE.md)\n- [Mintlify docs source](./docs-site/README.md)\n- [Examples](./examples/README.md)\n\n## Current Limits\n\n- Text annotations work best on real DOM text.\n- Canvas, video, images, and cross-origin iframes are not yet annotatable.\n- If the exact commented text changes, the comment remains in markdown and the sidebar, but the highlight may not reattach.\n- Strict in-page CSP meta tags are removed from the served response so the injected same-origin client can run.\n- WebRTC peer-to-peer connections depend on browser and network support; the WebSocket relay keeps `--live` usable when direct peer connections fail.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchekos%2Ftunelito","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchekos%2Ftunelito","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchekos%2Ftunelito/lists"}