{"id":50708014,"url":"https://github.com/choonkeat/hotroute","last_synced_at":"2026-06-09T13:01:43.469Z","repository":{"id":353476718,"uuid":"1194954640","full_name":"choonkeat/hotroute","owner":"choonkeat","description":"hotroute: laying tracks as the train arrives","archived":false,"fork":false,"pushed_at":"2026-03-29T08:49:48.000Z","size":1369,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-24T04:38:03.057Z","etag":null,"topics":["channel","claude","code"],"latest_commit_sha":null,"homepage":"","language":"Erlang","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/choonkeat.png","metadata":{"files":{"readme":"README.md","changelog":null,"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-03-29T02:55:03.000Z","updated_at":"2026-03-29T08:49:51.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/choonkeat/hotroute","commit_stats":null,"previous_names":["choonkeat/hotroute"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/choonkeat/hotroute","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/choonkeat%2Fhotroute","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/choonkeat%2Fhotroute/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/choonkeat%2Fhotroute/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/choonkeat%2Fhotroute/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/choonkeat","download_url":"https://codeload.github.com/choonkeat/hotroute/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/choonkeat%2Fhotroute/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34107866,"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-09T02:00:06.510Z","response_time":63,"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":["channel","claude","code"],"created_at":"2026-06-09T13:01:42.934Z","updated_at":"2026-06-09T13:01:43.458Z","avatar_url":"https://github.com/choonkeat.png","language":"Erlang","funding_links":[],"categories":[],"sub_categories":[],"readme":"# hotroute\n\nA self-building HTTP server powered by Claude Code. When a browser hits an unknown route, Claude is notified, asks you what it should do, writes a Gleam handler module, hot-loads it into the running BEAM VM, and serves the response — all without restarting.\n\n![hotroute loading page](docs/hotroute-1.png)\n\u003e *Someone just hit GET / on your hotroute server. What should the homepage do?*\n\n## How it works\n\n```\nBrowser: GET /articles/42\n    |\n    v\nhotroute: no handler for /articles/:id\n    |\n    v\nClaude (in your terminal): \"Unknown route: GET /articles/42. What should this do?\"\n    |\n    v\nYou: \"Show the article by ID, render as HTML\"\n    |\n    v\nClaude: writes src/handlers/articles_show.gleam\n      -\u003e compiles and hot-loads into the running VM\n      -\u003e registers GET /articles/:id\n      -\u003e responds to the waiting browser request\n    |\n    v\nBrowser: sees the article page\n\nNext request to GET /articles/99 is served directly — no Claude involved.\n```\n\n![hotroute in action](docs/hotroute-2.png)\n\u003e *Homepage is live at GET / with links to /faq and /contact. The pending browser request has been served. Those two pages don't exist yet — I'll build them when someone hits them.*\n\n## Getting started\n\n### Build (once)\n\n```bash\nmake build\n```\n\nBehind an enterprise proxy with SSL inspection:\n\n```bash\ncp /path/to/Corporate_CA.pem .\nmake build CUSTOM_CA_CERT=Corporate_CA.pem\n```\n\n### Run\n\n```bash\nmake run\n```\n\nTo use a different port:\n\n```bash\nmake run PORT=8080\n```\n\n### First launch\n\n1. Accept the MCP server and permissions prompts\n2. If you see \"Channels require claude.ai authentication\", type `/login` and follow the auth URL\n3. After login, exit (Ctrl+C) and re-run `make run` — the auth persists in your mounted `~/.claude/`\n\nThese prompts are one-time; subsequent launches skip them.\n\n### Usage\n\nOpen `http://localhost:3000` in a browser. Any URL that doesn't have a handler shows a loading page while Claude asks you in the terminal what to build.\n\n### Reset\n\nTo clear all routes and generated handlers:\n\n```bash\nmake reset-routes\n```\n\n## Configuration\n\n| Environment variable | Default | Description |\n|---------------------|---------|-------------|\n| `PORT` | `3000` | HTTP server port |\n| `HOTROUTE_ROOT` | `.` | Project root directory |\n| `HOTROUTE_INSTRUCTIONS` | — | Path to custom MCP instructions file |\n\n### Docker volumes\n\n| Mount point | Purpose |\n|-------------|---------|\n| `/home/hotroute/.claude` | Claude Code auth (mount your `~/.claude`) |\n| `/home/hotroute/app/data` | Route persistence (`routes.json`) |\n\n### Custom instructions\n\nEdit `instructions.md` to change how Claude behaves when an unknown route is hit. Or point to a different file:\n\n```bash\nmake run HOTROUTE_INSTRUCTIONS=./my-instructions.md\n```\n\nUse this to integrate with other communication channels (Telegram, Slack, etc.) or to change Claude's behavior (e.g. auto-build without asking).\n\n## Architecture\n\nhotroute is a single BEAM application running two concurrent services:\n\n1. **MCP channel server** (stdin/stdout) — speaks JSON-RPC with Claude Code. Pure Gleam, no Node.js.\n2. **HTTP server** (Mist/Cowboy) — serves web requests on the configured port.\n\nRoutes are stored in ETS (in-memory). On shutdown, routes are saved to `data/routes.json`. On boot, persisted routes are loaded and handler modules are recompiled.\n\n## Stack\n\n- [Gleam](https://gleam.run) on the BEAM\n- [Mist](https://github.com/lpil/mist) HTTP server\n- [MCP](https://modelcontextprotocol.io) channel protocol (pure Gleam implementation)\n- Erlang/OTP 27 (ETS, hot code loading, process supervision)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchoonkeat%2Fhotroute","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchoonkeat%2Fhotroute","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchoonkeat%2Fhotroute/lists"}