{"id":50351200,"url":"https://github.com/marcomc/kodexlink-tools","last_synced_at":"2026-05-29T21:01:38.940Z","repository":{"id":355303096,"uuid":"1220495624","full_name":"marcomc/kodexlink-tools","owner":"marcomc","description":null,"archived":false,"fork":false,"pushed_at":"2026-05-02T22:33:48.000Z","size":86,"stargazers_count":1,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-02T23:30:43.987Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/marcomc.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.md","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-04-25T00:54:28.000Z","updated_at":"2026-04-26T03:22:13.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/marcomc/kodexlink-tools","commit_stats":null,"previous_names":["marcomc/kodexlink-tools"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/marcomc/kodexlink-tools","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marcomc%2Fkodexlink-tools","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marcomc%2Fkodexlink-tools/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marcomc%2Fkodexlink-tools/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marcomc%2Fkodexlink-tools/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/marcomc","download_url":"https://codeload.github.com/marcomc/kodexlink-tools/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marcomc%2Fkodexlink-tools/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33670211,"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-29T02:00:06.066Z","response_time":107,"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-29T21:01:36.893Z","updated_at":"2026-05-29T21:01:38.926Z","avatar_url":"https://github.com/marcomc.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# KodexLink Relay Tools\n\nLocal tooling for running a private KodexLink mobile relay on macOS with Docker\nCompose, Tailscale Serve, and the upstream KodexLink desktop agent.\n\n## Table of Contents\n\n- [What It Does](#what-it-does)\n- [Architecture](#architecture)\n- [Quick Start](#quick-start)\n- [Daily Commands](#daily-commands)\n- [Pairing](#pairing)\n- [Updates](#updates)\n- [Uninstall](#uninstall)\n- [Boot Behavior](#boot-behavior)\n- [Security Model](#security-model)\n- [Resource Use](#resource-use)\n- [Documentation](#documentation)\n- [Project Files](#project-files)\n- [License](#license)\n- [References](#references)\n\n## What It Does\n\nThis project gives one command surface for a private KodexLink relay setup:\n\n- clones or updates the upstream relay source;\n- builds and runs the relay, PostgreSQL, and Redis with Docker Compose;\n- keeps the relay bound to `127.0.0.1` on the Mac;\n- publishes the relay privately over HTTPS with Tailscale Serve;\n- installs the KodexLink desktop agent as a macOS LaunchAgent;\n- opens the local QR pairing panel when a phone or iPad needs pairing;\n- checks health, resources, diagnostics, and repository privacy.\n\nThe generated runtime environment lives outside this repository:\n\n```text\n~/.config/kodexlink-tools/relay.env\n```\n\nIn that file:\n\n- `KODEXLINK_RELAY_PUBLIC_BASE_URL` is the mobile-facing URL.\n- `KODEXLINK_TAILSCALE_HTTPS_PORT` is the shared published Tailscale\n  Serve/Funnel HTTPS port and must be `443`, `8443`, or `10000`.\n- `KODEXLINK_RELAY_HOST_PORT` is only the local Docker port.\n\nWith Tailscale Serve, the public URL should normally be\n`https://machine-name.tailnet-name.ts.net` without `:8787`; Tailscale proxies\nHTTPS port `443` to the local Docker port. If port `443` is already occupied by\nanother local reverse proxy, you can persist a different published HTTPS port\nsuch as `8443` or `10000` and use a public URL like\n`https://machine-name.tailnet-name.ts.net:8443`.\n\nThe LaunchAgent is not the configuration source for relay URL or port. The\nLaunchAgent only keeps the desktop agent running in the background. Relay URL\nand HTTPS port should be changed through `relay.env` via the supported Makefile\ncommands, not by editing the LaunchAgent plist.\n\nDo not commit real tailnet names, Tailscale IPs, tokens, local user paths,\nhostnames, generated pairing payloads, or generated env files.\n\n## Architecture\n\n```text\niPhone / iPad\n  -\u003e Tailscale HTTPS URL\n  -\u003e Tailscale Serve on the Mac\n  -\u003e http://127.0.0.1:8787\n  -\u003e Docker relay\n  -\u003e PostgreSQL + Redis\n\nKodexLink desktop agent\n  -\u003e same relay URL\n  -\u003e local Codex CLI / codex app-server\n```\n\nThe relay itself is plain HTTP and does not load TLS certificates. Tailscale\nServe terminates HTTPS for the `*.ts.net` address and proxies to the local\nrelay port. That keeps Docker private to the Mac while giving iOS and iPadOS a\ntrusted HTTPS endpoint.\n\n`RELAY_PUBLIC_BASE_URL` is critical. The relay embeds it into pairing payloads,\nand the mobile app stores it when pairing succeeds. Set the final Tailscale\nHTTPS URL before pairing.\n\n## Quick Start\n\nEnable MagicDNS and HTTPS certificates in the Tailscale admin console first,\nthen run:\n\n```bash\nmake check-deps\nmake install PUBLIC_URL=https://machine-name.tailnet-name.ts.net\nmake enable\nmake doctor\nmake pair\n```\n\nFor normal operation, prefer the Makefile workflow above. You do not usually\nneed to run `tailscale serve ...` manually, because `make enable` already\nconfigures Tailscale Serve with the saved URL and HTTPS port.\n\nOn iPhone or iPad, before scanning the QR code:\n\n1. Connect Tailscale.\n2. Open KodexLink Settings.\n3. Open Relay Server.\n4. Select Custom Address.\n5. Enter the same Tailscale HTTPS URL.\n6. Tap Save Custom Address.\n7. Return to the pairing scanner and scan the Mac QR code.\n\n`make install` prepares the machine but does not start runtime services.\nIf `~/.config/kodexlink-tools/relay.env` already exists, it reuses the saved\nrelay URL instead of prompting again.\n`make enable` starts Docker, configures Tailscale Serve, and installs the\ndesktop LaunchAgent.\n\n## Daily Commands\n\n```bash\nmake help              # show available targets\nmake status            # relay containers and desktop agent status\nmake health            # local relay health\nmake curl              # local relay JSON from /healthz\nmake curl PUBLIC=1     # HTTPS relay JSON from /healthz\nmake configure-https-port HTTPS_PORT=8443\nmake doctor            # relay, Tailscale, mobile URL, privacy checks\nmake measure           # one-shot Docker CPU and memory stats\nmake logs SERVICE=relay\nmake restart           # rebuild/reapply relay compose config\nmake disable           # stop services without deleting data\nmake uninstall         # remove project-installed services and launcher\nmake enable            # start services again\n```\n\nThe lower-level script remains available for direct operations:\n\n```bash\n./scripts/kodexlink-relay.sh help\n```\n\nPrefer Makefile targets for normal use.\n\nTreat direct `tailscale ...` commands in this repository as verification or\ntroubleshooting commands unless the documentation explicitly says otherwise.\n\nIf another local service already owns host port `443`, move only the Tailscale\npublished port instead of the relay container port:\n\n```bash\nmake configure-https-port HTTPS_PORT=8443\nmake configure-url PUBLIC_URL=https://machine-name.tailnet-name.ts.net:8443\nmake enable\nmake doctor\nmake pair\n```\n\nYou can also inspect the persisted settings directly:\n\n```bash\nsed -n '1,120p' ~/.config/kodexlink-tools/relay.env\n```\n\nKeep the `kodexlink-tools` clone after installation. Runtime data lives outside\nthe clone, so already-created containers, Docker volumes, Tailscale Serve, and\nthe desktop LaunchAgent can continue to exist if the clone is deleted. However,\nthe clone contains the supported Makefile, Compose file, Dockerfile, scripts,\nand docs needed for updates, diagnostics, rebuilds, and service management.\n\n## Pairing\n\nOpen a fresh pairing panel with:\n\n```bash\nmake pair\n```\n\nThe QR code is rendered by the desktop agent, not by the relay. The phone does\nnot need to reach the local pairing panel URL; it only uses the relay URL and\nshort-lived enrollment secret inside the QR payload.\n\nPairing payloads expire after roughly five minutes and are consumed after a\nsuccessful claim. Do not store QR images, `pairingId`, `pairingSecret`, or full\nmanual pairing payloads as recovery credentials. It is useful to store only:\n\n- the private relay HTTPS URL;\n- the command `make pair`;\n- the reminder to connect Tailscale first;\n- the reminder to set the mobile app Custom Address before scanning.\n\n## Updates\n\nWhen the upstream relay or desktop CLI changes:\n\n```bash\nmake update\n```\n\nThis updates the managed upstream checkout, updates the KodexLink desktop CLI\nfrom npm, rebuilds and restarts the relay container, and refreshes the\nLaunchAgent. It does not delete Docker volumes, recreate `relay.env`, or change\nthe relay public URL, so already paired devices should remain paired. Any QR\npairing session open during the restart can expire; run `make pair` again.\n\n## Uninstall\n\nTo remove project-installed services while preserving relay data and saved\nsettings:\n\n```bash\nmake uninstall\n```\n\nThis removes the KodexLink desktop LaunchAgent, disables Tailscale Serve or\nFunnel mappings, stops the Docker Compose stack, and removes the\n`/usr/local/bin/tailscale` launcher only when it matches this repository's\nlauncher script.\n\nIt preserves:\n\n- `~/.config/kodexlink-tools/relay.env`;\n- the managed upstream relay checkout under `~/.local/share/kodexlink-tools/`;\n- Docker volumes, including paired device data.\n\nThe global KodexLink npm CLI is left installed because it may have existed\nbefore this setup. Remove it explicitly only when it was installed solely for\nthis relay:\n\n```bash\nmake uninstall-tool-cli\n```\n\n## Boot Behavior\n\nThis project does not install a separate LaunchAgent to supervise Docker\nCompose. Docker owns relay container restart behavior through\n`restart: unless-stopped`.\n\nThe relay comes back after reboot when:\n\n- it was enabled and running before Docker stopped;\n- Docker Desktop starts again after reboot or login.\n\nIf Docker Desktop is quit while the relay containers are running, Docker should\nrestart them the next time Docker Desktop starts. If the relay is intentionally\nstopped with `make disable`, `make stop`, or `docker compose down`, Docker will\nnot restart it automatically until `make enable` or `make start` runs again.\n\nIf Docker Desktop is not configured to start at login:\n\n```bash\nmake docker-start\nmake start\n```\n\nTailscale Serve persists in Tailscale background mode. The desktop agent\npersists through the upstream KodexLink macOS LaunchAgent.\n\n## Security Model\n\nRecommended private path:\n\n```text\nTailscale Serve HTTPS -\u003e localhost relay HTTP\n```\n\nTailscale Funnel is available but public. Use it only when public exposure is\nacceptable:\n\n```bash\nmake tailscale-funnel\nmake tailscale-funnel-off\n```\n\nThe relay has bearer tokens and short-lived pairing secrets, but no global admin\npassword. Treat public exposure as an internet-facing API. Keep\n`RELAY_ENABLE_DEV_RESET` disabled outside local development.\n\nRun the desktop agent on the Mac host, not in Docker. It launches\n`codex app-server`, uses the host user's Codex login, stores credentials in\nmacOS Keychain when available, and installs a macOS LaunchAgent.\n\n## Resource Use\n\nIdle smoke tests on this Mac reported roughly:\n\n- `relay`: 31-36 MiB memory;\n- `postgres`: 25-28 MiB memory;\n- `redis`: 4 MiB memory.\n\nExpect short CPU spikes during image builds and migrations, then low idle CPU.\nActual memory can grow with active WebSocket sessions, thread traffic, and\nPostgreSQL cache.\n\n## Documentation\n\n- [docs/tailscale-private-relay.md](docs/tailscale-private-relay.md): Tailscale\n  admin setup, HTTPS, Serve, optional exit nodes, and mobile setup.\n- [docs/service-and-makefile.md](docs/service-and-makefile.md): Makefile\n  workflow, boot behavior, pairing, updates, diagnostics, and recovery notes.\n- [docs/cloudflare-zero-trust-research.md](docs/cloudflare-zero-trust-research.md):\n  research notes for a future Cloudflare Zero Trust publishing mode.\n- [CHANGELOG.md](CHANGELOG.md): release history.\n\n## Project Files\n\n- `Makefile`: primary command entrypoint.\n- `docker-compose.kodexlink-relay.yml`: relay, PostgreSQL, and Redis stack.\n- `docker/relay-server.Dockerfile`: relay image build from upstream source.\n- `scripts/kodexlink-relay.sh`: lifecycle, publishing, and measurement helper.\n- `scripts/tailscale-cli-launcher`: `/usr/local/bin/tailscale` wrapper.\n- `.env.example`: non-secret configuration template.\n- `LICENSE.md`: license, upstream notice, and Tailscale disclaimer.\n\n## License\n\nThis tooling is distributed under `AGPL-3.0-only` and references the upstream\nKodexLink / Codex Mobile Relay project by David699. See [LICENSE.md](LICENSE.md)\nfor the upstream notice and Tailscale disclaimer.\n\n## References\n\n- [Tailscale Serve](https://tailscale.com/docs/features/tailscale-serve)\n- [Tailscale Funnel](https://tailscale.com/kb/1223/funnel)\n- [Tailscale CLI](https://tailscale.com/docs/reference/tailscale-cli)\n- [Tailscale HTTPS certificates](https://tailscale.com/kb/1153/enabling-https)\n- [Tailscale MagicDNS](https://tailscale.com/docs/features/magicdns)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarcomc%2Fkodexlink-tools","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmarcomc%2Fkodexlink-tools","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarcomc%2Fkodexlink-tools/lists"}