Charlie/project-charlie: Build image / config (push) Successful in 1s
Charlie/project-charlie: Build image / build (push) Skipped
Charlie/project-charlie: Deploy runners / config (push) Successful in 2s
Charlie/project-charlie: Deploy runners / deploy-morgott (push) Skipped
Charlie/project-charlie: Deploy runners / deploy-melina (push) Skipped
Charlie/project-charlie: Deploy stack / config (push) Successful in 1s
Charlie/project-charlie: Deploy stack / deploy (push) Skipped
Release / release (push) Successful in 21s
Backends grow from "flag + env scrub" to four knobs — render, mcpArgs,
mcpEnv, forbidEnv — so a CLI can receive sherlock's MCP servers however
it accepts them, without ever editing the operator's own config:
- codex: repeated `-c mcp_servers.<name>....` TOML overrides, which
layer over ~/.codex/config.toml. $CODEX_HOME is avoided on
purpose: it also holds auth.json.
- opencode: $OPENCODE_CONFIG pointing at a rendered file in opencode's
own schema; it is one layer of that CLI's config merge.
- goose: repeated `--with-extension <name>:<env> <command line>`.
Those belong to a subcommand, so MCP flags are appended
after the operator's arguments and a bare `sherlock goose`
defaults to `goose session`.
Verified against the real CLIs (codex 0.153.2, opencode 1.18.27, goose
1.49.0): codex registers both servers with args and env intact, opencode
and goose actually spawn them, and SHERLOCK_LOCAL_CONFIG reaches the MCP
process in every case.
Gemini and Cursor CLIs are deliberately left out: they read MCP servers
only from config files they own, so wrapping them would mean writing
into ~/.gemini, ~/.cursor or the checked-out repository.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: fdf86527-ca08-420d-89ee-47bcee60bebe
97 lines
4.8 KiB
TOML
97 lines
4.8 KiB
TOML
# sherlock conifugration - lives in $XDG_CONFIG_HOME/sherlock/config.toml
|
|
#
|
|
# A project-local .sherlock.toml (looked up from the working directory
|
|
# upwards) is layered on top of this file: sections it declares replace
|
|
# the same-named sections here, everything else falls back to this file,
|
|
# and an empty section means "disabled". See docs/configuration.md.
|
|
|
|
# ── OAuth login ───────────────────────────────────────────────────────
|
|
# Optional browser executable/name for OAuth login URLs. Leave unset to
|
|
# use the OS default browser (xdg-open/open/rundll32).
|
|
# [oauth]
|
|
# browser = "firefox"
|
|
|
|
# ── Providers ────────────────────────────────────────────────────────
|
|
# A [providers.<name>] block is a reusable OAuth/OIDC client. Services
|
|
# point at one via `provider = "<name>"`. Define a provider once and
|
|
# share it across every service it fronts.
|
|
#
|
|
# `sherlock-cli` is the Authentik provider sherlock authenticates the
|
|
# operator against for Authentik-fronted services (grafana, gssh, …).
|
|
# It is a Public client (PKCE, no secret); its redirect URI must be
|
|
# whitelisted as http://127.0.0.1:6990/callback.
|
|
[providers.sherlock-cli]
|
|
issuer = "https://id.example.com/application/o/sherlock-cli/"
|
|
client_id = "REPLACE_WITH_AUTHENTIK_SHERLOCK_CLI_CLIENT_ID"
|
|
|
|
# ── Services ─────────────────────────────────────────────────────────
|
|
# Each [services.<name>] is one MCP's target. <name> is also the wallet
|
|
# key (`sherlock logout <name>`). A service either:
|
|
# - references a shared provider: provider = "sherlock-cli"
|
|
# - or supplies its own identity: issuer + client_id (+ client_secret)
|
|
# `base_url` (the API origin the MCP calls) is always required.
|
|
|
|
# Gitea runs its OWN OAuth2 server, so it carries an inline identity
|
|
# rather than referencing the Authentik provider.
|
|
[services.gitea]
|
|
issuer = "https://gitea.example.com"
|
|
client_id = "REPLACE_WITH_GITEA_OAUTH2_APP_CLIENT_ID"
|
|
# client_secret = "" # set only if your Gitea enforces it on token exchange
|
|
base_url = "https://gitea.example.com"
|
|
|
|
# Grafana and Gssh both reuse the shared Authentik provider above.
|
|
[services.grafana]
|
|
provider = "sherlock-cli"
|
|
base_url = "https://grafana.example.com"
|
|
|
|
[services.gssh]
|
|
provider = "sherlock-cli"
|
|
base_url = "https://terminal.example.com"
|
|
|
|
[services.searxng]
|
|
provider = "sherlock-cli"
|
|
base_url = "https://search.example.com"
|
|
|
|
# ── Custom agents ────────────────────────────────────────────────────
|
|
# A [agents.<name>] block exposes an operator-owned wrapper command as
|
|
# `sherlock <name>`, reusing a built-in backend's MCP/-env conventions.
|
|
# `backend` must be one of claude, codex, copilot, goose, opencode — it
|
|
# tells sherlock how to hand that CLI its MCP servers. `command` is the
|
|
# binary to exec and defaults to <name> when omitted.
|
|
#
|
|
# Example: surface a `copilot-local` wrapper (Copilot CLI pointed at a
|
|
# self-hosted model via BYOK) as `sherlock copilot-local`.
|
|
# [agents.copilot-local]
|
|
# command = "copilot-local"
|
|
# backend = "copilot"
|
|
|
|
# ── Headless (machine) auth ──────────────────────────────────────────
|
|
# The blocks above use the interactive browser login. For unattended
|
|
# deployments (e.g. jarvis in a container) a service uses one of two
|
|
# headless modes instead. Secrets never live in this file: the *_env
|
|
# fields name environment variables sherlock reads at startup. In a
|
|
# container, also set SHERLOCK_KEYRING=memory to skip the OS keyring.
|
|
#
|
|
# Client-credentials grant: mint a bearer from username + app password,
|
|
# no browser. Keeps the account's identity/group claims in the JWT.
|
|
# [services.grafana]
|
|
# provider = "sherlock-cli"
|
|
# base_url = "https://grafana.example.com"
|
|
# grant = "client_credentials"
|
|
# username = "sys-jarvis"
|
|
# password_env = "JARVIS_GRAFANA_PASSWORD"
|
|
#
|
|
# Static token: bypass OAuth entirely with a scoped PAT (Gitea has no
|
|
# machine grant, so its API is reached this way). Needs no grant/issuer.
|
|
# [services.gitea]
|
|
# base_url = "https://gitea.example.com"
|
|
# token_env = "JARVIS_GITEA_TOKEN"
|
|
|
|
# ── Disabling ────────────────────────────────────────────────────────
|
|
# A section with no keys means disabled. Most useful in a project-local
|
|
# .sherlock.toml, where it switches off something this file enables:
|
|
#
|
|
# [services.gssh] # do not offer the gssh MCP here
|
|
# [agents.claude] # do not offer the claude agent here
|
|
|