llm-cli-gateway
"Without consultation, plans are frustrated, but with many counselors they succeed." — Proverbs 15:22 (LSB)
Secure local control plane for AI coding agents.
llm-cli-gateway lets supported MCP clients operate Claude Code, Codex, Gemini/Antigravity, Grok Build, Mistral Vibe, Cognition Devin, Cursor Agent, and configured HTTP API providers through one user-owned gateway while preserving native CLI sessions, local credentials, durable async jobs, validation receipts, and review workflows.
Why developers try it: use the client you are already in to delegate work to local coding agents, scope remote execution to registered workspaces, gate risky actions, survive disconnects, and collect auditable review evidence without turning those agents into a generic chat proxy.
Current signals: CI and security workflows pass on main, OpenSSF Scorecard is published, OpenSSF Best Practices is passing, releases use Sigstore signing, and the package is MIT licensed.
Quick Start
npm install -g llm-cli-gateway
Or use directly with npx from an MCP client:
{
"mcpServers": {
"llm-gateway": {
"command": "npx",
"args": ["-y", "llm-cli-gateway"]
}
}
}
What It Provides Today
llm-cli-gateway is a single-user MCP control plane for operating AI coding agents from supported local or remote clients. It is more than a thin CLI wrapper:
- Runs registered provider CLIs and configured HTTP API providers through consistent sync and async MCP tools.
- Persists long-running jobs, supports restart-safe result collection, deduplication, cancellation, and sync-to-async deferral.
- Tracks sessions, real CLI resume paths, structured response metadata, and cache telemetry.
- Supports cache-aware
promptParts, including explicit Claudecache_controlwhen opted in. - Can run supported provider requests inside gateway-managed git worktrees for isolated multi-agent review and implementation loops when using the local file-backed session manager. PostgreSQL-backed sessions reject this filesystem-local feature before creation. Grok, Devin, and Mistral require an explicit provider-native
sessionIdfor a gateway worktree; fresh,createNewSession, andresumeLatest-only worktree requests fail closed because they cannot durably reselect it. Materialization suppresses repository, system, and global Git hooks, configured clean, smudge, and process checkout filters, sparse checkout, and lazy object fetching. Filter-dependent content such as Git LFS remains in its repository representation instead of executing host commands. - Ships personal-appliance setup surfaces: HTTP transport with bearer-token auth,
doctor --json, setup UI artifacts, provider setup snippets, Docker fallback, and checked release bundles. - Remote web connectors use MCP OAuth discovery and authorization-code setup with static client or shared-secret gates. Client secrets are generated locally, stored only as hashes, and printed only by explicit copy-once commands.
- Provider CLI requests can select registered workspaces by alias via
workspace; every HTTP/tunnel request must use a registered alias, session workspace, or[workspaces].defaultbefore provider execution. Local unrestricted filesystem access is the stdio transport.
Workflow Assets
The repo ships agent-ready workflow skills under .agents/skills for async orchestration, session continuity, multi-LLM review, implement-review-fix loops, retrospective evidence walks, secure approval-gated dispatch, and Personal Agent Config Kit operations. Nine caller-facing skills are bundled in the published npm package: async-job-orchestration, multi-llm-review, session-workflow, secure-orchestration, implement-review-fix, retrospective-walk, public-demo-session, least-cost-routing, and personal-agent-config-kit. Machine-readable DAG-TOML plans live under docs/plans and setup/install-plan.dag.toml for workflows that need deterministic sequencing and verification gates.
Skill packs can be updated outside the core npm release by placing skill
directories in local, operator-controlled paths. The gateway loads bundled
skills first, then [skills].paths, then LLM_GATEWAY_SKILLS_PATH, then
~/.llm-cli-gateway/skills when it exists; later roots override earlier skills
by name. Each skill is a directory containing SKILL.md. A root may also carry
skill-pack.json to pin expected SKILL.md hashes:
[skills]
paths = ["/opt/llm-cli-gateway/skills"]
export LLM_GATEWAY_SKILLS_PATH="/opt/team-skill-pack:/opt/incident-skill-pack"
{
"name": "team-pack",
"version": "1.0.0",
"skills": [
{
"name": "incident-retrospective",
"sha256": "<sha256 of incident-retrospective/SKILL.md>"
}
]
}
The loader is intentionally local-only: it never fetches remote Markdown at
startup. To update a pack, install or replace files through your package manager
or deployment system, then restart the gateway so the advertised skills://...
resources refresh.
The next documentation focus is provider-specific skill and DAG-TOML pairs for each outbound CLI and API-provider family: Claude, Codex, Gemini/Antigravity, Grok, Mistral Vibe, Devin, Cursor Agent, OpenAI-compatible endpoints, Anthropic Messages, and xAI Responses. The implementation plan is tracked in docs/plans/provider-workflow-assets.dag.toml, with each provider asset expected to cover install/login checks or token-env checks, session behavior, approval modes, cache/telemetry surfaces, failure modes, and a smoke-test gate.
Trust & Supply Chain
- CI runs build, lint, format, tests, package checks, and npm audit.
- Security CI runs actionlint, zizmor, shellcheck, typos, osv-scanner, gitleaks, and lychee.
- GitHub release installer artifacts are checksummed and signed with Sigstore keyless signing.
- npm releases use a generated prod-only shrinkwrap and release security audit; GitHub Actions Trusted Publishing exchanges the job's OIDC identity for short-lived npm publish credentials.
- The npm package intentionally ships a generated, prod-only
npm-shrinkwrap.jsonso registry installs resolve the audited release tree. Release gates regenerate it frompackage-lock.json, compare for parity, and run a registry-fidelity consumer install before publishing. - Socket behavioural alerts are documented in
socket.ymland under "Security Considerations" below.shellAccessandshrinkwrapare reviewed package capabilities/configuration for this CLI appliance, not hidden install behaviour.
Personal MCP Appliance
The personal-appliance contract keeps that surface intentionally narrow: one trusted user runs the gateway on a machine or volume they own, connects one MCP endpoint, and lets supported clients operate local coding agents through workspace-scoped, approval-gated, auditable requests.
The product contract is documented in docs/personal-mcp/PRODUCT_CONTRACT.md. It defines the single-user scope, security posture, target support matrix, and provider-support verification gates. Public setup guides must not claim ChatGPT, Claude web, Claude Desktop, Codex, Gemini CLI, Gemini web, or Grok inbound support until the corresponding provider/client path has been verified.
This project does not provide hosted multi-tenant credential custody. Provider credentials stay on the user's machine or user-owned deployment volume.
For a single developer who works on several workstations and repositories, the Personal Agent Config Kit guide explains the Git-synchronised personal baseline, repository overlays, immutable context stamps, and workstation-safe provider continuity model. The baseline directory is confined to a non-symlinked descendant of the local home directory, and every publish or sync revalidates its configured origin fetch and push URLs against the HTTPS/SSH-only policy. The Kit is intentionally local-caller-only; Kit provider execution and recovery of an unadmitted attempt require healthy durable SQLite or PostgreSQL async-job admission. Kit scope never inherits the gateway process cwd: Claude requires a registered workspace selection or configured default, while Codex can also use an explicit absolute workingDir. Relative Kit workingDir values are rejected before filesystem or Git inspection. It disables cross-model validation tools while enabled and is not an HTTP/OAuth configuration or remote execution feature.
For a retention-pinned non-Kit Claude MCP request configuration, follow the local-only same-host recovery procedure. It accepts no SQL or arbitrary-path override. A valid recovery invocation emits JSON and exits 0 after success or 2 for a safe refusal; invalid usage or unavailable durable storage exits 1.
Release-readiness history is tracked in docs/personal-mcp/RELEASE_READINESS.md. Dogfooding evidence (which target LLMs guided setup, what unsafe suggestions were captured, and which findings were deferred from the initial personal-appliance rollout) is in docs/personal-mcp/DOGFOODING_RESULTS.md.
Current personal-appliance artifacts include:
- Streamable HTTP startup:
LLM_GATEWAY_AUTH_TOKEN=<token> npm run start:http - Machine-readable diagnostics:
npm run doctor - Go bootstrapper:
installer/withsetup,doctor --json,start,stop,status,repair,upgrade,uninstall,print-client-config, and verified bundle download commands. - Release packaging: on the public mirror, the release workflow builds Linux binaries on GitHub-hosted
ubuntu-latestand builds Windows/macOS binaries on their GitHub-hosted platform runners. The private upstream uses its internal self-hosted Linux runner. Each release publishes checksummed platform bundles with the gateway, production dependencies, and a managed Node runtime; see installer/packaging/README.md. - Docker Compose fallback: docker/personal.compose.yml + docker/Dockerfile.personal for users who already manage containers.
- Local setup UI artifact: setup/ui/index.html
- Provider setup snippets: setup/providers/
- Cross-validation tools:
review_changes,validate_with_models,second_opinion,compare_answers,red_team_review,consensus_check,ask_model,synthesize_validation,job_status,job_result, andvalidation_receipt(plus thevalidation-receipt://{validationId}resource).review_changesand durable receipts require a SQLite or PostgreSQL validation-run store and are absent in Personal Agent Config Kit mode.
Install / Upgrade / Uninstall (single binary)
Windows PowerShell:
$Version = '<version>'
$Base = "https://github.com/verivus-oss/llm-cli-gateway/releases/download/v$Version"
$InstallDir = Join-Path (Join-Path $env:LOCALAPPDATA 'Programs') 'llm-cli-gateway'
$ExeName = "llm-cli-gateway-$Version-windows-amd64.exe"
$BundleName = "llm-cli-gateway-bundle-$Version-windows-amd64.tar.gz"
$Exe = Join-Path $InstallDir 'llm-cli-gateway.exe'
$Checksums = Join-Path $InstallDir 'SHA256SUMS'
$ChecksumBundle = Join-Path $InstallDir 'SHA256SUMS.sigstore.json'
New-Item -ItemType Directory -Force $InstallDir | Out-Null
Invoke-WebRequest -UseBasicParsing "$Base/$ExeName" -OutFile $Exe
Invoke-WebRequest -UseBasicParsing "$Base/SHA256SUMS" -OutFile $Checksums
Invoke-WebRequest -UseBasicParsing "$Base/SHA256SUMS.sigstore.json" -OutFile $ChecksumBundle
cosign verify-blob $Checksums --bundle $ChecksumBundle --certificate-identity "https://github.com/verivus-oss/llm-cli-gateway/.github/workflows/release-installer.yml@refs/tags/v$Version" --certificate-oidc-issuer "https://token.actions.githubusercontent.com"
if ($LASTEXITCODE -ne 0) { throw "Sigstore verification failed for SHA256SUMS" }
function Get-ReleaseSha256($Name) {
$line = Select-String -Path $Checksums -Pattern "^[a-fA-F0-9]{64}\s+$([regex]::Escape($Name))$" | Select-Object -First 1
if (-not $line) { throw "No SHA256SUMS entry found for $Name" }
return (($line.Line -split "\s+")[0]).ToLowerInvariant()
}
if ((Get-FileHash $Exe -Algorithm SHA256).Hash.ToLowerInvariant() -ne (Get-ReleaseSha256 $ExeName)) { throw "Checksum mismatch for $ExeName" }
$env:RVWR_GATEWAY_BUNDLE_URL = "$Base/$BundleName"
$env:RVWR_GATEWAY_BUNDLE_SHA256 = Get-ReleaseSha256 $BundleName
& $Exe setup
& $Exe stop
& $Exe install-bundle
& $Exe start
& $Exe status
& $Exe doctor
The Windows installer keeps a stable llm-cli-gateway.exe command in
%LOCALAPPDATA%\Programs\llm-cli-gateway and adds that directory to the user
PATH. Do not script against release-versioned exe names after install.
# After downloading the binary that matches your OS/arch from a release:
cosign verify-blob SHA256SUMS --bundle SHA256SUMS.sigstore.json \
--certificate-identity "https://github.com/verivus-oss/llm-cli-gateway/.github/workflows/release-installer.yml@refs/tags/v<version>" \
--certificate-oidc-issuer "https://token.actions.githubusercontent.com"
sha256sum --check SHA256SUMS # verify before run (or `shasum -a 256 --check` on macOS)
chmod +x llm-cli-gateway-<ver>-<os>-<arch>
./llm-cli-gateway-<ver>-<os>-<arch> setup
./llm-cli-gateway-<ver>-<os>-<arch> install-bundle # uses the platform bundle URL/SHA256
./llm-cli-gateway-<ver>-<os>-<arch> start
./llm-cli-gateway-<ver>-<os>-<arch> doctor
# Upgrade: replace the binary, set the new bundle env vars, run upgrade.
./llm-cli-gateway-<new>-<os>-<arch> upgrade
# Uninstall: dry-run first, then run with --yes.
./llm-cli-gateway-<ver>-<os>-<arch> uninstall
./llm-cli-gateway-<ver>-<os>-<arch> uninstall --yes
Docker fallback:
LLM_GATEWAY_AUTH_TOKEN=$(openssl rand -hex 32) \
docker compose -f docker/personal.compose.yml up -d
docker compose -f docker/personal.compose.yml run --rm doctor
Features
Core Capabilities
- Multi-LLM Orchestration: Unified interface for Claude Code, Codex, Gemini, Grok, Mistral (Vibe), Devin, and Cursor Agent CLIs
- Session Management: Track gateway session metadata and provider-specific continuity with persistent storage
- Gateway-owned worktrees: Run supported sync or async provider requests inside a managed git worktree with the local file-backed session manager. Same-session reuse requires same-host durable ownership plus a matching live Git registration and gateway branch; manager-level named path collisions fail closed. PostgreSQL-backed sessions reject worktrees before creation because a different database-connected host cannot safely own filesystem cleanup. Grok, Devin, and Mistral require an explicit provider-native
sessionId; fresh,createNewSession, andresumeLatest-only worktree requests fail closed. A worktree requires a registered workspace selected explicitly, through caller-owned session metadata, or by the configured default; it never inherits process cwd or combines withworkingDir,addDir, orincludeDirs. Materialization suppresses repository, system, and global Git hooks, configured clean, smudge, and process checkout filters, sparse checkout, and lazy object fetching. Filter-dependent content such as Git LFS remains in its repository representation instead of executing host commands. Session deletion and TTL eviction hide a durably owned worktree session while cleanup runs. If Git removal fails, the file-backed store retains a durable cleanup-pending tombstone, blocks reuse, and retries cleanup when that store is registered on the owning host. The record is finalized only after verified Git removal. - Token Optimization: Automatic 44% reduction on prompts, 37% on responses (opt-in)
- Correlation ID Tracking: Full request tracing across all LLM interactions
- Cross-Tool Collaboration: LLMs can use each other via MCP (validated through dogfooding)
Observability
- SQLite Flight Recorder: Every request/response logged to
~/.llm-cli-gateway/logs.dbwith correlation IDs, token usage, duration, retry counts, and circuit breaker state. Browse with Datasette:datasette ~/.llm-cli-gateway/logs.db - Structured Metadata: Tool responses include machine-readable
structuredContent(model, cli, correlationId, sessionId, durationMs, token counts) - Cache observability resources:
cache-state://global,cache-state://session/{id}, andcache-state://prefix/{hash}MCP resources return aggregate cache hit/miss/savings — tokens and hashes only, no prompt text.session_getincludes acacheStateblock when the session has prior requests. - Provider capability inventory:
provider_tool_capabilitiesandprovider-tools://catalogexpose the gateway request fields, supported/degraded provider controls, local skill/tool discovery, and safe config-surface hints for Claude Code, Codex CLI, Gemini/Antigravity, Grok CLI/API, Mistral Vibe, Cognition Devin, and Cursor Agent.doctor --jsonincludes a compactprovider_capabilitiessummary for setup assistants.
Cache-aware operation
Every *_request and *_request_async tool except devin_request / devin_request_async and cursor_request / cursor_request_async accepts an optional promptParts field that structures the prompt for better cache hit rates (the Devin and Cursor headless paths take a plain prompt only). The gateway concatenates the parts in canonical order (system → tools → context → task) so that the stable prefix bytes precede the volatile task tail unchanged across calls, letting each provider's automatic prompt-caching land on the same content hash each time.
{
"promptParts": {
"system": "You are a helpful code reviewer.",
"tools": "You have access to Read, Grep, Bash.",
"context": "<long stable context block — file dumps, etc.>",
"task": "Review the changes in src/foo.ts for security issues."
}
}
prompt and promptParts are mutually exclusive — pass exactly one.
Per-CLI capability matrix (prefix discipline is automatic via promptParts for all providers except Devin and Cursor, which have no promptParts surface; explicit levers are provider-specific):
| CLI | Prefix discipline | Explicit lever(s) |
|---|---|---|
| claude | yes | promptParts.cacheControl + outputFormat: "stream-json" (Anthropic cache_control breakpoints on stable blocks; ttl="1h" forced) |
| codex | yes | none (OpenAI implicit) |
| gemini | yes | none (implicit server-side) |
| grok | yes | compactionMode / compactionDetail (context compaction: `summary |
| mistral | yes | none (implicit) |
| devin | no | plain prompt only |
| cursor | no | plain prompt only |
Claude example (explicit cacheControl)
claude_request({
promptParts: {
system: "You are a helpful code reviewer.",
context: "<long stable file dump>",
task: "Review the diff.",
cacheControl: { system: true, context: true }, // task is never marked
},
outputFormat: "stream-json",
});
Gateway emits the stream-json stdin path with cache_control: {type:"ephemeral", ttl:"1h"} on marked blocks only.
Grok example (compaction)
grok_request({
promptParts: { system: "...", context: "...", task: "..." },
compactionMode: "segments",
compactionDetail: "balanced",
});
Emits --compaction-mode segments --compaction-detail balanced.
See docs/personal-mcp/PROVIDER_CACHE_SURFACES.md for full surfaces, telemetry differences (e.g. Grok -p vs ACP), exact stream-json payload shapes, and cross-LLM review notes.
Opt-in flags (all default off) live under [cache_awareness] in ~/.llm-cli-gateway/config.toml.
Reliability & Performance
- Retry Logic: Exponential backoff with circuit breaker for transient failures
- Atomic File Writes: Process-specific temp files with fsync for data integrity
- Host-protection backpressure: bounded HTTP session lifecycle (max sessions + idle reaper), global and per-provider job-execution limits with a bounded FIFO queue, and a configurable per-job output cap (default 50MB). See Host-protection limits.
- NVM Path Caching: Eliminates I/O overhead on every request
- Long-Running Jobs: Non-time-bound async execution via
*_request_async+ polling tools
Security & Quality
- Comprehensive Testing: 1,700+ tests covering unit, integration, and regression scenarios with real CLI execution
- Input Validation: Zod schemas prevent injection attacks
- No Secret Leakage: Generic session descriptions only (file permissions 0o600)
- No ReDoS: Bounded regex patterns prevent catastrophic backtracking
- Type Safety: Strict TypeScript with comprehensive error handling
- Supply-chain hardening: a dedicated
.github/workflows/security.ymlruns actionlint, zizmor, shellcheck, typos, osv-scanner, gitleaks, and lychee on every push and PR (seeSECURITY.mdfor the threat model)
Provider capability surface
Every provider is reachable through the same request, session, job, and validation machinery, but the underlying CLIs differ in what they natively expose. The table records what actually shipped per provider; discover the live surface at runtime with provider_tool_capabilities, list_models, and the provider-acp://<provider> / provider-tools://<provider> resources.
| Provider | CLI request tools | Native ACP | Live model discovery | Admin surface |
|---|---|---|---|---|
Claude Code (claude) |
claude_request / _async |
None (CLI-first; no ACP entrypoint at claude 2.1.212) | model aliases, reasoning-effort levels, fallback model | read-only via provider_admin_list / provider_admin_run |
OpenAI Codex (codex) |
codex_request / _async, codex_fork_session |
None (codex-cli 0.144.5 advertises mcp-server / app-server transports, not native ACP) | codex debug models |
read-only via provider_admin_list / provider_admin_run |
Gemini / Antigravity (gemini, agy) |
gemini_request / _async |
None (agy 1.1.3 exposes no ACP entrypoint; legacy Gemini CLI ACP evidence does not transfer) | agy models |
read-only via provider_admin_list / provider_admin_run |
xAI Grok (grok) |
grok_request (sync transport: "acp") / _async |
Native via grok agent stdio |
grok models + ~/.grok/config.toml |
read-only via provider_admin_list / provider_admin_run |
Mistral Vibe (mistral) |
mistral_request (sync transport: "acp") / _async |
Native via vibe-acp |
Vibe config plus the VIBE_ACTIVE_MODEL active model and agent profiles |
read-only via provider_admin_list / provider_admin_run |
Cognition Devin (devin) |
devin_request (sync transport: "acp", agentType: summarizer|review) / _async |
Native via devin acp |
--model / DEVIN_MODEL |
read-only via provider_admin_list / provider_admin_run |
Cursor Agent (cursor) |
cursor_request (sync transport: "acp") / _async |
Native via cursor-agent acp (companion-owned) |
model aliases | read-only via provider_admin_list / provider_admin_run |
- Native ACP is reported honestly.
grok,mistral,devin, andcursorexpose a native ACP entrypoint, soprovider-acp://<provider>carries the negotiatedinitializecapability set and the derived session-method availability, and the sync*_requestacceptstransport: "acp"(fails closed unless[acp]and the provider'sruntime_enabledgate are set). ACP routing is sync-only: the*_request_asyncvariants always run the CLI transport and do not accepttransport: "acp"(nor Devin'sagentType); async ACP parity is a later phase. ACP workspace selection is gateway-owned: an explicit ACPworkspacemust be a registered alias. A fresh remote ACP request uses that alias or[workspaces].default; a remote resume is fixed to its recorded canonical alias and cwd, and a different or unbound workspace is rejected. Local ACP may omitworkspace; each unscoped process then gets a fresh private0o700neutral directory that is removed after the process exits, never a shared predictable temp path.claude,codex, andgeminihave no native ACP entrypoint at their target CLI versions; theirprovider-acp://records reportnative: falsewith no methods and no adapter-as-native masquerade, and they expose notransport: "acp"selector. - Managed approval is Claude-only today.
approvalStrategy:"mcp_managed"is executable only by the Claude CLI adapter, which launches Claude with a request-scoped generated MCP configuration and--strict-mcp-config. It permits only provisioned, gateway-owned MCP definitions and rejects dynamicnpx, ambient-PATH, and Codex-config overrides. Codex, Gemini, Grok, Mistral, Devin, and Cursor rejectmcp_managedbefore launching a provider because their current adapters cannot isolate ambient MCP configuration. For those adapters, useapprovalStrategy:"legacy";approvalPolicyhas no effect. - ACP has its own permission bridge.
approvalStrategy:"mcp_managed"and anyapprovalPolicyare rejected whentransport:"acp"is selected. Use the Claude CLI transport for managed approval. ACP host services fail closed: reads are unavailable by default, and write or terminal callbacks need[acp]host-service configuration plus a one-time ApprovalManager decision. ACP never maps a raw CLI bypass input to a standing permission grant. - Resources are generated from the provider registry for every CLI provider:
models://<provider>,sessions://<provider>,provider-acp://<provider>,provider-tools://<provider>, andprovider-subcommands://<provider>. - Model discovery is live and account-aware: the discovery listed above reaches
models://<provider>andlist_models, degrading to static registry facts when a live probe is unavailable (a resource read never spawns a CLI). - Admin surfaces are discovery-driven and output-redacted.
provider_admin_listandprovider_admin_runare read-only for every provider. State-mutating admin operations are exposed only throughprovider_admin_mutate, gated behind[admin] allow_mutating_cli_admin_ops, the remotecli:adminscope, an approval gate, and an audit record. Mutating ACP session operations are likewise gated behind[acp] allow_mutating_session_ops. - Validation commands work across every provider:
review_changes,validate_with_models,second_opinion,compare_answers,red_team_review,consensus_check,ask_model, andsynthesize_validation, with canonically hashed immutable receipts viavalidation_receiptand thevalidation-receipt://{validationId}resource.review_changescaptures a complete, hashed Git artifact and starts repository-bound read-only reviewers.
Prerequisites
Node.js >= 24.4.0 is required (engines.node in package.json). The gateway uses Node's built-in node:sqlite module for persistence — there is no native binding to compile and no install scripts run. The 24.4 floor is where allowBareNamedParameters defaults to true, which the persistence layer relies on.
Before using this gateway, you need to install the CLI tools you want to use:
Claude Code CLI
# Installation instructions for Claude Code
# Visit: https://docs.anthropic.com/claude-code
npm install -g @anthropic-ai/claude-code
Codex CLI
npm install -g @openai/codex
codex login
Gemini (Google Antigravity CLI)
The Gemini provider runs through Google Antigravity CLI (agy).
curl -fsSL https://antigravity.google/cli/install.sh | bash
# Docs: https://antigravity.google/docs
Grok Build CLI (xAI)
curl -fsSL https://x.ai/cli/install.sh | bash
grok login # OAuth flow; for headless auth, set XAI_API_KEY
# Docs: https://docs.x.ai/build/overview
Mistral Vibe CLI
# Pick one — the gateway's cli_upgrade auto-detects which one you used.
curl -LsSf https://mistral.ai/vibe/install.sh | bash
pip install mistral-vibe
uv tool install mistral-vibe
brew install mistral-vibe
vibe --setup
# Complete the API-key setup locally. Do not paste the key into a chat.
# Current Vibe defaults session logging to enabled. If an older config disabled it,
# edit ~/.vibe/config.toml and set:
# [session_logging]
# enabled = true
Vibe-specific notes:
- Model selection is via the
VIBE_ACTIVE_MODELenvironment variable — Vibe has no--modelflag. The gateway discovers~/.vibe/config.toml/VIBE_MODELS, injectsVIBE_ACTIVE_MODELonly when a model is explicitly requested or Vibe config needs recovery, and retries once after a model-not-found failure with refreshed discovery. permissionModeis the Vibe--agentname. Builtins aredefault | plan | accept-edits | auto-approve; Vibe also accepts install-gated builtins (e.g.lean) and custom agents from~/.vibe/agents. Requests pass the selected name through for Vibe to validate.mcp_managedis not available for Vibe.- Tool controls use Vibe's native flags. The gateway emits one
--enabled-tools <tool>flag perallowedToolsentry and one--disabled-tools <tool>flag perdisallowedToolsentry. Vibe applies disabled tools after enabled-tool filtering. - Usage telemetry is best-effort. Vibe does not emit token or cost data in
programmatic stdout. When the gateway knows Vibe's native session UUID, it
reads
~/.vibe/logs/session/session_<...>/meta.jsonfor usage and cost. A missing, malformed, or not-yet-known session log leaves those fields empty. - No self-update:
cli_upgrade --cli mistraldetects whether you used pip / uv / brew and dispatches the matching upgrade command. Runningvibe updateis not a thing.
Installation
As an MCP server (npm)
npm install -g llm-cli-gateway
Or use directly with npx:
{
"mcpServers": {
"llm-gateway": {
"command": "npx",
"args": ["-y", "llm-cli-gateway"]
}
}
}
From source
git clone https://github.com/verivus-oss/llm-cli-gateway.git
cd llm-cli-gateway
npm install
npm run build
Usage
As an MCP Server
For clients that already support local stdio MCP servers, add a configuration like:
{
"mcpServers": {
"llm-cli-gateway": {
"command": "node",
"args": ["/path/to/llm-cli-gateway/dist/index.js"]
}
}
}
Stdio is the recommended path for unrestricted machine-local development access. HTTP MCP, including localhost HTTP and tunneled HTTPS, is treated as remote-capable for provider execution: provider tools must resolve a registered workspace alias, a session workspace, or [workspaces].default before spawning a CLI. Remote clients should pass relative workingDir, addDir, and include-directory values inside the selected workspace, and may resume only gateway-tracked sessions they own. Raw native provider session IDs are local-only. Disabling auth or using a no-auth connector path is not a filesystem bypass.
For a local CLI request with no resolved workingDir, registered workspace,
or gateway-managed worktree, the child runs in a fresh private 0o700
temporary directory that is removed after the process exits. It never inherits
the gateway repository cwd or its provider-native instruction context. The
gateway canonicalizes the temp root and rejects or relocates it when any
ancestor contains .git, AGENTS.md, AGENTS.override.md, Agents.md,
AGENT.md, CLAUDE.md, Claude.md, CLAUDE.local.md,
.claude/CLAUDE.md, .claude/rules/, .cursor/rules/, .cursorrules,
GEMINI.md, or .vibe/config.toml, including through a symlinked or custom
TMPDIR beneath that context. The list covers entries a provider discovers by
walking up from its cwd. User-scope configuration such as
~/.claude/settings.json is deliberately absent: it loads on every invocation
regardless of cwd, so relocating the workspace would not isolate it.
Provider-native resumeLatest operations that use a cwd-scoped latest-session
pointer therefore require an explicit workingDir, workspace, or configured
default workspace and fail closed when none is available. Use explicit target
selection whenever several repositories are active at once.
CLI request schemas accept prompts up to 100,000 characters, but operating
systems also impose byte limits on individual argv elements. Codex new and
resume requests stream the exact prompt over stdin. codex_fork_session
remains argv-bound and rejects an oversized UTF-8 prompt before spawn as
non-retryable input_too_large. Other providers whose current CLI contracts
require an argv prompt use the same admission rule. Every other
caller-controlled argv value is checked on its final encoded form too,
including serialized agent/schema JSON, joined tool lists, instruction
overrides, paths, model names, and native session IDs. The final spawn boundary
checks every argv element plus the aggregate resolved command line against a
conservative platform-specific byte budget and a 2,048-element cap. The
aggregate byte budget excludes the environment but reserves headroom for it;
on Windows, pre-resolution admission assumes the smaller npm .cmd/.bat
wrapper limit until command resolution proves a native executable. Native
session and resume flags on non-Kit requests are included before workspace,
session, provider-artifact handoff, or durable job side effects. Claude Kit
projects its eventual argv before materializing its compiled context artifact
or allocating a durable Kit session.
An embedded NUL byte in the command or any argv element is rejected before
spawn as non-retryable invalid_input. Caller-facing results, long-lived job
memory, durable job args, and async flight rows use a fixed invalid-argv marker;
the optional duplicate durable payload is suppressed. None retains the rejected
vector or Node's value-echoing native error.
Native E2BIG, including an environment-driven failure, is normalized without
retaining the native spawnargs. The gateway never truncates instructions or
other values to make them fit. For stdin-backed requests, a clean provider exit
is accepted only after the complete payload write callback succeeds. A closed
or still-pending pipe becomes a fixed, non-sensitive incomplete-delivery
failure; timeout, cancellation, and provider nonzero exits remain authoritative.
This generic stdio example is not provider-support verification for the Personal MCP Appliance. Client-specific setup guides for ChatGPT, Claude web, Claude Desktop, Codex, Gemini CLI, Gemini web, and Grok remain gated by the provider-support matrix in docs/personal-mcp/PRODUCT_CONTRACT.md.
Available Tools
Cross-LLM Validation Tools
The personal-appliance surface exposes simplified validation tools for non-developer clients. These tools start provider CLI jobs through the durable async job manager and return normalized provider status plus raw job references.
validate_with_models: ask two or more providers to independently validate a question.- `review_
No comments yet
Be the first to share your take.