hatch
Open a hatch: serve a dev server, static page, report, or prototype on a private tailnet URL with the hatch CLI.
Skill by KroniK907
Install
Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.
npx agentmarket install skill/kronik907-hatch
Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.
Get the weekly diff
The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.
About
Use cases: documents, backend
Reviews
Write a reviewNo reviews yet. Installed it? Reviews come from verified installers only. How reviews work
Permissions
What this skill can do and what it asks for, from its SKILL.md. Checked Oct 25, 2026.
- Tools
- No tools found
- Secrets
- None asked for
- Install scripts
- None found
Network hosts it talks to 1
codeload.github.com· found in install command
Files it touches
~/.claude/skills/hatch
What's inside
- Skill name
hatch- Description
- Open a hatch: serve a dev server, static page, report, or prototype on a private tailnet URL with the hatch CLI. Use when asked to open, close, or extend a hatch, or to host, preview, or share anything web-based for the user to view from another device.
- License
- MIT
- Instructions
- 87 lines in SKILL.md · view on GitHub
Before installing
- Instructions call the network
Files (1)
- SKILL.md
SKILL.md (first lines)
**Hatch** is a command-line tool on this machine (`hatch`). "Open a hatch" means: run the thing the user wants to see under `hatch up` and give them the URL it prints. The URL works from any device on the user's tailnet, including their laptop and phone.
It is not the in-app browser preview, `localhost`, a `file://` path, `tailscale serve`, cloudflared, or ngrok. Don't offer any of those as a substitute. If `command -v hatch` finds nothing, say so and stop.
## Open a hatch
### 1. Pick what runs and its name
Hatch assigns a free port (20000-29999) and passes it to the command as `PORT`. The app must listen on **`127.0.0.1:$PORT` only**. Hatch already holds the tailnet address on that port for TLS, so an app that binds every interface (`0.0.0.0`, `::`, or Go's `":"+port`) fails with "address already in use".
| What to show | Command after `hatch up ... --` |
|---|---|
| Static HTML, a report, mocks | `sh -c 'exec python3 -m http.server "$PORT" --bind 127.0.0.1 --directory <dir>'` |
| App that reads `PORT` and binds loopback | `<dev command>` |
| App that takes a port or host flag | `sh -c 'exec <app> --host 127.0.0.1 --port "$PORT"'` |
| Vite | `sh -c 'exec npx vite --host 127.0.0.1 --port "$PORT" --strictPort'` |
| Next.js | `sh -c 'exec npx next dev -H 127.0.0.1 -p "$PORT"'` |
- Hatch execs the command without a shell, so a bare `$PORT` in the argument list is never expanded. Wrap it in `sh -c '...'`, and use `exec` inside so signals reach the app.
- For static files, serve the smallest directory that holds the page and its assets. Not `/tmp`, not `$HOME`. If the page links assets by relative path, serve from the directory those paths start at.
- Check the app's listen code before you start it. If it binds every interface and has no host flag or env var, **stop**. Tell the user and propose the small app change that binds loopback. Do not put a proxy or forwarder in front of it.
- Always pass `--name <short-label>` (lowercase letters, digits, `-`). The default is the git branch, which in agent worktrees is a meaningless id. The label shows up in `hatch ls`, not in the URL.
- When the app builds absolute links or redirects, point it at the public origin: hatch sets `HATCH_URL` in the child's env.
**Done when:** you have one command that starts the app on loopback at `$PORT`, and a name.
### 2. Start it detached
```bash
setsid nohup hatch up --name <label> --minutes 240 -- <command> \
> /tmp/hatch-<label>.log 2>&1 < /dev/null &
sleep 4; head -2 /tmp/hatch-<label>.log; hatch ls
```
- `hatch up` blocks for as long as the route lives. Start it with `setsid nohup ... &` as above. A background task from the agent's own tool (Claude Code `run_in_background`, for example) is killed when the tool's time limit hits, and that takes the hatch down with it. That cut off a 2-hour hatch before.
- `--minutes` defaults to 30, too short for most reviews. Use 240 unless the user gave a time. `--minutes 0` keeps it up until the process is stopped; use it only when the user asks for that. `hatch up -h` lists the flag. An old note that says otherwise is out of date.
- `--port N` without a command routes to a server that is already running. That works only if the server listens on `127.0.0.1:N` and N is in 20000-29999. Starting the app under hatch is the default.
**Done when:** the log's first line is a URL and `hatch ls` shows your name.
### 3. Check it, then hand it over
```bash
curl -s -o /dev/null -w '%{http_code}\n' '<url><path>'
```
This machine is on the tailnet, so curl the real URL, not `127.0.0.1`.
| Result | Cause |
|---|---|
| `200` (or the app's normal code) | Working |
| `000`, curl exit 35, `packet length too long` | The app answered plain HTTP on the tailnet port: it binds every interface. See step 1. |
| `502` "registered on port N, but nothing answered" | The app hasn't started yet, crashed, or listens on another port. Read the log. |
| Log shows `address already in use`, `command exited with status 1` | The app tried to bind every interface. See step 1. |
| `register: ... (is hatch serve running?)` | The daemon is down. Run `systemctl status hatch` and `journalctl -u hatch -n 30 --no-pager`, report what you find, and stop. Don't start `hatch serve` yourself. |
| `<label> is already registered by another process` | Run `hatch ls`. If the owner is your own earlier hatch, stop it (see below). Otherwise pick another name. Use `--replace` only on a route you own. |
Give the user the full link, including the path to the page (`https://<machine>.<tailnet>.ts.net:<port>/docs/report.html`), how long it stays up, and that the device must be on the tailnet. Every new `hatch up` gets a new port, so the old link stops working.
**Done when:** the URL with its path returns the page through hatch, and the user has the link.
## Close or extend a hatch
Stop the `hatch up` process. It stops the app and removes the route:
```bash
pkill -f '^hatch up --name <label> '
hatch ls
```
- Anchor the pattern with `^hatch up`. An unanchored `pkill -f "<label>"` also matches the agent's own shell command and kills it (exit 144).
- `hatch down <label>` alone does not close a live hatch. The running `hatch up` re-registers within 5 seconds. Use `hatch down` only to clear a route whose process is already gone.
- To extend, stop it and open it again with a longer `--minutes`. Tell the user the new URL.
- "Clean up" or "close out the thread" includes the hatch: stop it and confirm `hatch ls` no longer lists it.
**Done when:** `hatch ls` doesn't list the label.
## Reference
- `hatch ls --json` prints `{"zone": ..., "routes": [{"name", "port", "url", "owner", "expires", ...}]}`. It's an object, not a list.
- Env in the child: `PORT`, `HATCH_PORT`, `HATCH_URL`, `HATCH_NAME`.
- The browser's `Host` is `<machine>.<tailnet>.ts.net:<port>`, passed through unchanged. Dev servers with a host allowlist need that name. For Vite, set `server.allowedHosts: ['.ts.net']`. On "blocked request" or "invalid host header" errors, add it there.
- WebSockets, HMR, and server-sent events pass through.
- Daemon ports are off limits for `--port`: 53, 80, 7080, 7081, 8008, 8080, 8880.
- Source and design notes: the `NUSAlaska/hatch` repository's `README.md`.From KroniK907/agent-config, MIT.
More from KroniK907/agent-config
- 0.570score
babysit
KroniK907
Babysit a pull request: wait for reviewbot, fix what holds up, push, and repeat until the review comes back clean, then merge.
SkillAFreshness: AClaude Code +9 - 0.567score
backlog-sweep
KroniK907
Sweep a repo's open GitHub issues: close what shipped or went stale, narrow what is half done, and label small quick work priority: high.
SkillAFreshness: AClaude Code +9 - 0.565score
subagent
KroniK907
Pick the model and reasoning effort for a subagent before you spawn one.
SkillAFreshness: AClaude Code +9 - 0.561score
writing-for-agents
KroniK907
writing for agents, create or edit skills, AGENTS.md, CLAUDE.md, project rules, skill description pointers, context pointers, leading words
SkillAFreshness: AClaude Code +9 - 0.561score
commit
KroniK907
commit this chat, git commit agent output, snapshot chat changes, commit work from this conversation, commit only this session's changes, split commits from…
SkillAFreshness: AClaude Code +9 - 0.561score
ccr-summary
KroniK907
CCR summary, summarize a CCR, Consumer Confidence Report PDF, water quality report PDF, 40 CFR 141.156, § 141.156 summary
SkillAFreshness: AClaude Code +9 - 0.561score
improve-codebase-architecture
KroniK907
deep modules, shallow modules, improve architecture, refactoring opportunities, consolidate tightly-coupled modules, module deepening, architectural friction
SkillAFreshness: AClaude Code +9 - 0.558score
triage-issue
KroniK907
triage, bug report, file issue with fix plan, investigate a problem, root cause and TDD fix plan, what's broken
SkillAFreshness: AClaude Code +9 - 0.553score
wayfinder
KroniK907
Overview of the wayfinder map lifecycle - map, grill, build, release - and which skill runs each step.
SkillAFreshness: AClaude Code +9 - 0.553score
write-a-skill
KroniK907
write-a-skill, create a skill, write a skill, build an agent skill, new agent skill
SkillAFreshness: AClaude Code +9 - 0.552score
taste-skill-v2
KroniK907
Anti-slop frontend skill for landing pages, portfolios, and redesigns.
SkillAFreshness: AClaude Code +9 - 0.539score
code-review
KroniK907
Review a PR, branch, or diff since a ref on two axes - standards and spec - and report or post the findings.
SkillAFreshness: AClaude Code +9
Signals
- Stars
- 0
- Forks
- 0
- Open issues
- 7
- Last commit (this folder)
- Oct 12, 2026 (16 days ago)
- Last release
- Sep 23, 2026 (1 month ago)
From GitHub (fetched Oct 24, 2026).
Details
- License
- MIT
- Repository
- github.com/KroniK907/agent-config
- First seen
- Oct 24, 2026
- Last checked
- Oct 24, 2026
- Source
- GitHubgithub-graphql
More from KroniK907
- 0.570score
babysit
KroniK907
Babysit a pull request: wait for reviewbot, fix what holds up, push, and repeat until the review comes back clean, then merge.
SkillAFreshness: AClaude Code +9 - 0.567score
backlog-sweep
KroniK907
Sweep a repo's open GitHub issues: close what shipped or went stale, narrow what is half done, and label small quick work priority: high.
SkillAFreshness: AClaude Code +9 - 0.565score
subagent
KroniK907
Pick the model and reasoning effort for a subagent before you spawn one.
SkillAFreshness: AClaude Code +9 - 0.561score
commit
KroniK907
commit this chat, git commit agent output, snapshot chat changes, commit work from this conversation, commit only this session's changes, split commits from…
SkillAFreshness: AClaude Code +9 - 0.561score
ccr-summary
KroniK907
CCR summary, summarize a CCR, Consumer Confidence Report PDF, water quality report PDF, 40 CFR 141.156, § 141.156 summary
SkillAFreshness: AClaude Code +9 - 0.561score
improve-codebase-architecture
KroniK907
deep modules, shallow modules, improve architecture, refactoring opportunities, consolidate tightly-coupled modules, module deepening, architectural friction
SkillAFreshness: AClaude Code +9
Cite this page
hatch skill. Agent Mart. https://agentmart.dev/skills/kronik907-hatch (last updated 2026-10-24)