Add Providers docs page

Splits first-class and custom provider docs out of the Configuration
page onto /docs/providers. Introduces the first-class providers
(claude, codex, opencode, copilot, pi) and covers extending a provider,
Z.AI and Qwen plans, multiple profiles, custom binaries, ACP agents,
additionalModels, and disabling. Points to docs/CUSTOM-PROVIDERS.md on
GitHub as the source of truth.
This commit is contained in:
Mohamed Boudra
2026-04-22 22:24:12 +07:00
parent 1f8f8e4036
commit 434b28fc8e
6 changed files with 397 additions and 78 deletions
+21
View File
@@ -25,6 +25,7 @@ import { Route as DocsVoiceRouteImport } from "./routes/docs/voice";
import { Route as DocsUpdatesRouteImport } from "./routes/docs/updates";
import { Route as DocsSkillsRouteImport } from "./routes/docs/skills";
import { Route as DocsSecurityRouteImport } from "./routes/docs/security";
import { Route as DocsProvidersRouteImport } from "./routes/docs/providers";
import { Route as DocsConfigurationRouteImport } from "./routes/docs/configuration";
import { Route as DocsCliRouteImport } from "./routes/docs/cli";
import { Route as DocsBestPracticesRouteImport } from "./routes/docs/best-practices";
@@ -110,6 +111,11 @@ const DocsSecurityRoute = DocsSecurityRouteImport.update({
path: "/security",
getParentRoute: () => DocsRoute,
} as any);
const DocsProvidersRoute = DocsProvidersRouteImport.update({
id: "/providers",
path: "/providers",
getParentRoute: () => DocsRoute,
} as any);
const DocsConfigurationRoute = DocsConfigurationRouteImport.update({
id: "/configuration",
path: "/configuration",
@@ -145,6 +151,7 @@ export interface FileRoutesByFullPath {
"/docs/best-practices": typeof DocsBestPracticesRoute;
"/docs/cli": typeof DocsCliRoute;
"/docs/configuration": typeof DocsConfigurationRoute;
"/docs/providers": typeof DocsProvidersRoute;
"/docs/security": typeof DocsSecurityRoute;
"/docs/skills": typeof DocsSkillsRoute;
"/docs/updates": typeof DocsUpdatesRoute;
@@ -165,6 +172,7 @@ export interface FileRoutesByTo {
"/docs/best-practices": typeof DocsBestPracticesRoute;
"/docs/cli": typeof DocsCliRoute;
"/docs/configuration": typeof DocsConfigurationRoute;
"/docs/providers": typeof DocsProvidersRoute;
"/docs/security": typeof DocsSecurityRoute;
"/docs/skills": typeof DocsSkillsRoute;
"/docs/updates": typeof DocsUpdatesRoute;
@@ -188,6 +196,7 @@ export interface FileRoutesById {
"/docs/best-practices": typeof DocsBestPracticesRoute;
"/docs/cli": typeof DocsCliRoute;
"/docs/configuration": typeof DocsConfigurationRoute;
"/docs/providers": typeof DocsProvidersRoute;
"/docs/security": typeof DocsSecurityRoute;
"/docs/skills": typeof DocsSkillsRoute;
"/docs/updates": typeof DocsUpdatesRoute;
@@ -212,6 +221,7 @@ export interface FileRouteTypes {
| "/docs/best-practices"
| "/docs/cli"
| "/docs/configuration"
| "/docs/providers"
| "/docs/security"
| "/docs/skills"
| "/docs/updates"
@@ -232,6 +242,7 @@ export interface FileRouteTypes {
| "/docs/best-practices"
| "/docs/cli"
| "/docs/configuration"
| "/docs/providers"
| "/docs/security"
| "/docs/skills"
| "/docs/updates"
@@ -254,6 +265,7 @@ export interface FileRouteTypes {
| "/docs/best-practices"
| "/docs/cli"
| "/docs/configuration"
| "/docs/providers"
| "/docs/security"
| "/docs/skills"
| "/docs/updates"
@@ -389,6 +401,13 @@ declare module "@tanstack/react-router" {
preLoaderRoute: typeof DocsSecurityRouteImport;
parentRoute: typeof DocsRoute;
};
"/docs/providers": {
id: "/docs/providers";
path: "/providers";
fullPath: "/docs/providers";
preLoaderRoute: typeof DocsProvidersRouteImport;
parentRoute: typeof DocsRoute;
};
"/docs/configuration": {
id: "/docs/configuration";
path: "/configuration";
@@ -436,6 +455,7 @@ interface DocsRouteChildren {
DocsBestPracticesRoute: typeof DocsBestPracticesRoute;
DocsCliRoute: typeof DocsCliRoute;
DocsConfigurationRoute: typeof DocsConfigurationRoute;
DocsProvidersRoute: typeof DocsProvidersRoute;
DocsSecurityRoute: typeof DocsSecurityRoute;
DocsSkillsRoute: typeof DocsSkillsRoute;
DocsUpdatesRoute: typeof DocsUpdatesRoute;
@@ -448,6 +468,7 @@ const DocsRouteChildren: DocsRouteChildren = {
DocsBestPracticesRoute: DocsBestPracticesRoute,
DocsCliRoute: DocsCliRoute,
DocsConfigurationRoute: DocsConfigurationRoute,
DocsProvidersRoute: DocsProvidersRoute,
DocsSecurityRoute: DocsSecurityRoute,
DocsSkillsRoute: DocsSkillsRoute,
DocsUpdatesRoute: DocsUpdatesRoute,
+1
View File
@@ -12,6 +12,7 @@ const navigation = [
{ name: "Git worktrees", href: "/docs/worktrees" },
{ name: "CLI", href: "/docs/cli" },
{ name: "Skills", href: "/docs/skills" },
{ name: "Providers", href: "/docs/providers" },
{ name: "Configuration", href: "/docs/configuration" },
{ name: "Security", href: "/docs/security" },
{ name: "Best practices", href: "/docs/best-practices" },
@@ -11,6 +11,8 @@ export const Route = createFileRoute("/docs/configuration")({
component: Configuration,
});
const CUSTOM_PROVIDERS_URL = "https://github.com/getpaseo/paseo/blob/main/docs/CUSTOM-PROVIDERS.md";
function Configuration() {
return (
<div className="space-y-8">
@@ -59,15 +61,12 @@ function Configuration() {
<section className="space-y-4">
<h2 className="text-xl font-medium">Example</h2>
<p className="text-white/60 leading-relaxed">
Minimal example that configures listening address, hostnames, provider keys, and MCP:
Minimal example that configures listening address, hostnames, and MCP:
</p>
<pre className="bg-card border border-border rounded-lg p-4 font-mono text-sm overflow-x-auto text-white/80">
{`{
"$schema": "https://paseo.sh/schemas/paseo.config.v1.json",
"version": 1,
"providers": {
"openai": { "apiKey": "..." }
},
"daemon": {
"listen": "127.0.0.1:6767",
"hostnames": ["localhost", ".localhost"],
@@ -83,84 +82,31 @@ function Configuration() {
</section>
<section className="space-y-4">
<h2 className="text-xl font-medium">Agent provider runtime settings</h2>
<h2 className="text-xl font-medium">Agent providers</h2>
<p className="text-white/60 leading-relaxed">
Use <code className="font-mono">agents.providers</code> to customize how Paseo launches
agent provider CLIs. This works for <code className="font-mono">claude</code>,{" "}
<code className="font-mono">codex</code>, and
<code className="font-mono"> opencode</code>.
Agent providers — both the first-class ones Paseo ships with and custom entries you add
under <code className="font-mono">agents.providers</code> — are documented on their own
page.
</p>
<p className="text-white/60 leading-relaxed">
<code className="font-mono">command.mode</code> can be{" "}
<code className="font-mono">default</code>, <code className="font-mono">append</code>, or{" "}
<code className="font-mono">replace</code>. Use <code className="font-mono">env</code> to
inject provider-specific environment variables.
See{" "}
<a href="/docs/providers" className="underline hover:text-white/80">
Providers
</a>{" "}
for first-class providers, how to point Claude at Anthropic-compatible endpoints (Z.AI,
Alibaba/Qwen), multiple profiles, custom binaries, ACP agents, and the{" "}
<code className="font-mono">additionalModels</code> merge behavior. The full field
reference lives on GitHub at{" "}
<a
href={CUSTOM_PROVIDERS_URL}
target="_blank"
rel="noreferrer"
className="underline hover:text-white/80"
>
docs/CUSTOM-PROVIDERS.md
</a>
.
</p>
<h3 className="text-lg font-medium">Enable Claude Code Chrome MCP</h3>
<pre className="bg-card border border-border rounded-lg p-4 font-mono text-sm overflow-x-auto text-white/80">
{`{
"agents": {
"providers": {
"claude": {
"command": {
"mode": "append",
"args": ["--chrome"]
}
}
}
}
}`}
</pre>
<h3 className="text-lg font-medium">
Point Claude to Anthropic-compatible endpoints (z.ai example)
</h3>
<pre className="bg-card border border-border rounded-lg p-4 font-mono text-sm overflow-x-auto text-white/80">
{`{
"agents": {
"providers": {
"claude": {
"env": {
"ANTHROPIC_BASE_URL": "https://api.z.ai/api/anthropic",
"ANTHROPIC_AUTH_TOKEN": "auth token",
"ANTHROPIC_API_KEY": ""
}
}
}
}
}`}
</pre>
<h3 className="text-lg font-medium">Run Claude through Docker</h3>
<p className="text-white/60 leading-relaxed">
Create a wrapper script that runs Claude in Docker, then tell Paseo to replace the Claude
launch command with that script.
</p>
<pre className="bg-card border border-border rounded-lg p-4 font-mono text-sm overflow-x-auto text-white/80">
{`{
"agents": {
"providers": {
"claude": {
"command": {
"mode": "replace",
"argv": ["/Users/you/bin/claude-docker"]
}
}
}
}
}`}
</pre>
<pre className="bg-card border border-border rounded-lg p-4 font-mono text-sm overflow-x-auto text-white/80">
{`#!/usr/bin/env bash
set -euo pipefail
docker run --rm -i \\
-v "$PWD":"$PWD" \\
-w "$PWD" \\
-v "$HOME/.claude":"$HOME/.claude" \\
ghcr.io/anthropics/claude-code:latest \\
claude "$@"`}
</pre>
</section>
<section className="space-y-4">
@@ -148,6 +148,11 @@ function GettingStarted() {
Voice
</a>
</li>
<li>
<a href="/docs/providers" className="underline hover:text-white/80">
Providers
</a>
</li>
<li>
<a href="/docs/configuration" className="underline hover:text-white/80">
Configuration
@@ -0,0 +1,345 @@
import { createFileRoute } from "@tanstack/react-router";
import { pageMeta } from "~/meta";
export const Route = createFileRoute("/docs/providers")({
head: () => ({
meta: pageMeta(
"Providers - Paseo Docs",
"First-class agent providers in Paseo, and how to configure custom providers, ACP agents, and profiles.",
),
}),
component: Providers,
});
const CUSTOM_PROVIDERS_URL = "https://github.com/getpaseo/paseo/blob/main/docs/CUSTOM-PROVIDERS.md";
function Providers() {
return (
<div className="space-y-10">
<div>
<h1 className="text-3xl font-medium font-title mb-4">Providers</h1>
<p className="text-white/60 leading-relaxed">
A provider is an agent CLI that Paseo knows how to launch, stream, and control. Paseo
ships with first-class providers for the major coding agents, and lets you add your own
through <code className="font-mono">config.json</code> — either by pointing an existing
provider at a different API, adding extra profiles, or plugging in any{" "}
<a
href="https://agentclientprotocol.com"
target="_blank"
rel="noreferrer"
className="underline hover:text-white/80"
>
ACP
</a>
-compatible agent.
</p>
</div>
<section className="space-y-4">
<h2 className="text-xl font-medium">First-class providers</h2>
<p className="text-white/60 leading-relaxed">
These work out of the box once the underlying CLI is installed and authenticated. Paseo
discovers them automatically, wires up modes, and exposes them in the app and CLI.
</p>
<ul className="text-white/60 space-y-3 list-disc list-inside">
<li>
<code className="font-mono">claude</code> — Anthropic's Claude Code. Multi-tool
assistant with MCP support, streaming, and deep reasoning.
</li>
<li>
<code className="font-mono">codex</code> — OpenAI's Codex workspace agent with sandbox
controls and optional network access.
</li>
<li>
<code className="font-mono">opencode</code> — Open-source coding assistant with
multi-provider model support.
</li>
<li>
<code className="font-mono">copilot</code> — GitHub Copilot via ACP, with dynamic modes
and session support.
</li>
<li>
<code className="font-mono">pi</code> — Minimal terminal-based coding agent with
multi-provider LLM support.
</li>
</ul>
</section>
<section className="space-y-4">
<h2 className="text-xl font-medium">Custom providers</h2>
<p className="text-white/60 leading-relaxed">
Everything beyond the defaults lives under{" "}
<code className="font-mono">agents.providers</code> in{" "}
<code className="font-mono">~/.paseo/config.json</code>. You can:
</p>
<ul className="text-white/60 space-y-2 list-disc list-inside">
<li>
<strong>Extend</strong> a first-class provider to point at a different API (Z.AI,
Alibaba/Qwen, a proxy, a self-hosted endpoint).
</li>
<li>
<strong>Add profiles</strong> — multiple entries against the same underlying provider
with different credentials or curated model lists.
</li>
<li>
<strong>Override the binary</strong> — run a nightly build, a wrapper script, or a
Docker image instead of the installed CLI.
</li>
<li>
<strong>Add ACP agents</strong> — Gemini CLI, Hermes, or any agent speaking the Agent
Client Protocol over stdio.
</li>
<li>
<strong>Disable</strong> a provider you don't use.
</li>
</ul>
<p className="text-white/60 leading-relaxed">
Provider IDs must be lowercase alphanumeric with hyphens (
<code className="font-mono">/^[a-z][a-z0-9-]*$/</code>). Every custom entry needs{" "}
<code className="font-mono">extends</code> (a first-class provider ID or{" "}
<code className="font-mono">"acp"</code>) and a <code className="font-mono">label</code>.
</p>
<p className="text-white/60 leading-relaxed">
The examples below are a quick tour. The full, up-to-date reference is on GitHub:{" "}
<a
href={CUSTOM_PROVIDERS_URL}
target="_blank"
rel="noreferrer"
className="underline hover:text-white/80"
>
docs/CUSTOM-PROVIDERS.md
</a>
.
</p>
</section>
<section className="space-y-4">
<h2 className="text-xl font-medium">Extending a first-class provider</h2>
<pre className="bg-card border border-border rounded-lg p-4 font-mono text-sm overflow-x-auto text-white/80">
{`{
"agents": {
"providers": {
"my-claude": {
"extends": "claude",
"label": "My Claude",
"env": {
"ANTHROPIC_API_KEY": "sk-ant-...",
"ANTHROPIC_BASE_URL": "https://my-proxy.example.com/v1"
}
}
}
}
}`}
</pre>
</section>
<section className="space-y-4">
<h2 className="text-xl font-medium">Z.AI (GLM) coding plan</h2>
<p className="text-white/60 leading-relaxed">
Z.AI exposes GLM models through an Anthropic-compatible endpoint. Point{" "}
<code className="font-mono">ANTHROPIC_BASE_URL</code> at their API and use{" "}
<code className="font-mono">ANTHROPIC_AUTH_TOKEN</code> for the key. Third-party endpoints
don't support Anthropic's server-side tools, so disable{" "}
<code className="font-mono">WebSearch</code>.
</p>
<pre className="bg-card border border-border rounded-lg p-4 font-mono text-sm overflow-x-auto text-white/80">
{`{
"agents": {
"providers": {
"zai": {
"extends": "claude",
"label": "ZAI",
"env": {
"ANTHROPIC_AUTH_TOKEN": "<your-zai-api-key>",
"ANTHROPIC_BASE_URL": "https://api.z.ai/api/anthropic",
"API_TIMEOUT_MS": "3000000"
},
"disallowedTools": ["WebSearch"],
"models": [
{ "id": "glm-5-turbo", "label": "GLM 5 Turbo", "isDefault": true },
{ "id": "glm-5.1", "label": "GLM 5.1" }
]
}
}
}
}`}
</pre>
</section>
<section className="space-y-4">
<h2 className="text-xl font-medium">Alibaba Cloud (Qwen) coding plan</h2>
<p className="text-white/60 leading-relaxed">
Alibaba's coding plan routes Claude Code to Qwen models via an Anthropic-compatible API.
Subscription keys look like <code className="font-mono">sk-sp-...</code> and must be
created in the Singapore region.
</p>
<pre className="bg-card border border-border rounded-lg p-4 font-mono text-sm overflow-x-auto text-white/80">
{`{
"agents": {
"providers": {
"qwen": {
"extends": "claude",
"label": "Qwen (Alibaba)",
"env": {
"ANTHROPIC_AUTH_TOKEN": "sk-sp-<coding-plan-key>",
"ANTHROPIC_BASE_URL": "https://coding-intl.dashscope.aliyuncs.com/apps/anthropic"
},
"disallowedTools": ["WebSearch"],
"models": [
{ "id": "qwen3.5-plus", "label": "Qwen 3.5 Plus", "isDefault": true },
{ "id": "qwen3-coder-next", "label": "Qwen 3 Coder Next" }
]
}
}
}
}`}
</pre>
</section>
<section className="space-y-4">
<h2 className="text-xl font-medium">Multiple profiles</h2>
<p className="text-white/60 leading-relaxed">
Create as many entries as you want against the same first-class provider. Each one shows
up as a separate option in the app with its own credentials and models.
</p>
<pre className="bg-card border border-border rounded-lg p-4 font-mono text-sm overflow-x-auto text-white/80">
{`{
"agents": {
"providers": {
"claude-work": {
"extends": "claude",
"label": "Claude (Work)",
"env": { "ANTHROPIC_API_KEY": "sk-ant-work-..." }
},
"claude-personal": {
"extends": "claude",
"label": "Claude (Personal)",
"env": { "ANTHROPIC_API_KEY": "sk-ant-personal-..." }
}
}
}
}`}
</pre>
</section>
<section className="space-y-4">
<h2 className="text-xl font-medium">Custom binary</h2>
<p className="text-white/60 leading-relaxed">
<code className="font-mono">command</code> is an array — first element is the binary, the
rest are arguments. It fully replaces the default launch command for that provider.
</p>
<pre className="bg-card border border-border rounded-lg p-4 font-mono text-sm overflow-x-auto text-white/80">
{`{
"agents": {
"providers": {
"claude": {
"command": ["/opt/claude-nightly/claude"]
}
}
}
}`}
</pre>
</section>
<section className="space-y-4">
<h2 className="text-xl font-medium">ACP providers</h2>
<p className="text-white/60 leading-relaxed">
Any agent that speaks{" "}
<a
href="https://agentclientprotocol.com"
target="_blank"
rel="noreferrer"
className="underline hover:text-white/80"
>
ACP
</a>{" "}
over stdio can be added with <code className="font-mono">extends: "acp"</code> and a{" "}
<code className="font-mono">command</code>. Paseo spawns the process, sends an{" "}
<code className="font-mono">initialize</code> JSON-RPC request, and the agent reports its
capabilities, modes, and models at runtime.
</p>
<pre className="bg-card border border-border rounded-lg p-4 font-mono text-sm overflow-x-auto text-white/80">
{`{
"agents": {
"providers": {
"gemini": {
"extends": "acp",
"label": "Google Gemini",
"command": ["gemini", "--acp"]
},
"hermes": {
"extends": "acp",
"label": "Hermes",
"command": ["hermes", "acp"]
}
}
}
}`}
</pre>
</section>
<section className="space-y-4">
<h2 className="text-xl font-medium">Adding or relabeling models</h2>
<p className="text-white/60 leading-relaxed">
<code className="font-mono">models</code> replaces the model list entirely.{" "}
<code className="font-mono">additionalModels</code> merges with runtime-discovered models
(ACP) or with <code className="font-mono">models</code> — use it to add an extra entry or
relabel a discovered one without redeclaring the full list. An entry with the same{" "}
<code className="font-mono">id</code> as a discovered model updates it in place.
</p>
<pre className="bg-card border border-border rounded-lg p-4 font-mono text-sm overflow-x-auto text-white/80">
{`{
"agents": {
"providers": {
"gemini": {
"extends": "acp",
"label": "Google Gemini",
"command": ["gemini", "--acp"],
"additionalModels": [
{ "id": "experimental-model", "label": "Experimental", "isDefault": true },
{ "id": "gemini-2.5-pro", "label": "Gemini 2.5 Pro (preferred)" }
]
}
}
}
}`}
</pre>
</section>
<section className="space-y-4">
<h2 className="text-xl font-medium">Disabling a provider</h2>
<pre className="bg-card border border-border rounded-lg p-4 font-mono text-sm overflow-x-auto text-white/80">
{`{
"agents": {
"providers": {
"copilot": { "enabled": false }
}
}
}`}
</pre>
</section>
<section className="space-y-4">
<h2 className="text-xl font-medium">Full reference</h2>
<p className="text-white/60 leading-relaxed">
For the complete field reference (<code className="font-mono">extends</code>,{" "}
<code className="font-mono">label</code>, <code className="font-mono">command</code>,{" "}
<code className="font-mono">env</code>, <code className="font-mono">models</code>,{" "}
<code className="font-mono">additionalModels</code>,{" "}
<code className="font-mono">disallowedTools</code>,{" "}
<code className="font-mono">enabled</code>, <code className="font-mono">order</code>),
model and thinking-option schemas, and deeper examples for each plan, see{" "}
<a
href={CUSTOM_PROVIDERS_URL}
target="_blank"
rel="noreferrer"
className="underline hover:text-white/80"
>
docs/CUSTOM-PROVIDERS.md
</a>{" "}
on GitHub.
</p>
</section>
</div>
);
}
+1
View File
@@ -20,6 +20,7 @@ const sitemapPages = [
"/docs/best-practices",
"/docs/cli",
"/docs/configuration",
"/docs/providers",
"/docs/skills",
"/docs/security",
"/docs/updates",