From e6c3f2838b81179d81ade6e05e31f50f779fa662 Mon Sep 17 00:00:00 2001 From: Mohamed Boudra Date: Thu, 5 Feb 2026 14:20:20 +0700 Subject: [PATCH] restore website docs routes --- .../src/routes/docs/best-practices.tsx | 149 +++++++++ .../website/src/routes/docs/configuration.tsx | 104 +++++++ packages/website/src/routes/docs/index.tsx | 118 +++++++ packages/website/src/routes/docs/security.tsx | 290 ++++++++++++++++++ 4 files changed, 661 insertions(+) create mode 100644 packages/website/src/routes/docs/best-practices.tsx create mode 100644 packages/website/src/routes/docs/configuration.tsx create mode 100644 packages/website/src/routes/docs/index.tsx create mode 100644 packages/website/src/routes/docs/security.tsx diff --git a/packages/website/src/routes/docs/best-practices.tsx b/packages/website/src/routes/docs/best-practices.tsx new file mode 100644 index 000000000..ea9a330d1 --- /dev/null +++ b/packages/website/src/routes/docs/best-practices.tsx @@ -0,0 +1,149 @@ +import { createFileRoute } from '@tanstack/react-router' + +export const Route = createFileRoute('/docs/best-practices')({ + head: () => ({ + meta: [ + { title: 'Best Practices - Paseo Docs' }, + { + name: 'description', + content: 'Tips for getting the most out of Paseo and mobile-first agent workflows.', + }, + ], + }), + component: BestPractices, +}) + +function BestPractices() { + return ( +
+
+

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. +

+
+
+ ) +} diff --git a/packages/website/src/routes/docs/configuration.tsx b/packages/website/src/routes/docs/configuration.tsx new file mode 100644 index 000000000..5841f851a --- /dev/null +++ b/packages/website/src/routes/docs/configuration.tsx @@ -0,0 +1,104 @@ +import { createFileRoute } from '@tanstack/react-router' + +export const Route = createFileRoute('/docs/configuration')({ + head: () => ({ + meta: [ + { title: 'Configuration - Paseo Docs' }, + { + name: 'description', + content: 'Configure Paseo via config.json, environment variables, and CLI overrides.', + }, + ], + }), + component: Configuration, +}) + +function Configuration() { + return ( +
+
+

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: +

+
+ $ + ~/.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. +
  3. config.json
  4. +
  5. Environment variables
  6. +
  7. CLI flags
  8. +
+

+ Lists append across sources (for example, allowedHosts and + cors.allowedOrigins). +

+
+ +
+

Example

+

+ Minimal example that configures listening address, host allowlist, provider keys, and MCP: +

+
+{`{
+  "$schema": "https://paseo.dev/schemas/paseo.config.v1.json",
+  "version": 1,
+  "providers": {
+    "openai": { "apiKey": "..." },
+    "openrouter": { "apiKey": "..." }
+  },
+  "daemon": {
+    "listen": "127.0.0.1:6767",
+    "allowedHosts": ["localhost", ".localhost"],
+    "mcp": { "enabled": true }
+  }
+}`}
+        
+
+ +
+

Common env vars

+
    +
  • PASEO_HOME — set Paseo home directory
  • +
  • PASEO_LISTEN — override daemon.listen
  • +
  • PASEO_ALLOWED_HOSTS — override/extend daemon.allowedHosts
  • +
  • OPENAI_API_KEY and OPENROUTER_API_KEY — override provider keys
  • +
+
+ +
+

Schema

+

+ For editor autocomplete/validation, set $schema to: +

+
+ https://paseo.dev/schemas/paseo.config.v1.json +
+
+
+ ) +} + diff --git a/packages/website/src/routes/docs/index.tsx b/packages/website/src/routes/docs/index.tsx new file mode 100644 index 000000000..56d3e40a9 --- /dev/null +++ b/packages/website/src/routes/docs/index.tsx @@ -0,0 +1,118 @@ +import { createFileRoute } from '@tanstack/react-router' + +export const Route = createFileRoute('/docs/')({ + head: () => ({ + meta: [ + { title: 'Getting Started - Paseo Docs' }, + { + name: 'description', + content: 'Learn how to set up and use Paseo to manage your coding agents from anywhere.', + }, + ], + }), + component: GettingStarted, +}) + +function GettingStarted() { + return ( +
+
+

Getting Started

+

+ Paseo connects to your local development environment and lets you manage your coding agents from anywhere. +

+
+ +
+

Installation

+

+ Install the server globally and run it on your machine: +

+
+ $ + npm install -g @paseohq/server +
+
+ $ + paseo +
+
+ +
+

Connect the App

+

+ Open Paseo on your phone and scan the QR code displayed in your terminal, or enter the server address manually. +

+
+ +
+

Prerequisites

+

+ Paseo wraps CLI tools like Claude Code and Codex. You'll need to have them installed and configured with your own credentials before Paseo can manage them. +

+ +
+ +
+

Voice Setup

+

+ Voice features currently require an OpenAI API key. Set it as an environment variable before running the server: +

+
+ $ + export OPENAI_API_KEY=your-key-here +
+

+ Local voice support is coming soon. +

+
+ +
+

Next

+ +
+
+ ) +} diff --git a/packages/website/src/routes/docs/security.tsx b/packages/website/src/routes/docs/security.tsx new file mode 100644 index 000000000..31b372b2e --- /dev/null +++ b/packages/website/src/routes/docs/security.tsx @@ -0,0 +1,290 @@ +import { createFileRoute } from '@tanstack/react-router' + +export const Route = createFileRoute('/docs/security')({ + head: () => ({ + meta: [ + { title: 'Security - Paseo Docs' }, + { + name: 'description', + content: + 'Security model for Paseo: architecture overview, connection methods, relay encryption, and best practices.', + }, + ], + }), + component: Security, +}) + +function Callout({ children }: { children: React.ReactNode }) { + return ( +
+ {children} +
+ ) +} + +function Security() { + return ( +
+
+

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 Overview */} +
+

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 Connection */} +
+

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. +
  3. + When you scan the QR code or click the pairing link, your phone receives the daemon's + public key +
  4. +
  5. + Your phone sends a handshake message with its own public key. The daemon will not accept + any commands until this handshake completes. +
  6. +
  7. + Both sides perform an ECDH key exchange to derive a shared secret. All subsequent + messages are encrypted with AES-256-GCM. +
  8. +
+

+ 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 Connection */} +
+

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 + + . 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 + +
  2. +
  3. + Configure the daemon to listen on your Tailscale IP (e.g.,{' '} + 100.x.y.z:6767) +
  4. +
  5. + Add your Tailscale hostname to allowedHosts and{' '} + cors.allowedOrigins +
  6. +
  7. Add the daemon as a direct connection in the Paseo app using the Tailscale address
  8. +
+ +

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{' '} + allowedHosts configuration. +
+
+ + {/* DNS Rebinding Protection */} +
+

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.allowedHosts 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 */} +
+

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. +

+
+ + {/* Best Practices Summary */} +
+

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 +
  • +
+
+
+ ) +}