docs: lowercase internal docs + migrate website docs to public-docs/ (#634)

* docs: rename to lowercase + drop leftover plans

Rename docs in docs/ to lowercase kebab-case for consistency and update
all references in CLAUDE.md, CONTRIBUTING.md, CHANGELOG.md,
packages/server/CLAUDE.md, and inter-doc links.

Drop two leftover design plan docs:
- docs/ATTACHMENT_BASED_REVIEW_CONTEXT_PLAN.md
- docs/plan-approval-normalization.md

* docs: drop stale uppercase entries from case-insensitive rename

* feat(website): power /docs from public-docs/ markdown tree

Move website docs out of TSX route components and into a root-level
public-docs/ directory of plain markdown files with frontmatter
(title, description, nav, order).

- Add packages/website/src/docs.ts loader using import.meta.glob with
  ?raw to compile the markdown into the bundle at build time.
- Replace the 9 hand-written docs/*.tsx routes with a single $.tsx
  catch-all that renders any slug via react-markdown.
- Drive the docs sidebar nav from frontmatter order/nav.
- Auto-discover docs routes in vite.config.ts so the sitemap stays in
  sync without manual edits.

* fix(website): bind dev server to 0.0.0.0 so port collisions trigger fallback

`host: "127.0.0.1"` (or unset) lets macOS coexist with another process
holding an IPv6 dual-stack `*:8082` socket, so Vite never sees
EADDRINUSE and silently binds alongside it. Forcing IPv4 wildcard
makes the conflict real, and Vite's default `strictPort: false`
falls through to the next free port.

* fix(website): restore docs page styling after markdown migration

Add a .docs-prose class that mirrors the styling the original
docs/*.tsx components hand-rolled (h1/h2/h3 sizes, paragraph/list
spacing, link colors, code blocks, callout-style blockquotes).

ReactMarkdown was emitting unstyled HTML because the previous
wrapper class only had inline-code rules — headings and code
blocks fell back to user-agent defaults.
This commit is contained in:
Mohamed Boudra
2026-04-30 17:27:15 +08:00
committed by GitHub
parent 5d9dc0c4d5
commit dec47d72d9
49 changed files with 1395 additions and 2572 deletions

View File

@@ -0,0 +1,56 @@
---
title: Best practices
description: Tips for getting the most out of Paseo and mobile-first agent workflows.
nav: Best practices
order: 10
---
# Best practices
What I've learned from using Paseo daily. Not rules, just patterns that have worked for me.
## Agents replace typing, not thinking
Your role has changed. You're no longer the one writing code line by line. You're the one making decisions: what to build, how it should work, what the architecture looks like. The agent executes, but you direct.
You can't just say "implement feature X" and walk away. You still have to do the hard part: deciding what to build, how it fits into the system, what trade-offs to make. Thinking is not optional. At least for now, agents replace the typing, not the thinking.
## Verification loops
The agent needs a way to verify its work. TDD is one implementation of this pattern: get the agent to write a failing test, verify it fails for the right reasons, then tell it to make the test pass. The agent can loop on its own because it knows what "done" means.
## Invest in tooling
It's not just test runners. For web apps, something like Playwright MCP lets the agent take screenshots and verify UI changes. For a SaaS app I built a CLI that wraps all the business logic so the agent could launch jobs, check statuses, and scrape data without going through the UI.
Code is cheap with coding agents. I would have never written that CLI before because it felt like wasted effort. Now I bootstrap tooling first. It pays off exponentially.
## Agents are cheap
Don't be shy about running multiple agents. Paseo lets you launch agents in isolated worktrees. Kick one off with voice while walking, then kick off another. They work independently. You get a notification when they're done.
## Use voice extensively
It's much more natural to use voice to communicate ideas and pull them out of your brain. The agent will parse and organize your thoughts better than if you try to write the perfect prompt. You don't need to organize anything. Just talk.
Current speech-to-text models are really good. They catch accents, acronyms, technical terms. And even when they don't, the LLM will infer what you meant.
## Understand the type of work
Sometimes you need to plan: design a spec, verify it, get the agent to follow through. Maybe it takes a couple of agents to work through it. Other times it's conversational: kick off a single agent and start talking, asking questions. Match your approach to the task.
## Iterate and refactor often
Don't expect perfect. Expect working. Make it work, make it correct, make it beautiful. Each iteration gets you closer. With tests, refactoring is cheap.
I don't let myself add too many features before stopping to refactor. Sometimes I kick off an agent and have it trace code paths, explain dependencies, show me how modules connect. I make mental notes during code review and circle back.
## Use agents to check agents
If an agent implements something and you ask it to review its own work, it will never find issues. Launch a separate agent with a fresh context to review the first agent's code. It will catch things the first agent missed or glossed over. An agent might say it's done when it's not. Another agent can detect that.
## Learn your agents' quirks
People argue about which model is better. That's the wrong question. Each model has strengths and weaknesses. Knowing them is more useful than chasing benchmarks. Benchmarks don't mean anything. You need to try the models yourself to form an opinion.
I use Claude Code as my main driver because it's quick and uses tools well. But sometimes it jumps to conclusions and gives up too easily. Codex is frustratingly slow but goes deep, doesn't stop, and is methodical. It's also stubborn and too serious. These aren't good or bad traits, just differences you learn to work around. Use the right model for the job.

166
public-docs/cli.md Normal file
View File

@@ -0,0 +1,166 @@
---
title: CLI
description: "Paseo CLI reference: manage agents, daemons, permissions, and worktrees from your terminal."
nav: CLI
order: 5
---
# CLI
The Paseo CLI lets you manage agents from your terminal. It's the same interface exposed by the daemon's API, so anything you can do in the app you can do from the command line.
> **Agent orchestration:** You can tell coding agents to use the Paseo CLI to spawn and manage other agents. This enables multi-agent workflows where one agent delegates subtasks to others and waits for results.
## Quick reference
```bash
paseo run "fix the tests" # Start an agent
paseo ls # List running agents
paseo attach <id> # Stream agent output
paseo send <id> "also fix linting" # Send follow-up task
paseo logs <id> # View agent timeline
paseo stop <id> # Stop an agent
```
## Running agents
Use `paseo run` to start a new agent with a task:
```bash
paseo run "implement user authentication"
paseo run --provider codex "refactor the API layer"
paseo run --detach "run the full test suite" # background
paseo run --worktree feature-x "implement feature X"
paseo run --output-schema schema.json "extract release notes"
paseo run --output-schema '{"type":"object","properties":{"summary":{"type":"string"}},"required":["summary"]}' "summarize release notes"
```
The `--worktree` flag creates the agent in an isolated git worktree, useful for parallel feature development.
Use `--output-schema` to return only matching JSON output. You can pass a schema file path or an inline JSON schema object. This mode cannot be used with `--detach`.
By default, `paseo run` waits for completion. Use `--detach` to run in the background.
## Listing agents
```bash
paseo ls # Running agents in current directory
paseo ls -a # Include completed/stopped agents
paseo ls -g # All directories
paseo ls -a -g --json # Full list as JSON
```
## Streaming output
Use `paseo attach` to stream an agent's output in real-time:
```bash
paseo attach abc123 # Attach to agent (Ctrl+C to detach)
```
Agent IDs can be shortened — `abc` works if it's unambiguous.
## Sending messages
Send follow-up tasks to a running or idle agent:
```bash
paseo send <id> "now run the tests"
paseo send <id> --image screenshot.png "what's wrong here?"
paseo send <id> --no-wait "queue this task"
```
## Viewing logs
```bash
paseo logs <id> # Full timeline
paseo logs <id> -f # Follow (streaming)
paseo logs <id> --tail 10 # Last 10 entries
paseo logs <id> --filter tools # Only tool calls
```
## Waiting for agents
Block until an agent finishes its current task:
```bash
paseo wait <id>
paseo wait <id> --timeout 60 # 60 second timeout
```
Useful in scripts or when one agent needs to wait for another.
## Permissions
Agents may request permission for certain actions. Manage these from the CLI:
```bash
paseo permit ls # List pending requests
paseo permit allow <id> # Allow all pending for agent
paseo permit deny <id> --all # Deny all pending
```
## Agent modes
Change an agent's operational mode (provider-specific):
```bash
paseo agent mode <id> --list # Show available modes
paseo agent mode <id> bypass # Set bypass mode
paseo agent mode <id> plan # Set plan mode
```
## Daemon management
```bash
paseo daemon start # Start the daemon
paseo daemon status # Check status
paseo daemon stop # Stop the daemon
```
Use `PASEO_HOME` to run multiple isolated daemon instances.
## Multi-agent workflows
The CLI is designed to be used by agents themselves. You can instruct an agent to spawn sub-agents for parallel work:
```bash
# Agent A spawns Agent B and waits for it
paseo run --detach "implement the API" --name api-agent
paseo wait api-agent
paseo logs api-agent --tail 5
```
Simple implement + verify loop:
```bash
# Requires jq
while true; do
paseo run --provider codex "make the tests pass" >/dev/null
verdict=$(paseo run --provider claude --output-schema '{"type":"object","properties":{"criteria_met":{"type":"boolean"}},"required":["criteria_met"],"additionalProperties":false}' "ensure tests all pass")
if echo "$verdict" | jq -e '.criteria_met == true' >/dev/null; then
echo "criteria met"
break
fi
done
```
This pattern enables hierarchical task decomposition — a lead agent can break down work, delegate to specialists, and synthesize results.
## Output formats
Most commands support multiple output formats for scripting:
```bash
paseo ls --json # JSON output
paseo ls --format yaml # YAML output
paseo ls -q # IDs only (quiet)
```
## Global options
- `--host <host:port>` — connect to a different daemon
- `--json` — JSON output
- `-q, --quiet` — minimal output
- `--no-color` — disable colors

View File

@@ -0,0 +1,118 @@
---
title: Configuration
description: Configure Paseo via config.json, environment variables, and CLI overrides.
nav: Configuration
order: 8
---
# Configuration
Paseo loads configuration from a single JSON file in your Paseo home directory, with optional environment variable and CLI overrides.
## Where config lives
By default, Paseo uses `~/.paseo` as its home directory. The configuration file is:
```bash
~/.paseo/config.json
```
You can change the home directory by setting `PASEO_HOME` or passing `--home` to `paseo daemon start`.
## Precedence
Paseo merges configuration in this order:
1. Defaults
2. `config.json`
3. Environment variables
4. CLI flags
Lists append across sources (for example, `hostnames` and `cors.allowedOrigins`).
## Example
Minimal example that configures listening address, hostnames, and MCP:
```json
{
"$schema": "https://paseo.sh/schemas/paseo.config.v1.json",
"version": 1,
"daemon": {
"listen": "127.0.0.1:6767",
"hostnames": ["localhost", ".localhost"],
"mcp": { "enabled": true }
}
}
```
`daemon.hostnames` is the primary field. The old `daemon.allowedHosts` name still works as a deprecated alias for backward compatibility.
## Agent providers
Agent providers — both the first-class ones Paseo ships with and custom entries you add under `agents.providers` — are documented on their own page.
See [Providers](/docs/providers) for first-class providers, how to point Claude at Anthropic-compatible endpoints (Z.AI, Alibaba/Qwen), multiple profiles, custom binaries, ACP agents, and the `additionalModels` merge behavior. The full field reference lives on GitHub at [docs/custom-providers.md](https://github.com/getpaseo/paseo/blob/main/docs/custom-providers.md).
## Voice
Voice is configured through `features.dictation` and `features.voiceMode`, with provider credentials under `providers`.
For voice philosophy, architecture, and complete local/OpenAI setup examples, see [Voice docs](/docs/voice).
## Logging
Daemon logging uses separate console and file sinks by default:
- Console: `info` and above
- File (`$PASEO_HOME/daemon.log`): `trace` and above
- File rotation: `10m` max file size, `2` retained files total (active + 1 rotated)
```json
{
"log": {
"console": {
"level": "info",
"format": "pretty"
},
"file": {
"level": "trace",
"path": "daemon.log",
"rotate": {
"maxSize": "10m",
"maxFiles": 2
}
}
}
}
```
Legacy fields `log.level` and `log.format` are still supported and map to the new destination settings.
## Common env vars
- `PASEO_HOME` — set Paseo home directory
- `PASEO_LISTEN` — override `daemon.listen`
- `PASEO_HOSTNAMES` — override/extend `daemon.hostnames`
- `PASEO_ALLOWED_HOSTS` — deprecated alias for `PASEO_HOSTNAMES`
- `PASEO_LOG_CONSOLE_LEVEL` — override `log.console.level`
- `PASEO_LOG_FILE_LEVEL` — override `log.file.level`
- `PASEO_LOG_FILE_PATH` — override `log.file.path`
- `PASEO_LOG_FILE_ROTATE_SIZE` — override `log.file.rotate.maxSize`
- `PASEO_LOG_FILE_ROTATE_COUNT` — override `log.file.rotate.maxFiles`
- `PASEO_LOG`, `PASEO_LOG_FORMAT` — legacy log overrides (still supported)
- `OPENAI_API_KEY` — override OpenAI provider key
- `PASEO_VOICE_LLM_PROVIDER` — override voice LLM provider (`claude`, `codex`, `opencode`)
- `PASEO_DICTATION_STT_PROVIDER`, `PASEO_VOICE_STT_PROVIDER`, `PASEO_VOICE_TTS_PROVIDER` — override voice provider selection (`local` or `openai`)
- `PASEO_LOCAL_MODELS_DIR` — control local model directory
- `PASEO_DICTATION_LOCAL_STT_MODEL` — override local dictation STT model
- `PASEO_VOICE_LOCAL_STT_MODEL`, `PASEO_VOICE_LOCAL_TTS_MODEL` — override local voice STT/TTS models
- `PASEO_VOICE_LOCAL_TTS_SPEAKER_ID`, `PASEO_VOICE_LOCAL_TTS_SPEED` — optional local voice TTS tuning
## Schema
For editor autocomplete/validation, set `$schema` to:
```
https://paseo.sh/schemas/paseo.config.v1.json
```

58
public-docs/index.md Normal file
View File

@@ -0,0 +1,58 @@
---
title: Getting started
description: Learn how to set up and use Paseo to manage your coding agents from anywhere.
nav: Getting started
order: 1
---
# Getting started
Paseo has three main pieces: the daemon is the local server that manages your agents, the app is the client you use from mobile, web, or desktop, and the CLI is the terminal interface that can also launch the daemon.
## Prerequisites
Paseo manages existing agent CLIs. Install at least one agent and make sure it already works with your credentials before you set up Paseo.
- [Claude Code](https://docs.anthropic.com/en/docs/claude-code)
- [Codex](https://github.com/openai/codex)
- [OpenCode](https://github.com/anomalyco/opencode)
## Desktop App
Download the desktop app from [paseo.sh/download](https://paseo.sh/download) or the [GitHub releases page](https://github.com/getpaseo/paseo/releases). Open it and you're done.
The desktop app bundles and manages its own daemon automatically, so you do not need a separate CLI install on that machine unless you want it.
On first launch, you may briefly see a startup screen while the local server starts and the app connects to it. After that, connect from your phone by scanning the QR code in Settings if you want mobile access.
## CLI / Server
Use this path for headless setups, servers, or remote machines where you want the daemon running without the desktop app.
```bash
npm install -g @getpaseo/cli
```
```bash
paseo
```
Paseo prints a QR code in the terminal. Scan it from the mobile app, or enter the daemon address manually from another client.
Configuration and local state live under `PASEO_HOME`.
## Voice Setup
Paseo includes first-class voice support with a local-first architecture and configurable speech providers.
For architecture, local model behavior, and provider configuration, see the Voice docs page.
[Voice docs](/docs/voice)
## Next
- [Updates](/docs/updates)
- [Voice](/docs/voice)
- [Providers](/docs/providers)
- [Configuration](/docs/configuration)
- [Security](/docs/security)

206
public-docs/providers.md Normal file
View File

@@ -0,0 +1,206 @@
---
title: Providers
description: First-class agent providers in Paseo, and how to configure custom providers, ACP agents, and profiles.
nav: Providers
order: 7
---
# Providers
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 `config.json` — either by pointing an existing provider at a different API, adding extra profiles, or plugging in any [ACP](https://agentclientprotocol.com)-compatible agent.
## First-class providers
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.
- `claude` — Anthropic's Claude Code. Multi-tool assistant with MCP support, streaming, and deep reasoning.
- `codex` — OpenAI's Codex workspace agent with sandbox controls and optional network access.
- `opencode` — Open-source coding assistant with multi-provider model support.
- `copilot` — GitHub Copilot via ACP, with dynamic modes and session support.
- `pi` — Minimal terminal-based coding agent with multi-provider LLM support.
## Custom providers
Everything beyond the defaults lives under `agents.providers` in `~/.paseo/config.json`. You can:
- **Extend** a first-class provider to point at a different API (Z.AI, Alibaba/Qwen, a proxy, a self-hosted endpoint).
- **Add profiles** — multiple entries against the same underlying provider with different credentials or curated model lists.
- **Override the binary** — run a nightly build, a wrapper script, or a Docker image instead of the installed CLI.
- **Add ACP agents** — Gemini CLI, Hermes, or any agent speaking the Agent Client Protocol over stdio.
- **Disable** a provider you don't use.
Provider IDs must be lowercase alphanumeric with hyphens (`/^[a-z][a-z0-9-]*$/`). Every custom entry needs `extends` (a first-class provider ID or `"acp"`) and a `label`.
The examples below are a quick tour. The full, up-to-date reference is on GitHub: [docs/custom-providers.md](https://github.com/getpaseo/paseo/blob/main/docs/custom-providers.md).
## Extending a first-class provider
```json
{
"agents": {
"providers": {
"my-claude": {
"extends": "claude",
"label": "My Claude",
"env": {
"ANTHROPIC_API_KEY": "sk-ant-...",
"ANTHROPIC_BASE_URL": "https://my-proxy.example.com/v1"
}
}
}
}
}
```
## Z.AI (GLM) coding plan
Z.AI exposes GLM models through an Anthropic-compatible endpoint. Point `ANTHROPIC_BASE_URL` at their API and use `ANTHROPIC_AUTH_TOKEN` for the key. Third-party endpoints don't support Anthropic's server-side tools, so disable `WebSearch`.
```json
{
"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" }
]
}
}
}
}
```
## Alibaba Cloud (Qwen) coding plan
Alibaba's coding plan routes Claude Code to Qwen models via an Anthropic-compatible API. Subscription keys look like `sk-sp-...` and must be created in the Singapore region.
```json
{
"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" }
]
}
}
}
}
```
## Multiple profiles
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.
```json
{
"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-..." }
}
}
}
}
```
## Custom binary
`command` is an array — first element is the binary, the rest are arguments. It fully replaces the default launch command for that provider.
```json
{
"agents": {
"providers": {
"claude": {
"command": ["/opt/claude-nightly/claude"]
}
}
}
}
```
## ACP providers
Any agent that speaks [ACP](https://agentclientprotocol.com) over stdio can be added with `extends: "acp"` and a `command`. Paseo spawns the process, sends an `initialize` JSON-RPC request, and the agent reports its capabilities, modes, and models at runtime.
```json
{
"agents": {
"providers": {
"gemini": {
"extends": "acp",
"label": "Google Gemini",
"command": ["gemini", "--acp"]
},
"hermes": {
"extends": "acp",
"label": "Hermes",
"command": ["hermes", "acp"]
}
}
}
}
```
## Adding or relabeling models
`models` replaces the model list entirely. `additionalModels` merges with runtime-discovered models (ACP) or with `models` — use it to add an extra entry or relabel a discovered one without redeclaring the full list. An entry with the same `id` as a discovered model updates it in place.
```json
{
"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)" }
]
}
}
}
}
```
## Disabling a provider
```json
{
"agents": {
"providers": {
"copilot": { "enabled": false }
}
}
}
```
## Full reference
For the complete field reference (`extends`, `label`, `command`, `env`, `models`, `additionalModels`, `disallowedTools`, `enabled`, `order`), model and thinking-option schemas, and deeper examples for each plan, see [docs/custom-providers.md](https://github.com/getpaseo/paseo/blob/main/docs/custom-providers.md) on GitHub.

103
public-docs/security.md Normal file
View File

@@ -0,0 +1,103 @@
---
title: Security
description: "Security model for Paseo: architecture overview, connection methods, relay encryption, and best practices."
nav: Security
order: 9
---
# Security
Paseo follows a client-server architecture, similar to Docker. The daemon runs on your machine and manages your coding agents. Clients (the mobile app, CLI, or web interface) connect to the daemon to monitor and control those agents.
Your code never leaves your machine. Paseo is a local-first tool that connects directly to your development environment.
## Architecture
The Paseo daemon can run anywhere you want to execute agents: your laptop, a Mac Mini, a VPS, or a Docker container. The daemon listens for connections and manages agent lifecycles.
Clients connect to the daemon over WebSocket. There are two ways to establish this connection:
- **Relay connection (recommended)** — The daemon connects outbound to our relay server, and clients meet it there. No open ports required.
- **Direct connection** — The daemon listens on a network address and clients connect directly.
## Relay connections (recommended)
The relay is the simplest way to connect from your phone. It requires no VPN setup, no port forwarding, and no firewall configuration. The daemon can stay bound to localhost or a socket file — it connects _outbound_ to the relay, and your phone meets it there.
> **The relay is designed to be untrusted.** All traffic between your phone and daemon is end-to-end encrypted. The relay server cannot read your messages, see your code, or modify traffic without detection. Even if the relay is compromised, your data remains protected.
### How it works
1. The daemon generates a persistent ECDH keypair and stores it in `$PASEO_HOME/daemon-keypair.json`
2. When you scan the QR code or click the pairing link, your phone receives the daemon's public key
3. Your phone sends a handshake message with its own public key. The daemon will not accept any commands until this handshake completes.
4. Both sides perform an ECDH key exchange to derive a shared secret. All subsequent messages are encrypted with AES-256-GCM.
The relay sees only: IP addresses, timing, message sizes, and session IDs. It cannot read message contents, forge messages, or derive encryption keys from observing the handshake.
### Why the relay can't attack you
The daemon requires a valid cryptographic handshake before processing any commands. A compromised relay cannot:
- **Send commands** — Without your phone's private key, it cannot complete the handshake
- **Read your traffic** — All messages are encrypted with AES-256-GCM after the handshake
- **Forge messages** — GCM provides authenticated encryption; tampered messages are rejected
- **Replay old messages** — Each session derives fresh encryption keys
### Trust model
The QR code or pairing link is the trust anchor. It contains the daemon's public key, which is required to establish the encrypted connection. Treat it like a password — don't share it publicly.
If you believe a pairing offer has been compromised, restart the daemon to generate a new session ID and rotate the relay pairing.
## Direct connections
By default, the daemon listens on `127.0.0.1:6767` (localhost only). This is safe for local CLI usage but not reachable from your phone or other devices.
### Socket file (CLI only)
For maximum isolation, you can configure the daemon to listen on a Unix socket file instead of a TCP port. This prevents any network access entirely — only processes on the same machine can connect. The CLI supports this mode, but the mobile app and web interface require a network connection.
### VPN access
If you prefer direct connections over the relay, you can use a VPN like [Tailscale](https://tailscale.com). Tailscale creates a private network between your devices, so you can access your daemon without exposing it to the public internet.
To set this up:
1. Install Tailscale on your machine and phone and join them to the same [tailnet](https://tailscale.com/kb/1136/tailnet)
2. Configure the daemon to listen on your Tailscale IP (e.g., `100.x.y.z:6767`)
3. Add your Tailscale hostname to `hostnames` and `cors.allowedOrigins`
4. Add the daemon as a direct connection in the Paseo app using the Tailscale address
### Binding to 0.0.0.0
> **Warning:** Binding to `0.0.0.0` makes the daemon reachable on all network interfaces, including public Wi-Fi and local networks. This can expose your daemon to unauthorized access. If you must bind to all interfaces, ensure you have proper firewall rules and review your `hostnames` configuration.
## DNS rebinding protection
**CORS is not a complete security boundary.** It controls which browser origins can make requests, but does not prevent a malicious website from resolving its domain to your local machine (DNS rebinding).
Paseo uses a host allowlist to validate the `Host` header on incoming requests. Requests with unrecognized hosts are rejected.
Configure via `daemon.hostnames` in `config.json`:
- Default (`[]`): allow `localhost`, `*.localhost`, and all IP addresses
- `['.example.com']`: allow `example.com` and any subdomain, plus defaults
- `true`: allow any host (not recommended)
## Agent authentication
Paseo wraps agent CLIs (Claude Code, Codex, OpenCode) but does not manage their authentication. Each agent provider handles its own credentials:
- **Claude Code** — authenticates via Anthropic's OAuth flow, stored in `~/.claude/`
- **Codex** — uses your OpenAI API key or OAuth session
- **OpenCode** — configured via provider-specific API keys
Paseo never stores or transmits provider API keys. Agents run in your user context with your existing credentials.
## Recommendations
- **Use the relay** for mobile access — it's the simplest option and all traffic is end-to-end encrypted
- **Treat the QR code like a password** — anyone with the pairing offer can connect to your daemon
- **Never bind to 0.0.0.0** unless you understand the implications and have proper firewall rules
- **Keep your daemon updated** — security improvements are released regularly

77
public-docs/skills.md Normal file
View File

@@ -0,0 +1,77 @@
---
title: Orchestration skills
description: "Paseo orchestration skills: teach coding agents to spawn, coordinate, and manage other agents using slash commands."
nav: Skills
order: 6
---
# Orchestration skills
Paseo ships orchestration skills that teach coding agents (Claude Code, Codex) how to use the Paseo CLI to spawn, coordinate, and manage other agents. Skills are slash commands your agent can invoke — they provide the prompts, context, and workflows so agents know how to orchestrate without you writing boilerplate. Install them from the desktop app's Integrations settings or via the CLI.
## Installation
Two ways to install:
- **Desktop app:** Settings → Integrations → Install
- **Manual:** `npx skills add getpaseo/paseo` — this installs to `~/.agents/skills/` and sets up symlinks for each agent.
## `/paseo` — CLI Reference
The foundational skill. Loaded automatically by other skills. Contains the full Paseo CLI command reference so agents know how to run commands.
Not typically invoked directly by users — it's a reference that other skills depend on.
## `/paseo-handoff` — Task Handoff
Hands off your current task to another agent with full context. The receiving agent gets a comprehensive prompt with: task description, relevant files, what's been tried, decisions made, and acceptance criteria.
Default provider is Codex. Can specify Claude (sonnet/opus). Supports `--worktree` for isolated git branches.
```
/paseo-handoff hand off the auth fix to codex in a worktree
/paseo-handoff hand this to claude opus for review
```
## `/paseo-loop` — Iterative Loops
Runs an agent in a loop with automatic verification until an exit condition is met. Worker runs, verifier checks, repeat until done or max iterations. Supports different providers for worker vs verifier (e.g., Codex implements, Claude verifies).
Stop conditions: `--max-iterations`, `--max-time`, or verification passes.
```
/paseo-loop fix the failing tests, verify with npm test, max 5 iterations
/paseo-loop use codex to implement, claude sonnet to verify, loop until tests pass
```
## `/paseo-orchestrator` — Team Orchestration
Builds and manages a team of agents coordinating through a shared chat room. You describe the work, it sets up roles, launches agents, and coordinates through chat. Uses a heartbeat schedule to check progress.
Cross-provider: typically Codex for implementation, Claude for review.
```
/paseo-orchestrator spin up a team to implement the database migration, codex implements, claude reviews
```
## `/paseo-chat` — Chat Rooms
Use persistent chat rooms for asynchronous agent coordination. Create rooms, post messages, read history, wait for replies. Supports @mentions for specific agents or @everyone.
Typically used by the orchestrator skill, but can be used directly.
```
/paseo-chat create a room called "backend-refactor" for coordinating the API changes
/paseo-chat post to backend-refactor: "API endpoints are done, ready for review"
```
## `/paseo-committee` — Committee Planning
Forms a committee of two high-reasoning agents (Claude Opus + GPT 5.4) to analyze a problem before implementing. Both agents reason in parallel, then plans are merged. Useful when stuck, looping, or facing a hard architectural decision.
Agents are prevented from editing code — they only produce a plan.
```
/paseo-committee why are the websocket connections dropping under load?
/paseo-committee plan the auth system migration
```

42
public-docs/updates.md Normal file
View File

@@ -0,0 +1,42 @@
---
title: Updates
description: How to update Paseo daemon and apps across web, desktop, and mobile.
nav: Updates
order: 2
---
# Updates
Keep your daemon and apps current to get the latest fixes and features.
## Version compatibility
For now, daemon and app versions should be kept in lockstep. If your daemon is version X, make sure your clients are also version X.
## Update the daemon
Install the latest CLI/daemon package globally:
```bash
npm install -g @getpaseo/cli@latest
```
Then restart the daemon:
```bash
paseo daemon restart
```
## Web app
[app.paseo.sh](https://app.paseo.sh) is always up to date. No manual update needed.
## Desktop app
Download the latest desktop build from the GitHub releases page and install it over your current version.
[Paseo releases](https://github.com/getpaseo/paseo/releases)
## Mobile apps
Mobile apps are available on the App Store and Play Store. Update through your respective store. Store versions may lag behind the latest release due to review processes.

81
public-docs/voice.md Normal file
View File

@@ -0,0 +1,81 @@
---
title: Voice
description: Paseo voice architecture, local-first model execution, and provider configuration.
nav: Voice
order: 3
---
# Voice
Paseo has first-class voice support for dictation and realtime conversations with your coding environment.
## Philosophy
Voice is local-first. You can run speech fully on-device, or choose OpenAI for speech features. For voice reasoning/orchestration, Paseo reuses agent providers already installed and authenticated on your machine.
This keeps credentials and execution in your environment and avoids introducing a separate cloud-only voice stack.
## Architecture
- Speech I/O: STT and TTS providers per feature (`local` or `openai`)
- Local speech runtime: ONNX models executed on CPU by default
- Voice LLM orchestration: hidden agent session using your configured provider (`claude`, `codex`, or `opencode`)
- Tooling path: MCP stdio bridge for voice tools and agent control
## Local Speech
Local speech defaults to model IDs `parakeet-tdt-0.6b-v3-int8` (STT) and `kokoro-en-v0_19` (TTS, speaker 0 / voice 00).
Missing models are downloaded at daemon startup into `$PASEO_HOME/models/local-speech`. Downloads happen only for missing files.
```json
{
"version": 1,
"features": {
"dictation": { "stt": { "provider": "local", "model": "parakeet-tdt-0.6b-v3-int8" } },
"voiceMode": {
"llm": { "provider": "claude", "model": "haiku" },
"stt": { "provider": "local", "model": "parakeet-tdt-0.6b-v3-int8" },
"tts": { "provider": "local", "model": "kokoro-en-v0_19", "speakerId": 0 }
}
},
"providers": {
"local": {
"modelsDir": "~/.paseo/models/local-speech"
}
}
}
```
## OpenAI Speech Option
You can switch dictation, voice STT, and voice TTS to OpenAI by setting provider fields to `openai` and providing `OPENAI_API_KEY`.
```json
{
"version": 1,
"features": {
"dictation": { "stt": { "provider": "openai" } },
"voiceMode": {
"stt": { "provider": "openai" },
"tts": { "provider": "openai" }
}
},
"providers": {
"openai": { "apiKey": "..." }
}
}
```
## Environment Variables
- `OPENAI_API_KEY` — OpenAI speech credentials
- `PASEO_VOICE_LLM_PROVIDER` — voice agent provider override
- `PASEO_LOCAL_MODELS_DIR` — local model storage directory
- `PASEO_DICTATION_LOCAL_STT_MODEL` — local dictation STT model ID
- `PASEO_VOICE_LOCAL_STT_MODEL`, `PASEO_VOICE_LOCAL_TTS_MODEL` — local voice STT/TTS model IDs
- `PASEO_VOICE_LOCAL_TTS_SPEAKER_ID`, `PASEO_VOICE_LOCAL_TTS_SPEED` — optional local voice TTS tuning
## Operational Notes
Realtime voice can launch and control agents. Treat voice prompts with the same care as direct agent instructions, especially when specifying working directories or destructive operations.

163
public-docs/worktrees.md Normal file
View File

@@ -0,0 +1,163 @@
---
title: Git worktrees
description: Run agents in isolated git worktrees with setup hooks, scripts, and long-running services.
nav: Git worktrees
order: 4
---
# Git worktrees
Each agent runs in its own git worktree — a separate directory on a separate branch — so parallel agents never step on each other. You configure setup, scripts, and long-running services through a `paseo.json` file at your repo root.
## Layout and workflow
Worktrees live under `$PASEO_HOME/worktrees/`, grouped by a hash of the source checkout path. Each worktree gets a random slug; the branch name is chosen when you first launch an agent.
```
~/.paseo/worktrees/
└── 1vnnm9k3/ # hash of source checkout path
├── tidy-fox/ # worktree slug (branch set on first agent)
└── bold-owl/
```
1. Create a worktree — Paseo runs your setup hooks
2. Launch an agent — a branch is created or assigned
3. Review the diff against the base branch
4. Merge or archive — archive runs teardown and removes the directory
## paseo.json
Drop a `paseo.json` in your repo root. Paseo reads it from the committed version of the base branch you picked, so uncommitted changes in other branches don't apply.
```json
{
"worktree": {
"setup": "npm ci",
"teardown": "rm -rf .cache"
},
"scripts": {
"test": { "command": "npm test" },
"web": { "command": "npm run dev", "type": "service", "port": 3000 }
}
}
```
## Setup and teardown
`setup` runs once after the worktree is created. A fresh worktree has no installed dependencies and no ignored files (like `.env`), so use setup to install and copy what you need. `teardown` runs during archive, before the directory is removed.
```json
{
"worktree": {
"setup": "npm ci\ncp \"$PASEO_SOURCE_CHECKOUT_PATH/.env\" .env\nnpm run db:migrate",
"teardown": "npm run db:drop || true"
}
}
```
Both fields accept a multiline shell script or an array of commands; commands run sequentially either way.
Commands run with the worktree as `cwd`. Use `$PASEO_SOURCE_CHECKOUT_PATH` to reach files in the original checkout (untracked config, local caches, etc).
## Scripts and services
`scripts` are named commands you can run inside a worktree on demand. Mark one as a _service_ and Paseo supervises it as a long-running process, assigns it a port, and routes HTTP traffic to it through the daemon's reverse proxy.
### Plain scripts
```json
{
"scripts": {
"test": { "command": "npm test" },
"lint": { "command": "npm run lint" },
"generate": { "command": "npm run codegen" }
}
}
```
### Services
```json
{
"scripts": {
"web": {
"type": "service",
"command": "npm run dev -- --port $PASEO_PORT",
"port": 3000
},
"api": {
"type": "service",
"command": "npm run api -- --port $PASEO_PORT"
}
}
}
```
Omit `port` to let Paseo auto-assign one. Bind your process to `$PASEO_PORT` rather than hard-coding — each worktree gets a distinct port so multiple copies of the same service coexist.
### Reverse proxy
Every service is reachable through the daemon at a deterministic hostname:
```
http://<script>.<branch>.<project>.localhost:<daemon-port>
# on the default branch, the branch label is dropped:
http://<script>.<project>.localhost:<daemon-port>
```
`*.localhost` resolves to `127.0.0.1` on modern systems, so these URLs work out of the box. The proxy supports WebSocket upgrades.
### Service-to-service
Services launched from the same workspace see each other's ports and proxy URLs. Given `web` and `api` above, each process gets:
```
PASEO_PORT=3000 # this service's port
PASEO_URL=http://web.my-app.localhost:6767 # this service's proxy URL
PASEO_SERVICE_API_PORT=51732
PASEO_SERVICE_API_URL=http://api.my-app.localhost:6767
PASEO_SERVICE_WEB_PORT=3000
PASEO_SERVICE_WEB_URL=http://web.my-app.localhost:6767
```
Script names are upper-cased and non-alphanumerics become `_`. Point your frontend at `$PASEO_SERVICE_API_URL` instead of hard-coding a port.
## Terminals
Open terminals automatically when a worktree is created. Useful for tailing logs or leaving a REPL ready to go.
```json
{
"worktree": {
"terminals": [
{ "name": "logs", "command": "tail -f dev.log" },
{ "name": "shell", "command": "bash" }
]
}
}
```
## Environment variables
Setup, teardown, scripts, and services all see:
- `$PASEO_SOURCE_CHECKOUT_PATH` — the original repo root
- `$PASEO_WORKTREE_PATH` — the worktree directory
- `$PASEO_BRANCH_NAME` — the worktree's branch
- `$PASEO_WORKTREE_PORT` — legacy per-worktree port (prefer `$PASEO_PORT` inside services)
Services additionally get:
- `$PASEO_PORT` — this service's assigned port
- `$PASEO_URL` — this service's proxy URL
- `$PASEO_SERVICE_<NAME>_PORT` / `_URL` — peer service ports and URLs
- `$HOST``127.0.0.1` for local-only daemons, `0.0.0.0` when the daemon binds all interfaces
## CLI
```bash
paseo run --worktree feature-auth --base main "implement auth"
paseo worktree ls
paseo worktree archive feature-auth
```