![Labby](https://raw.githubusercontent.com/dinglebear-ai/labby/main/docs/assets/brand/labby-banner.png) # Labby Rust MCP gateway with Code Mode, authentication, setup, logs, CLI, HTTP API, and operator web UI. Canonical remote: `git@github.com:dinglebear-ai/labby.git`. The root README is the public entrypoint. The topic docs in [docs/](./docs/README.md) own the detailed contracts; when this file and a topic doc disagree, fix the topic doc first and then refresh this summary. ## Contents - [What Labby Does](#what-labby-does) - [Quick Start](#quick-start) - [Core Workflows](#core-workflows) - [Runtime Surfaces](#runtime-surfaces) - [Configuration](#configuration) - [Current Catalogs](#current-catalogs) - [Architecture](#architecture) - [Development](#development) - [Documentation](#documentation) ## What Labby Does Labby is centered on the current gateway/operator surface: - **MCP gateway** - connect HTTP and stdio upstream MCP servers, inspect their tools/resources/prompts, apply exposure filters, publish protected MCP routes, and optionally collapse the upstream catalog into Code Mode `search` and `execute`. - **Direct stdio proxy** - launch one stdio MCP server with `labby proxy /path/to/dist.js` and expose its unmodified MCP surface over loopback or an owned Tailscale Serve HTTPS port with tailnet, bearer, OAuth, or explicit no-auth policy. - **Authentication and protected routes** - run bearer or OAuth authentication, manage route-scoped access, authorize upstream OAuth connections, and publish protected MCP endpoints. - **Code Mode snippets** - author, store, and run reusable JavaScript snippets against the upstream catalog, with artifacts persisted under `$LABBY_HOME`. - **Setup and doctor** - bootstrap `~/.labby`, provision the host service, and run a health audit across env, reachability, auth, and versions. - **Filesystem service** - scoped, path-safety-checked file operations exposed through the same action dispatch as every other service. - **Server logs** - search and tail the local `labby serve` log stream. - **Incus and bare-metal setup** - provision and operate a dedicated Labby gateway host without introducing a separate fleet or deployment product. - **Generated discovery** - publish code-owned service, action, environment, proxy configuration, API route, OpenAPI, MCP help, CLI help, and feature-matrix artifacts under [docs/generated](./docs/generated/README.md). Use the generated service, action, and CLI catalogs below for the complete current product surface instead of copying inventories into hand-written documentation. Standalone ACP chat, Marketplace/MCP Registry browser, Fleet, Deploy, and the old Agent Artifact Manager (Stash) remain retired; current Linux principal-scoped File Stash is a separate contract. Bounded provider-backed discovery through the `artifacts` control-plane service does not restore those products. ## Quick Start ### Install Labby Download the reviewed installer snapshot over canonical HTTPS, then run it locally: ```bash curl --proto '=https' --proto-redir '=https' --tlsv1.2 -fSLo labby-install.sh \ https://raw.githubusercontent.com/dinglebear-ai/labby/5ee609bb255bebfbd9eef4d805998ac1e084b878/scripts/install.sh sh labby-install.sh ``` This initial script is trusted through canonical HTTPS delivery and the explicitly reviewed commit snapshot above; the download does not follow a mutable branch. Its reviewed, embedded SHA-256 pins authenticate the verifier bootstrap; the installer never downloads a replacement checksum to decide which verifier to trust. It uses an installed GitHub CLI **2.102.0 or newer**, or downloads and verifies pinned 2.102.0 into a private temporary directory. It does not change your PATH or install that helper globally. Required system tools are `curl`, `tar`, and `sha256sum` or `shasum`; macOS bootstrap also uses `unzip`. Labby release archives still require checksum and provenance verification against the exact repository, release workflow, immutable tag and hosted-runner policy. Releases with `.sigstore.jsonl` bundles need no GitHub account: verification runs without tokens and with an empty credential store. Older releases without bundles require your own GitHub authentication; the installer stops before downloading their archive if authentication is unavailable. No privileged credential is supplied or shared. Installing a binary does not establish complete onboarding; the subsequent product-owned setup checks remain required. The recommended local setup uses a native service, loopback listener, generated protected credentials, and a short-lived browser handoff. In Settings, connect your Agent provider, choose a discovered model and complete a starter Agent test, register selected supported clients, then use Discover to add and verify an MCP server. Required failures remain visible and resumable; installation alone is not full readiness. No manual configuration-file edits are needed on this path. #### Optional agent-assisted guidance The checked-in `install-labby` skill helps with guided installation, advanced deployments, and repair. It is optional. To add it to a skill-aware agent: ```bash npx skills add https://github.com/dinglebear-ai/labby --skill install-labby ``` ```text $install-labby ``` The skill inspects the selected host, follows binary-owned setup operations, helps with explicitly requested advanced deployment choices, and verifies the same required first-use checks. Built-in Agent configuration and external-client registration are separate steps. Security-sensitive durable writes remain owned by the Labby binary. See [`skills/install-labby/SKILL.md`](./skills/install-labby/SKILL.md) for the canonical APM orchestration skill and [`docs/adr/0001-install-labby-first-class-install-orchestrator.md`](./docs/adr/0001-install-labby-first-class-install-orchestrator.md) for the architecture decision. #### Install through APM Teams that standardize on the [Agent Package Manager](https://microsoft.github.io/apm/) get the skills and the MCP registration in one step: ```bash apm install -g dinglebear-ai/labby ``` That deploys `install-labby`, `using-labby`, `using-codemode`, and `using-snippets` into `~/.claude/skills` and `~/.agents/skills` and registers the `labby` stdio MCP server (`npx -y @dinglebear/labby mcp`) for Claude Code and Codex; `apm.yml` at the repository root is the manifest and `apm outdated -g` reports new releases. APM does not install the `labby` binary or provision a gateway host: use the standalone installer above and `labby setup` for that. The optional `$install-labby` skill can guide those steps. #### Manual Verified Release For independent verification of the installer itself, use GitHub CLI **2.102.0 or newer**. Older versions are rejected by Labby's installer and release gates because they lack the corrected signer and source-ref verification policy. Public provenance bundles allow this verification without GitHub login; legacy attestation lookup requires your own `gh auth login` or `GH_TOKEN`. Linux/macOS: > **Release compatibility gate:** select a release that publishes `labby-install.sh` and contains the documented first-run `labby setup --role ...` interface. Confirm the selected tag exposes the installer and checksum before continuing; do not assume an older release matches the current setup contract. ```bash version=vX.Y.Z base="https://github.com/dinglebear-ai/labby/releases/download/$version" curl -fSLO "$base/labby-install.sh" curl -fSLO "$base/labby-install.sh.sha256" # For releases publishing bundles; older releases require authenticated verification. curl -fSLO "$base/labby-install.sh.sigstore.jsonl" gh attestation verify labby-install.sh \ --bundle labby-install.sh.sigstore.jsonl \ --repo dinglebear-ai/labby \ --signer-workflow dinglebear-ai/labby/.github/workflows/release.yml \ --source-ref "refs/tags/$version" \ --deny-self-hosted-runners shasum -a 256 -c labby-install.sh.sha256 LABBY_INSTALL_VERSION="$version" sh ./labby-install.sh ``` MCP clients that prefer npm launchers can run Labby through the Node wrapper: ```bash npx -y @dinglebear/labby mcp ``` The npm launcher is a weaker trust path than the installer scripts. It downloads the release archive for the current platform and verifies only the `.sha256` sidecar (or the `SHA256SUMS` manifest) published next to it on the same release; it does not require `gh` and does not verify GitHub build provenance. Use `labby-install.sh` on Linux or macOS when provenance verification matters. Current releases do not publish Windows binaries or installers. The Windows installer source uses the same reviewed verifier pins, protected temporary extraction, and account-free bundle policy; Windows runtime qualification is still required before a Windows release claim. The separately downloaded and attested install scripts resolve an immutable GitHub Release containing the current platform asset, prepare a verified GitHub CLI, verify the archive's attestation against the Labby repository, `release.yml`, exact tag, and hosted-runner policy, verify its checksum, and install `labby` onto the user PATH. The shell installer then runs `labby setup`, which asks whether this machine should run a server or connect to an existing one. Server setup configures authentication and a managed native service, or an Incus container on supported Linux hosts. Client setup saves the explicit gateway URL and configures browser sign-in or a bearer token. Desktop installation is optional and off by default; if the published desktop package is unavailable, setup reports that and still completes. For Labby's supported ChatGPT web connection, configure the server in OAuth mode and expose it through a publicly reachable HTTPS `LABBY_PUBLIC_URL`; bearer-only mode is for local/CLI clients and is not the supported ChatGPT web path. The web UI offers bearer token sign-in only over HTTPS or a direct loopback connection; behind a TLS-terminating proxy, set `LABBY_PUBLIC_URL=https://...` to unlock it. For unattended shell installs, set `LABBY_SETUP_ROLE=server` or `client` and the corresponding `LABBY_SETUP_*` options. For a binary-only install, set `LABBY_INSTALL_NO_SETUP=1`. Manual and automatic `labby host update` operations always skip first-run setup. See the [setup guide](./docs/services/SETUP.md) for examples. Override install behavior with `LABBY_INSTALL_DIR`, `LABBY_INSTALL_VERSION`, or `LABBY_INSTALL_REPO`. Source fallback is off by default. Opt in with `LABBY_ALLOW_SOURCE_FALLBACK=1`; a pinned `LABBY_INSTALL_VERSION` is passed to Cargo as the exact tag instead of silently building the default branch. Each successful install retains the verified binary by SHA-256 plus an owner-only receipt beneath `/.labby-install/`. At least the prior verified artifact remains available when distribution is unavailable. Restore it without downloading or changing `$LABBY_HOME`: ```bash LABBY_INSTALL_ROLLBACK=1 sh ./labby-install.sh ``` Rollback switches only the installed executable and receipt. It does not downgrade or delete configuration, credentials, databases, or other durable state. Inspect the receipt at `/.labby-install/receipt`. Release qualification can install an already-downloaded candidate without network or source fallback by setting `LABBY_INSTALL_LOCAL_BINARY` and its exact lowercase `LABBY_INSTALL_LOCAL_SHA256`. The installer copies that input once to private staging, verifies the staged bytes, and activates those same bytes. It also rehashes every existing cached artifact before reuse. Before changing the binary or either receipt, the installer writes a recovery journal beneath `.labby-install/`; a later invocation restores the complete pre-install snapshot when it finds an interrupted activation. If restoration fails, the installer stops and retains the journal for diagnosis. All Unix installer entry points share a process-level transaction lock and flush journal boundaries before advancing them. Successful activation retains only the current artifact and the immediately previous artifact required for offline rollback. ### Automatic updates on macOS For a persistent macOS server, enable daily updates in the existing server job: ```bash LABBY_SERVICE_AUTO_UPDATE=1 bash scripts/install-macos-service.sh install ``` This runs `labby serve --auto-update` under launchd and removes the separate updater job after the server passes its health check. See the [macOS setup instructions](docs/services/SETUP.md#macos-server-and-automatic-updates). For an installation without a persistent server, use the standalone daily job: ```bash labby host update auto enable labby host update auto status labby host update auto disable ``` Both modes require Apple Silicon. The installer uses a suitable existing GitHub CLI or bootstraps its pinned verifier in a private temporary directory. They skip drafts, prereleases, missing platform assets, and versions equal to or older than the installed binary. The installer verifies attestations and checksums before atomic replacement. No separate language runtime is required. Use `labby host update --automatic --dry-run` to check without installing. ### Build From Source Prerequisites: - Rust 1.97.1 or newer. CI/release verifies with Rust 1.97.1. - `just` for repo commands. - `cargo-nextest` for the main test suite. - Node.js 22.x and `pnpm 9.15.9` to build the Labby web UI. The repo pins these in [.mise.toml](./.mise.toml) and [apps/web/package.json](./apps/web/package.json). - `openssl` if you want to generate a bearer token manually. ```bash git clone git@github.com:dinglebear-ai/labby.git cd labby just install labby serve --host 127.0.0.1 --port 8765 ``` `just install` installs the locked frontend dependencies, builds and validates the static web UI, then embeds it in the all-features release binary and installs it at `~/.local/bin/labby`. The normal build, run, and service-install recipes also build the UI automatically before compiling Rust. Node.js and pnpm are build-time tools only; prebuilt release binaries already include the UI. On macOS, install the gateway as a persistent per-user service instead of running `labby serve` in a terminal: ```bash just macos-service-install just macos-service-status ``` This installs a `launchd` LaunchAgent that keeps Labby listening on `127.0.0.1:8765`, restarts it after login or exit, and uses the stable absolute `LABBY_HOME` (default `~/.labby`) as both working directory and durable configuration root. It never persists the directory from which installation was invoked. Logs default to the same root. Use `just macos-service-restart` after changing service settings or `just macos-service-uninstall` to remove it. The cross-platform `just service-install`, `just service-status`, `just service-restart`, and `just service-uninstall` bindings select launchd on macOS and systemd on Linux. This is suitable for a Tailscale Serve/Funnel route whose OAuth callback targets the local gateway. When overriding the launchd paths, `LABBY_SERVICE_BIN`, `LABBY_STATE_DIR`, and `LABBY_HOME` must all be absolute; relative paths fail before the plist or service is changed. ### First Run For loopback development, `labby serve` can bootstrap a missing bearer token for you. If `LABBY_MCP_HTTP_TOKEN` is absent and `LABBY_AUTH_MODE` is not `oauth`, it generates a token, writes a minimal `~/.labby/.env`, reloads it into the running process, prints configuration guidance, and continues. The token itself is stored in `~/.labby/.env` rather than printed. Bootstrap writes these required `setup` keys if no env exists yet: - `LABBY_MCP_HTTP_TOKEN` (generated random 64-character hex token) - `LABBY_MCP_TRANSPORT=http` - `LABBY_MCP_HTTP_HOST=127.0.0.1` - `LABBY_MCP_HTTP_PORT=8765` - `LABBY_AUTH_MODE=bearer` It also enforces secure file creation via Labby's `env_merge` path (`0600` perms on Unix). This is a minimal loopback bootstrap, not the guided onboarding flow. Run `labby setup` for interactive server/client configuration, or `labby setup state --json` to inspect the snapshot without changing configuration. Ongoing configuration is available in the operator UI's Settings pages. For explicit setup with a manually generated bearer token: ```bash mkdir -p ~/.labby printf 'LABBY_AUTH_MODE=bearer\nLABBY_MCP_HTTP_TOKEN=%s\n' "$(openssl rand -hex 32)" > ~/.labby/.env chmod 600 ~/.labby/.env labby setup labby serve --host 127.0.0.1 --port 8765 ``` Open `http://127.0.0.1:8765/`. Release binaries and normal source builds already include the operator UI; no separate web-assets step is needed. ### Self-Host The Gateway The recommended self-hosted gateway substrate is an amd64 Ubuntu 26.04 Incus system container. Bare metal is the secondary supported shape for a dedicated gateway host or VM. Labby does not ship a Docker image or Compose deployment; stdio MCP servers and agent CLIs are installed and launched at runtime. ```bash labby host incus setup --version vX.Y.Z incus exec labby -- systemctl status labby --no-pager incus exec labby -- curl -fsS http://127.0.0.1:8765/ready ``` See [docs/runtime/INCUS.md](./docs/runtime/INCUS.md) for the full Incus runbook, bare-metal variant, `/dev/net/tun` Tailscale passthrough, manual `claude`/`codex`/`gemini` login checklist, and rollback commands. ### Proxy One Stdio MCP Server After installing Labby, configure proxy defaults once and launch a JavaScript stdio server without proxy flags: ```bash labby config proxy set labby doctor proxy labby proxy /path/to/dist.js ``` The built-in zero-flag policy is Tailscale Serve plus tailnet authorization on a random high port. Child flags follow the first child token unchanged, and an explicit separator is available for unusual commands: ```bash labby proxy /path/to/dist.js --workspace /srv/data --read-only labby proxy -- npx -y @modelcontextprotocol/server-filesystem /srv/data ``` Use `labby proxy --local --auth none ...` for explicit loopback-only development. Bearer and OAuth setup, exact-port resource audiences, safe Serve ownership, configuration precedence, output modes, and recovery are covered in the [stdio MCP proxy guide](./docs/guides/STDIO_MCP_PROXY.md). ## Core Workflows ### Start Labby ```bash labby serve --host 127.0.0.1 --port 8765 labby mcp ``` `labby serve` starts the hosted HTTP runtime: `/v1` product APIs, `/mcp` streamable HTTP MCP, auth routes, OAuth relay endpoints, and static Labby web assets when an export is available. `labby mcp` is the stdio MCP entrypoint for local MCP clients. A client configured to launch `labby mcp` does not need an HTTP URL: when a `labby serve` daemon is reachable, the stdio process becomes a transparent bridge to that daemon and uses its gateway configuration, upstream connections, and OAuth state. If no daemon is found and no explicit target is set, it starts a standalone local gateway instead. See the [local bridge guide](./docs/surfaces/TRANSPORT.md#local-bridge-to-the-running-daemon) for client configuration and `LABBY_SERVER_URL` fail-closed behavior. ### Discover Commands ```bash labby --help labby help --all labby help server --all labby help --search oauth labby help --all --json ``` Public command names use separate words without hyphens. Flags and resource names retain normal syntax. Help and completion work offline, even with broken configuration. See the [CLI guide](./docs/surfaces/CLI.md) and [breaking migration map](./docs/generated/cli-migration.md). ### Select A Gateway ```bash labby context add homelab --server https://example.invalid --use labby auth login --context homelab labby --context homelab server list labby config check ``` Contexts save non-secret destinations in the existing host configuration. Explicit `--server` or `--context` never borrows an unrelated environment token and never falls back to local execution. Host-local commands remain local. ### Manage Upstream MCP Servers ```bash labby server add github \ --url https://example.com/mcp \ --bearer-token-env GITHUB_MCP_TOKEN labby gateway reload labby server list ``` Stdio upstreams can execute local commands when tested or reconciled. Review configuration before adding or testing them; the CLI retains each operation's existing authorization and confirmation requirements. The stdio spawn guard allows known runtimes such as `npx`, `uvx`, `docker`, `node`, `python`, `python3`, `deno`, `pipx`, and `dnx`; customize it in `[gateway]` inside `config.toml`. Missing creation arguments can be filled by `labby server add` in an interactive terminal. Scripts should use complete arguments and `--no-input --json`. Timeouts use explicit units, such as `30s` or `2m`. ```bash labby server restart alpha beta --timeout 30s labby server restart --all --dry-run labby --context homelab completions refresh labby completions zsh --resources ``` Restart waits for observed completion and a connected replacement unless `--no-wait` is explicit. Bulk operations report every target and return a failing exit status when any target fails; uncertain operations are never replayed. Optional cached completion is authority-scoped and offline on every Tab key. ### Use Code Mode When `[code_mode].enabled = true`, Labby hides raw proxied upstream tools from MCP `list_tools()` and exposes the canonical synthetic `codemode` tool. ```bash labby code status labby code enable labby code search 'github issues' --limit 5 labby code describe github.search_issues labby code run --file ./task.js ``` MCP call shapes: ```json { "code": "async () => (await codemode.search({\"query\":\"github issues\",\"limit\":5})).results" } ``` ```json { "code": "async () => callTool(\"github::search_issues\", {\"query\":\"repo:dinglebear-ai/labby gateway\"})" } ``` ```json { "code": "async () => codemode.run(\"gateway-summary\", {\"includeHealth\": true})" } ``` Code Mode can call exposed upstream tools and eligible catalog-admitted in-process Labby actions. Route, Loadout, caller, and action policy still apply; sandbox access does not grant unrestricted administration. ### Work With Code Mode Snippets ```bash labby snippet list labby snippet get gateway-summary labby snippet add my-snippet --file ./my-snippet.js labby snippet validate my-snippet labby snippet run my-snippet labby snippet test my-snippet ``` Snippets are stored per-user under `$LABBY_HOME` and executed through the gateway Code Mode runner, so they can reach exposed upstream tools and eligible catalog-admitted in-process actions. The `snippets` service is gateway-gated: it is unavailable in builds without the `gateway` feature. ### Audit Health And Logs ```bash labby doctor # system, auth, gateway, and relay audit labby doctor system # local env vars, disk, toolchain labby doctor auth # auth/OAuth env vars, files, permissions labby doctor proxy # zero-route stdio-proxy config/dependency preflight labby doctor proxy --app-url URL --mcp-url URL --route /path # routed public reverse-proxy checks remain available labby doctor relay labby gateway status # query the selected daemon and its upstream state labby logs --lines 50 # bounded local rolling logs, without systemd labby logs --level error --query REQUEST_ID --json labby logs journal --follow # explicitly stream the deployment journal ``` `labby doctor --json` is the CI-friendly form; the exit code reflects the worst severity found. Runtime errors include their command, origin, side-effect classification, recovery guidance, and a request ID. `--json` errors remain one JSON envelope on stderr; command results stay on stdout. Use `-v` or `-vv` for diagnostics. `--quiet` suppresses console logs but never hides the actual error. > **Removed surfaces.** Earlier releases documented `labby marketplace`, > `labby stash`, `labby nodes`, and `labby deploy`, along with ACP chat, the MCP > Registry browser, and device/fleet runtimes. Those products have been deleted > from source, manifests, packaging, and CI — not merely feature-gated. > `scripts/check-retired-features.sh` guards against reintroduction, and the > historical designs are archived under > [docs/archive/retired-labby](./docs/archive/retired-labby/). Plugin > marketplace assets now live in the separate > [dendrite](https://github.com/dinglebear-ai/dendrite) repo. ### Drive The API Generic action dispatch: ```bash curl -s -X POST http://127.0.0.1:8765/v1/gateway \ -H "Authorization: Bearer $LABBY_MCP_HTTP_TOKEN" \ -H "Content-Type: application/json" \ -d '{"action":"gateway.list","params":{}}' ``` Dedicated product routes also exist for catalog discovery (`/v1/{service}/actions`), setup, doctor, snippets, filesystem, server logs, gateway OAuth (`/v1/gateway/oauth/*`), OAuth relay, auth allowlists (`/v1/auth/allowed-emails`), `/v1/openapi.json`, interactive API docs at `/v1/docs`, and the browser session routes under `/auth/*`. See [generated API routes](./docs/generated/api-routes.md) and [OpenAPI](./docs/generated/openapi.json). ## Runtime Surfaces | Surface | Entry Point | Notes | | --- | --- | --- | | CLI | `labby ` | Current commands are generated in [docs/generated/cli-help.md](./docs/generated/cli-help.md). Use `--json` for machine-readable output and `--color auto|plain|color` for human output styling. | | MCP stdio | `labby mcp` | Local editor/desktop MCP clients. | | MCP HTTP | `labby serve` plus `/mcp` | Streamable HTTP MCP with bearer or OAuth JWT auth. | | HTTP API | `labby serve` plus `/v1/*` | Generic `POST /v1/{service}` action dispatch plus dedicated product routes. | | Web UI | `labby serve` plus exported assets | Main routes are `/` (overview), `/gateways`, `/gateway`, `/snippets`, `/usage`, `/settings` (with `core`, `services`, `services/[service]`, `surfaces`, `features`, `doctor`, `extract`, `advanced` subpages), `/docs`, `/design-system`, and `/mcp/code-mode`. | MCP service tools use the shared action shape: ```json { "action": "gateway.list", "params": {} } ``` Every service tool also supports `help` and `schema` through the shared dispatcher. Destructive MCP actions require the MRTR elicitation exchange. Clients without form elicitation receive `confirmation_required`; `params.confirm` does not authorize execution. ## Configuration Configuration is split deliberately: | Data | Location | Examples | | --- | --- | --- | | Secrets and endpoint values | `$LABBY_HOME/.env` | `LABBY_MCP_HTTP_TOKEN`, `LABBY_GOOGLE_CLIENT_SECRET`, upstream bearer token env values | | Preferences | `$LABBY_HOME/config.toml` | transport, CORS, auth mode, workspace root, gateway spawn guard, and upstream behavior | `LABBY_HOME` selects the one authoritative configuration and durable-state root and must be absolute. It defaults to `~/.labby`; Labby does not implicitly read CWD or XDG fallback files. Existing process environment values win over values loaded from the selected `.env`. Runtime precedence is: 1. CLI flags 2. Environment variables 3. `config.toml` 4. Built-in defaults Useful environment variables: | Variable | Purpose | | --- | --- | | `LABBY_MCP_HTTP_TOKEN` | Static bearer token for protected admin/API/MCP routes. | | `LABBY_AUTH_MODE` | `bearer` or `oauth`. | | `LABBY_PUBLIC_URL` | Public base URL for OAuth metadata, issuer/audience, callbacks, and allowed-host derivation. | | `LABBY_AUTH_PROVIDER` | Inbound OAuth identity provider: `google` (stable) or `authelia` (open beta). | | `LABBY_GOOGLE_CLIENT_ID` / `LABBY_GOOGLE_CLIENT_SECRET` | Google credentials when Google is selected. | | `LABBY_AUTHELIA_ISSUER_URL` / `LABBY_AUTHELIA_CLIENT_ID` / `LABBY_AUTHELIA_CLIENT_SECRET` | Authelia OIDC configuration; see the pinned registration contract in the OAuth guide. | | `LABBY_AUTH_ADMIN_EMAIL` | Administrator email or comma-separated emails; required in OAuth mode. | | `LABBY_OAUTH_ENCRYPTION_KEY` | Base64 32-byte key required for encrypted upstream OAuth credentials. Rotation requires reauthorizing affected upstreams. | | `LABBY_WEB_ASSETS_DIR` | Override static Labby export directory. | | `LABBY_WEB_UI_AUTH_DISABLED` | Development-only browser auth bypass. | | `LABBY_LOG` / `LABBY_LOG_FORMAT` / `LABBY_LOG_COLOR` | Tracing filter, text/json format, and non-TTY color policy. | | `LABBY_LOG_DIR` | Optional rolling JSON file log directory. | | `LABBY_ACTOR_KEY_SECRET` | Stable secret for redacted actor correlation in logs. | | `LABBY_ADMIN_ENABLED` | Runtime opt-in for the `lab_admin` tool. | Static bearer authentication establishes an operator transport ceiling, not a universal durable administrator grant. Operation-specific access authority still applies. Public protected MCP routes validate route-scoped Labby OAuth JWTs; do not treat `LABBY_MCP_HTTP_TOKEN` as a public resource credential. When driving the web UI with automation while OAuth is enabled, pass the bearer token as a same-origin header. `/auth/session` recognizes that token and returns an authenticated session projection whose authority depends on durable access state; a bearer credential does not universally grant durable administration: ```bash TOKEN=$(awk -F= '/^LABBY_MCP_HTTP_TOKEN=/{print $2}' ~/.labby/.env) agent-browser open http://127.0.0.1:8765/gateways \ --headers "{\"Authorization\":\"Bearer $TOKEN\"}" ``` See [runtime configuration](./docs/runtime/CONFIG.md), [environment variables](./docs/runtime/ENV.md), and [OAuth](./docs/runtime/OAUTH.md). ## Current Catalogs Do not maintain action, feature, env, or coverage inventories by hand in this README. The generated artifacts describe the all-feature documentation projection. Runtime feature, platform, startup, route, and caller authorization gates still determine what a running gateway exposes: | Artifact | Purpose | | --- | --- | | [service-catalog.md](./docs/generated/service-catalog.md) | Service metadata, conditional registration, features, categories, and supported surfaces. | | [action-catalog.md](./docs/generated/action-catalog.md) | Per-service actions and destructive metadata. | | [env-reference.md](./docs/generated/env-reference.md) | Env vars generated from service metadata. | | [api-routes.md](./docs/generated/api-routes.md) | Mounted HTTP routes. | | [openapi.json](./docs/generated/openapi.json) | OpenAPI 3.1 schema. | | [feature-matrix.md](./docs/generated/feature-matrix.md) | Cargo feature invariants. | | [mcp-help.md](./docs/generated/mcp-help.md) | MCP help projection. | | [cli-help.md](./docs/generated/cli-help.md) | Clap command help snapshot. | Refresh and verify them with: ```bash just docs-generate just docs-check ``` `labby docs check` verifies generated-artifact freshness and invariants. The `just docs-check` recipe also checks Markdown links, documentation policy, instruction topology, and control-plane contracts with their regression tests. Neither establishes live service health or deployment acceptance. Fix generated content at the entrypoints in the [source-ownership index](./docs/generated/README.md), then regenerate; that index is itself generated. ## Architecture The workspace uses Rust 2024, resolver 3, a single `[workspace.package]` version, shared `[workspace.dependencies]`, and shared `[workspace.lints]` (`unsafe_code = "forbid"`, `mod_module_files = "deny"`, `disallowed_macros = "deny"`). The member inventory and exact Git-pinned MCP SDK revision are maintained in [Cargo.toml](./Cargo.toml); [Architecture](./docs/ARCH.md) owns the complete crate map. | Path | Role | | --- | --- | | [crates/labby-primitives](./crates/labby-primitives) | Workspace dependency-leaf crate: `ActionSpec`/`ParamSpec`, `PluginMeta`/`EnvVar`/`Category`, `UiSchema`, static SSRF checks. | | [crates/labby-apis](./crates/labby-apis) | Pure SDK contracts for core HTTP behavior, setup, doctor, and Artifact control; no ambient product configuration. | | [crates/labby-auth](./crates/labby-auth) | OAuth/JWT/session middleware, route support, and upstream OAuth runtime. | | [crates/labby-runtime](./crates/labby-runtime) | Surface-neutral contracts and helpers: `ToolError`, gateway config DTOs, dispatch helpers, redaction, path safety, and security helpers. | | [crates/labby-codemode](./crates/labby-codemode) | Client-neutral Code Mode runner kernel, broker, result shaping, snippets, and TypeScript descriptor generation. | | [crates/labby-gateway](./crates/labby-gateway) | Gateway manager, upstream MCP proxy pool, Code Mode host adapter, discovery/imports, virtual servers, protected routes, and OAuth lifecycle. | | [crates/labby-openapi](./crates/labby-openapi) | OpenAPI-to-Code-Mode derivation and hardened outbound HTTP execution. | | [crates/labby-browser](./crates/labby-browser) | Reusable browser bridge, pairing, permission, and invocation runtime. | | [crates/labby-model](./crates/labby-model) | Model-checking and verification support; never a product dependency. | | [crates/labby-web](./crates/labby-web) | Embedded/filesystem web asset serving with symlink escape defense. | | [crates/labby](./crates/labby) | Product binary crate: CLI, MCP, HTTP API, config loading, gateway dispatch, logs, setup, snippets, filesystem access, and output rendering. | | [crates/labby-winjob](./crates/labby-winjob) | Windows Job Object process-tree support, isolated so the main workspace can keep `unsafe_code = "forbid"`. | | [crates/xtask](./crates/xtask) | Repo automation tasks; not published. | | [apps/web](./apps/web/README.md) | Labby web UI, statically exported and served by `labby serve`. | | [packages/labby-mcp](./packages/labby-mcp) | npm launcher wrapper behind `npx -y @dinglebear/labby mcp`. | | [plugins](./plugins) | Claude/Codex plugin assets and skills. | | [docs](./docs/README.md) | Topic documentation and generated inventories. | Shared operations belong in the owning extracted runtime or product dispatch. `labby-gateway` owns upstream discovery, routing, OAuth lifecycle, and the gateway Code Mode host; `labby-codemode` owns the host-neutral kernel. `labby-apis` remains a pure SDK boundary. Product adapters under `crates/labby/src` translate input, caller context, and output without duplicating authorization, validation, or operation semantics. See [Architecture](./docs/ARCH.md) and [Dispatch](./docs/dev/DISPATCH.md). ## Development Read the canonical [AGENTS.md](./AGENTS.md), the [development workflow](./docs/dev/DEVELOPMENT.md), and the nearest nested instructions before changing code. `CLAUDE.md` and `GEMINI.md` are compatibility symlinks to AGENTS.md. See [documentation maintenance](./docs/dev/DOCUMENTATION.md) for documentation ownership and checks. Builds and tests do not update an installed gateway. The install, service, host-sync, and auth-disabled local-preview commands below are separate opt-in operations, not routine validation steps. Prefer the `just` aliases: ```bash just check # cargo check --workspace --all-features just test # cargo nextest run --workspace --all-features just test-integration # cargo nextest run --workspace --all-features --run-ignored ignored-only just lint # skill drift + toolchain sync + module reachability + clippy + fmt just docs-check # generated freshness + links + documentation policy and regressions just rustdoc-check # strict Rustdoc + workspace doctests just deny # cargo deny check just build # web export + optimized all-features Rust build just build-release # web export + release build and binary installation just service-install # build and install the native persistent gateway service just service-status # inspect the native service manager state labby host service install --install-self -y # install current binary + start system service labby host service restart --install-self -y # reinstall current binary + restart service labby host service status --json # inspect the host Labby gateway service just host-sync # repo dev shortcut: rebuild + install binary + restart host service just web-build # locked dependency install + validated static UI export just web-watch # rebuild web assets when frontend files change just run -- help # web export + cargo run --all-features -- just chat-local # local Labby admin UI workflow with browser auth disabled just install # web export + release build + install ~/.local/bin/labby just mcp-token # rotate checkout .env token and print it; not daemon secret rotation ``` Use all-feature workspace verification plus affected standalone feature slices: ```bash cargo check --workspace --all-features cargo clippy --workspace --all-features -- -D warnings cargo nextest run --workspace --all-features cargo build --workspace --all-features ``` Direct Cargo commands are low-level backend development paths: they do not build the frontend and may embed no UI in a clean checkout. Use `just build` or `just install` to produce a complete gateway binary. `just check`, `just test`, and `just lint` do not invoke the frontend build; `just web-build` is an optional frontend-only command, not a prerequisite users need to run separately. CI uses the same posture and runs nextest with its CI profile. Use `cargo test` only for narrow local slices or when a tool specifically requires it. Frontend changes should also run the relevant `pnpm` scripts under `apps/web`, and `just web-build` when exported assets matter. ### Host Gateway Runtime The recommended self-hosted gateway runtime is the Incus system container provisioned by `labby host incus setup --version vX.Y.Z` and converged in-box with `labby setup --provision`. Bare metal uses the same provisioner and system unit when the host or VM is dedicated to Labby. The default service is `/etc/systemd/system/labby.service`, running as `User=labby`, `Group=labby`, with `ExecStart=/usr/local/bin/labby serve`. From a source checkout, `just host-sync` remains the rebuild-and-restart developer shortcut. ### Releases Release Please maintains the version/changelog pull request and creates the stable tag plus draft GitHub release when that pull request merges. The stable tag triggers the heavy GitHub-hosted candidate workflow. It builds Linux and macOS archives with checksums, publishes the npm launcher, and publishes Labby's `server.json` metadata to the official MCP Registry. Only after qualification and publication succeed does the workflow promote the draft GitHub release. Incus substrate images build and publish independently through `.github/workflows/incus-image.yml`; normal binary releases do not build an image. ### Plugin Setup `plugins/labby` supplies usage skills; `plugins/install-labby` owns the installer skill, MCP configuration, and `userConfig`. Neither bundles the Labby binary or automatic lifecycle hooks. The former `plugins/labby/hooks/hooks.json` (SessionStart / ConfigChange shims) has been removed; operators run `labby setup` themselves. Do not reintroduce a `hooks/` directory, bundle a binary under `plugins/labby/bin/`, or add Docker/systemd bootstrap logic to plugin assets. `just validate-plugin` runs the supported read-only `labby setup check` flow against an isolated Labby home. Plugin lifecycle hooks and per-service plugin mutation commands remain retired. ## Related Servers - [soma](https://github.com/dinglebear-ai/soma) - RMCP runtime for provider-backed MCP servers. - [unifi-rmcp](https://github.com/dinglebear-ai/runifi) - UniFi controller REST API bridge. - [tailscale-rmcp](https://github.com/dinglebear-ai/rtailscale) - Tailscale API bridge for devices, users, and tailnet operations. - [unraid](https://github.com/dinglebear-ai/unraid) - Unraid monorepo; the Rust GraphQL bridge (`runraid`) lives in `unraid-rs/`. - [apprise-rmcp](https://github.com/dinglebear-ai/rapprise) - Apprise notification fan-out bridge for many delivery backends. - [gotify-rmcp](https://github.com/dinglebear-ai/rgotify) - Gotify push notification bridge for sends, messages, apps, and clients. - [arcane-rmcp](https://github.com/dinglebear-ai/rarcane) - Arcane Docker management bridge for containers and related resources. - [ytdl-rmcp](https://github.com/dinglebear-ai/rytdl) - Media download and metadata workflow server. - [synapse-rmcp](https://github.com/dinglebear-ai/synapse) - Local Synapse workflow server for scout and flux actions. - [cortex](https://github.com/dinglebear-ai/cortex) - Syslog and homelab log aggregation MCP server. - [axon](https://github.com/dinglebear-ai/axon) - RAG, crawl, scrape, extract, and semantic search project. ## Documentation Start at [docs/README.md](./docs/README.md). High-value entrypoints: - [Architecture](./docs/ARCH.md) - [Configuration](./docs/runtime/CONFIG.md) - [Environment](./docs/runtime/ENV.md) - [OAuth](./docs/runtime/OAUTH.md) - [Transport](./docs/surfaces/TRANSPORT.md) - [Gateway](./docs/services/GATEWAY.md) - [Setup](./docs/services/SETUP.md) - [Server Logs](./docs/services/SERVER_LOGS.md) - [Testing](./docs/dev/TESTING.md) - [Operations](./docs/OPERATIONS.md) ## License Original Dinglebear-authored portions of this project are licensed under [AGPL-3.0-only](LICENSE). The same file records the project-specific scope, third-party treatment, contribution policy, and availability of separately negotiated commercial terms.