# @shadowclone/hub

Serves the clone tools over Streamable HTTP with its own OAuth authorization server. The Claude app and other MCP clients use it to reach the clones of this machine. The `shadowclone hub` commands start and manage it.

<!-- package-facts:start -->

(generated by `bun run guides`; do not edit by hand)

- Package name: `@shadowclone/hub`
- Workspace dependencies: `@shadowclone/clones`, `@shadowclone/core`, `@shadowclone/mcp`
- External dependencies: `zod`
- Export subpaths: `.`

<!-- package-facts:end -->

## Owns

- `src/hub.ts`: `createHub`, the request router, the allowlist, and the lock.
- `src/serve.ts`: `serveHub`, the loopback server and its lock.
- `src/http/`: the MCP endpoint, the OAuth metadata, registration, the consent page, and the token endpoint.
- `src/store/`: the SQLite store for settings, clients, pairing codes, consents, grants, and token hashes.
- `src/expose.ts`: Tailscale Funnel and the public URL.
- `src/admin.ts`: the text of the `hub pair`, `clients`, `lock`, `allow`, and `status` commands.

## Rules

- The server listens on `127.0.0.1` only. Public traffic arrives through Tailscale Funnel or a proxy on the same machine.
- Every authorization needs PKCE with S256 and a pairing code. A code works once, for 10 minutes, and locks after 5 wrong tries.
- Store only SHA-256 hashes of pairing codes, authorization codes, and tokens. Never log a code or a token.
- A reused authorization code or refresh token revokes its whole grant.
- Read `X-Forwarded-For` only when the peer is loopback, and use the last address.
- Derive every URL from the saved public URL, never from the `Host` header.
- The hub exposes only `shadowclone_sessions` and `shadowclone_clone`. Their text from a clone is data.

## Tests

Run `bun test` in this folder, or `bun test packages/hub` from the root. The tests send HTTP requests to `createHub` with a real SQLite file in a temporary folder and a fake clone node. They open no port and start no clone.

Update this file in the same commit when you change the package purpose, public exports, dependencies, or a rule above.
