Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

PaddleBoard

PaddleBoard is a fork of Zed tuned for AI-native development. It keeps Zed’s speed, GPU-accelerated rendering, LSP, debugger, terminal, and git workflow, then layers on the pieces a modern coding agent actually needs — on your terms:

  • Bring-your-own-key models — OpenAI, Anthropic, Google, Vertex AI, Bedrock, and more. PaddleBoard sells no plan of its own and gates nothing behind a sign-in.
  • An agent workbench — an agent panel with delegation, plus first-class support for the ADK, LangGraph, CrewAI, and AutoGen frameworks.
  • The AI Dock — install and manage agents, skills, and MCP servers from one place.
  • Private by default — telemetry is hard-disabled at the source; no account required. Even usage visibility (the agent context gauge in the status bar) is computed and displayed entirely on your machine.

Status: active development. Signed, notarized builds are published for macOS (Apple Silicon) and Linux (x86_64) — you don’t have to build from source. See Getting Started.

These docs are task-oriented “how-to” guides. For a quick in-app tour, open the command palette and run workspace: Open Paddle Board Tour.

Getting Started

PaddleBoard is in active development, but you don’t have to build it — signed releases are published for macOS and Linux.

Grab the latest build from GitHub Releases:

PlatformAsset
macOS (Apple Silicon)PaddleBoard-aarch64.dmg — code-signed and notarized
Linux (x86_64)paddleboard-linux-x86_64.tar.gz
WindowsBuild from source for now — see below

The macOS build is signed and notarized with an Apple Developer ID, so it opens without Gatekeeper warnings.

Build from source

Needed on Windows, and useful if you want to hack on PaddleBoard itself.

Prerequisites

  • Rust (via rustup).
  • macOS: Xcode + Xcode command-line tools, and cmake.
  • Linux: run script/linux to install system dependencies.
  • Windows: Visual Studio with the C++ toolchain, the Windows SDK, and cmake.

Build and run

git clone https://github.com/paddleboarddev/paddleboard.git
cd paddleboard
cargo run -p paddleboard

The first build takes a while (it compiles the whole workspace). Subsequent runs are fast.

First launch

The first time you open PaddleBoard you land on an onboarding page. Three things there matter:

  • Theme. PaddleBoard’s own PaddleBoard Dark / Light is the default and is listed first — a deep navy palette matching paddleboard.dev. Every bundled Zed theme (One, Ayu, Gruvbox) is still available if you prefer one.
  • AI Providers. Connect a model without leaving onboarding. Local Models is the zero-key path — pick a model and PaddleBoard downloads and runs it on your machine. Or expand any provider (OpenAI, Anthropic, Google, …), paste an API key, and Save; keys go to your OS keychain. See Configuring LLM Providers for the full set of options.
  • Finish Setup takes you to the Welcome page, which offers Take the Tour — a short, rendered six-stop walkthrough. Reopen it any time with Cmd-Shift-Pworkspace: Open Paddle Board Tour.

First steps

  1. Make sure a model is connected. If you skipped that during onboarding, use the LLM provider panel or the settings LLM page — see Configuring LLM Providers.
  2. Open a project. Common languages work immediately; others are one click away in Language Support.
  3. (Optional) Save your git credentials so pushes don’t prompt — see Git Login.

Personas: Tell Your Agent Who to Be

Skills define what your agent can do. A persona defines who it should be — its voice, values, and what it pushes back on. Describe the teammate you want (a Senior Developer, an SRE, a QA Engineer) and PaddleBoard holds the agent to that identity for the whole thread, with any LLM provider.

Personas apply to the native PaddleBoard Agent. External agents (Claude Code, Codex, …) own their system prompts, so persona selection doesn’t apply there — on those threads a muted persona icon links back to the AI Dock’s Personas tab.

Quick start

Drop a PERSONA.md at your project root:

You are a Site Reliability Engineer. You think in blast radius and rollback
plans. For any deploy or migration, ask for the rollback plan before
discussing the rollout. Flag missing timeouts, retries without backoff, and
single points of failure whenever they appear.

That’s it. Every new PaddleBoard Agent thread in that project adopts the persona automatically — plain prose works, no frontmatter required.

The persona library

For more than one persona, keep a library of <name>.persona.md files:

  • {project}/.claude/personas/ — project-scoped
  • ~/.claude/personas/ — available in every project

Library files use flat YAML frontmatter plus a markdown body:

---
name: qa-engineer
description: A meticulous QA engineer who hunts edge cases.
type: role
voice: terse, skeptical, asks for repro steps before agreeing
---

# Identity
...

# Behavioral rules
- Before proposing a fix, ask for exact reproduction steps.
- When asked to "ship it," name the tests that would have to pass first.

name and description are required for library personas — the description is what the agent (and the picker) uses to choose between them. A project-library persona shadows a user-library persona with the same name.

Writing tip: short, imperative behavioral rules (“ask for repro steps before proposing a fix”) hold up far better over a long conversation than paragraphs of backstory.

Switching personas

Three ways, in increasing order of laziness:

  1. The picker. A persona pill sits in the agent panel’s message toolbar, next to the profile selector. Click it to switch or clear the persona for the current thread. The persona is saved with the thread and survives restarts.
  2. Just ask. The agent sees your persona catalog in its system prompt and carries an adopt_persona tool — say “be my QA tester” mid-conversation and it switches itself, applying the new identity from its very next response. “Drop the persona” returns it to the default voice. The agent only changes personas when you ask.
  3. Starter roles. The AI Dock’s Personas tab ships three ready-made roles — Senior Developer, Site Reliability Engineer, QA Engineer — with one-click Add to project / Add to user install, and lists every persona discovered in your project.

Composing personas with extends:

A persona can inherit another’s rules:

---
name: strict-qa
description: QA engineer on the house base.
extends: house-base
---

The parent’s body is included in the overlay ahead of the child’s (chains are followed; cycles are cut; a missing parent is skipped with a warning), so the child’s own rules always read last and win. Use it to keep a shared “house style” base that every role builds on.

Personas for sub-agents

Delegated work can wear its own identity: the agent can pass persona to its spawn_agent tool — or you can ask it to (“have a QA-persona sub-agent review this”). The sub-agent holds that identity for its whole session while your main thread keeps its own voice. A review pass that genuinely thinks like a reviewer beats an implementer grading their own work.

How it works

The persona is injected into the agent’s system prompt as an identity overlay, snapshotted when selected so a thread’s identity stays stable even if the file changes on disk. Because it rides the system prompt, it works identically with every configured LLM provider and stays byte-stable per thread, which keeps provider prompt caches warm. A persona shapes how the agent responds — tone, priorities, what it pushes back on — never its honesty or capabilities, and it composes with (rather than replaces) your project rules.

Settings

{
  "paddleboard_personas": {
    // Default true. The feature is inert until a persona file exists.
    "enabled": true
  }
}

Set Sail: Deploy to Serverless

Set Sail is PaddleBoard’s serverless-first “deploy to $platform” button. Quick-deploy the current project to Cloud Run, AWS Lambda, or Vercel — no pipeline YAML, no IAM safari. The agent does the work, following the open-source s8sskills playbook.

Quick start

  1. Click the ⛵ sailboat in the status bar (or run set sail: Deploy from the command palette).
  2. Pick your platform. The modal pre-fills a service name from your project folder; adjust it, set a region where it applies (Vercel manages placement itself), and choose whether the URL should be public. Not set up on the vendor yet? The Get started link at the bottom of the modal takes you to their signup.
  3. Click Set Sail. PaddleBoard:
    • installs the platform’s s8sskills pack into your project’s .agents/skills/gcloud-project-setup + cloud-run-deploy (GCP), aws-project-setup + lambda-deploy (AWS), or vercel-project-setup + vercel-deploy (Vercel) — skipped if already present, so pin them in git for a fixed version;
    • opens a PaddleBoard Agent thread that reads those skills and follows them.
  4. The agent checks your CLI setup first. Anything interactive — gcloud auth login, aws configure, vercel login — is handed to you to run in a terminal; the agent never runs auth flows itself.
  5. On success it reports your live URL and everything it created, so you can find (and later clean up) each resource.

Prerequisites

PlatformCLIYou need
Cloud RungcloudAn authenticated account and an active project with billing
AWS LambdaawsA working identity (aws sts get-caller-identity)
VercelvercelAn authenticated session (vercel whoami)

How it works

The platform knowledge is deliberately not hardcoded in PaddleBoard. Set Sail installs versioned skill packs from the community s8sskills catalog and lets the agent follow them — so support for more platforms (Azure, Cloudflare, Netlify, …) arrives by publishing skill packs, not by changing the editor. The deploy runs in a normal agent thread: every command goes through PaddleBoard’s usual permission flow, and you can watch, step through, or stop it like any other agent work.

Costs and cleanup

A real deploy creates billable resources in your cloud account (e.g. a Cloud Run service and Artifact Registry repo, or a Lambda function; Vercel hobby deploys are free-tier). The agent’s success report lists what was created — remove a test deploy with the platform’s delete command, e.g.:

gcloud run services delete <service-name> --region <region>
aws lambda delete-function --function-name <service-name>
vercel remove <service-name>

Rig the pipeline

The second mode. Instead of a one-off deploy, Set Sail sets up the durable flow — repo, GitHub Actions workflow, workload identity — so every git push deploys, the way production teams work. Pick it in the Set Sail modal alongside Quick deploy.

Pipeline support arrives per platform, as each one’s s8sskills pack is authored. It’s ready for Cloud Run, AWS Lambda, and Vercel; on Azure, Cloudflare, and Netlify the modal shows a “coming soon” note and Quick deploy still works. A custom platform bypasses the check entirely, since you supply the steps.

What’s next

  • More platforms as s8sskills packs land — both for Quick deploy and for pipelines.

Configuring LLM Providers

PaddleBoard is bring-your-own-key: you connect your own model accounts. There is no hosted PaddleBoard plan, and nothing is gated behind a PaddleBoard sign-in.

Add a provider

During onboarding (easiest). First launch includes an AI Providers section: expand a provider, paste a key, and Save — or take the zero-key path with Local Models (below).

Any time after that:

  1. Open the agent panel.
  2. Open agent settings → Configure Providers (or the command palette → provider config).
  3. Pick a provider, paste your API key, and save. Keys are stored in your OS keychain (never in settings or plaintext).

Most providers also read a standard environment variable (e.g. ANTHROPIC_API_KEY, OPENAI_API_KEY) as a fallback.

Switching providers

The LLM provider panel is a fast switcher — dock it wherever is convenient. It lists your providers with an authenticated check, marks the current default, and offers Use as Default to promote the selected one. It is deliberately just a switcher: deep configuration lives on the settings LLM page, and browsing or installing lives in the AI Dock.

Local Models — no API key needed

PaddleBoard can run a model on your machine with nothing to install: it ships a signed llama.cpp server and manages the process for you. Open Local Models in the AI provider settings (or during onboarding), turn on Run locally, managed by PaddleBoard, and pick a model — Gemma 3 4B is a good default. It downloads once, binds to 127.0.0.1 only, and is Metal-accelerated on Apple silicon. Afterwards it appears in the model picker like any other provider. Power users can still point it at their own llama.cpp server.

Supported providers

Hosted APIsAnthropic, OpenAI (and ChatGPT subscription auth), Google AI (Gemini), Google Vertex AI, Amazon Bedrock, DeepSeek, Mistral, xAI, OpenRouter, Vercel AI Gateway
Subscription-backedGitHub Copilot Chat, OpenCode
LocalPaddleBoard’s managed Local Models, Ollama, LM Studio
Anything elsethe generic OpenAI-compatible provider — point it at any endpoint speaking the OpenAI API, including a LiteLLM proxy or a self-hosted gateway

Zed’s hosted models

PaddleBoard is a fork of Zed, and Zed’s hosted models are available here as one provider among the others. Signing in is entirely optional — it is never a default, nothing is gated behind it, and BYO keys and local models are first-class alternatives. It’s offered because some users want it and because using it sends business to the upstream project this fork is built on.

If you do sign in and exhaust Zed’s free prompts, the upgrade prompt you see is Zed’s, and the subscription is Zed’s. PaddleBoard sells nothing.

Google Vertex AI (Gemini Enterprise)

Vertex is a PaddleBoard addition for teams whose Gemini access runs through Google Cloud. It supports three auth modes, in precedence order:

  1. Service-account key — set credentials_path to a service-account JSON file.
  2. Express API key — paste an AI Studio / Express key.
  3. gcloud (recommended, no stored secret) — run gcloud auth login once; PaddleBoard borrows short-lived Application Default Credentials. Just set project_id (and optionally location, default global) and it works.

Configure it from the provider settings (project id, location, optional credentials path). Newer models (e.g. Gemini 3) live on the global location, which is the default.

Privacy

Telemetry is hard-disabled in PaddleBoard — your prompts and usage never leave your machine except for the calls you make directly to your chosen provider.

The AI Dock

The AI Dock is one place to browse, install, and create the AI building blocks PaddleBoard supports: agents, skills, and MCP servers.

Open it from the command palette → ai dock: Open.

Tabs

  • Agents — register a custom agent server by registry ID (Add Agent), or install a catalog agent: Claude, Codex, Copilot, Cursor, Antigravity, Zed Agent, and the framework agents (Google ADK, LangGraph, CrewAI, AutoGen, A2A). CLI-based agents show a Set Up button that opens a terminal with the install command rather than running it inside the app.
  • Skills — install bundled slash-command skills with Add to project / Add to user, or Create Skill to write a new .claude/commands/ markdown command. The bundled set is /build, /update-tour, /clippy, /test, /check-drift, /build-mcp, /verify, /review, and /security-review.
  • Personas — browse and install the bundled personas (Senior Developer, Site Reliability Engineer, QA Engineer) into a project or your user directory.
  • MCP — add and manage Model Context Protocol servers, with live status and streaming logs — or Build an MCP to have an agent generate one for a service that has none. See Sandboxed Execution & MCP.
  • Usage — the local, per-provider, per-model token history described in Settings Reference. Nothing here leaves your machine.

The catalog is data-driven from assets/ai_dock/catalog.json in the repo — additions are pull requests, not network fetches.

Agent Frameworks

PaddleBoard has first-class support for four Python agent frameworks: Google ADK, LangGraph, CrewAI, and AutoGen. When you open a project that declares one of them (in pyproject.toml / requirements.txt), PaddleBoard detects it and offers to run it.

Running a framework

Each framework registers command-palette actions, e.g. adk: Run Agent, crewai: Run Agent.

  • Dev-server frameworks (ADK, LangGraph, AutoGen Studio) launch a local server and forward its port into the embedded browser. For example autogen: Run Agent runs autogenstudio ui --port 8081 and streams startup logs to a tab.
  • One-shot frameworks (CrewAI) run to completion and stream output to a tab — no port forwarding (crewai: Run Agentcrewai run).

Scaffolding

Frameworks with a project generator expose a Scaffold action (e.g. adk: Scaffold Agent, crewai: Scaffold Agent) that opens a small modal and runs the create command in a terminal.

Installing the CLIs

The frameworks themselves are external tools — install them in your environment (e.g. pip install crewai, pip install autogenstudio). PaddleBoard drives them; it doesn’t bundle them.

Scion: Isolated Parallel Agents

Scion runs “deep agents” as isolated, concurrent processes — each in its own container and git worktree. PaddleBoard integrates with a local Scion daemon so you can launch and watch those agents from the editor, and even delegate subtasks to them from your own agent.

Enable it (opt-in)

Scion is off by default. Turn it on in your settings:

{
  "paddleboard_scion": { "enabled": true }
}

Then install the Scion CLI and initialize it:

go install github.com/GoogleCloudPlatform/scion/cmd/scion@latest
scion init --machine   # one-time, sets up the container runtime
scion init             # in your project

Scion needs a container runtime (Docker / Podman / Apple Container).

Use it

  • scion: Start Agent (command palette) opens a modal — set a task, name, and template.
  • The Orchestration Panel shows a Scion Agents section with each agent’s phase (provisioning → running → stopped) and activity (working, thinking, waiting…). Right-click a row for View Logs (live-streaming), Sync Changes (pull its worktree changes into your project), or Stop Agent.
  • Delegation: when enabled, your agent gains a spawn_scion_agent tool — it can hand a subtask to a container + worktree-isolated Scion agent (instead of an in-process sub-agent that shares your workspace), wait for it, and return the result.

Telemetry (optional)

Scion can export agent-lifecycle traces over OpenTelemetry. See the Settings Reference for paddleboard_otel.

Language Support

PaddleBoard keeps the default install lean with two tiers.

Ready to use

Common languages — Rust, TypeScript/JavaScript, Python, Go, JSON, YAML, HTML/CSS, and more — are enabled by default. Open a matching file and the language server attaches automatically, downloading on first use.

Python

Basedpyright is the default language server for Python. PyRight and pylsp are disabled by default — Basedpyright is a superset of PyRight, so running both means duplicate diagnostics on every line.

To go back to one of the others, set the language server list yourself in settings.json:

{
  "languages": {
    "Python": {
      "language_servers": ["pyright", "!basedpyright", "ruff", "..."]
    }
  }
}

The ! prefix disables a server, and "..." stands in for the remaining defaults. Swap pyright for pylsp, ty, or pyrefly the same way.

“Import could not be resolved”

If Basedpyright reports Import "<package>" could not be resolved, it is usually right: the package isn’t installed in the interpreter it is analysing against. Basedpyright checks imports more strictly than pylsp did, so switching to it can surface an environment problem that was always there.

Create and populate a virtualenv in the project root, then reopen the folder:

python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt

PaddleBoard discovers .venv automatically. To point at a different interpreter, run toolchain: Select Toolchain from the command palette.

Install support (opt-in)

Languages that need an external toolchain are opt-in. Run Manage Languages from the command palette to enable them; each row shows its prerequisite up front so it never fails silently when the runtime is missing.

Six ship a built-in server:

LanguageServerPrerequisite
JavajdtlsJDK 17+
Kotlinkotlin-language-serverJDK 17+
PHPintelephenseNode
C#roslyn.NET
C++clangddownloads clangd (C stays on by default; clangd is shared)
SwiftSourceKit-LSPSwift toolchain (Xcode / swift.org) — resolved from PATH, not downloaded

Ruby and Dart get their servers from extensions, so their row opens the Extensions page.

Why opt-in? It keeps the default install small and means you choose to pull in a heavier toolchain knowingly, rather than hitting a confusing “server reset the connection” crash when the runtime isn’t present.

Git Login

Save your git host credentials once so HTTPS git operations stop prompting on every clone/fetch/push.

The logins list

Run git login: Manage from the command palette. The modal lists each provider — GitHub, GitLab, BitBucket — with its live status: Signed in as <user> or Not signed in. Click a row to select it, or click Remove on a row to delete its saved login. Custom hosts (e.g. a self-hosted GitLab) are managed through the form fields below the list.

Sign in with GitHub (browser)

On builds configured with an OAuth client id, selecting GitHub shows a Sign in with GitHub (browser) button:

  1. PaddleBoard displays a short code (like WDJB-MJHT) and opens github.com/login/device.
  2. Enter the code and approve access.
  3. The token is stored in your OS keychain automatically — you’re signed in.

This is the same device flow the gh CLI uses; no client secret is involved. If the button isn’t there, the build has no client id configured — use a token instead, which always works.

Save a token manually

  1. Pick a provider from the list (or enter a custom host).
  2. Enter your username and paste a Personal Access Token (the modal links straight to the provider’s token page and lists the scopes to grant).
  3. Save. The token is written to your OS keychain — never to settings or plaintext.

After that, git HTTPS clone / fetch / push authenticate silently. The password prompt only appears when there’s no saved login.

Remember from the prompt

No saved login yet? When git’s password prompt appears, tick “Remember on this device” before submitting — the credential is saved to your keychain and the next operation authenticates silently.

Beyond git: API requests

A saved GitHub login also authenticates PaddleBoard’s GitHub API requests — commit-author avatars in git blame resolve on private repos, and you skip the unauthenticated rate limit. GitHub Enterprise hosts use their own saved login. (GITHUB_TOKEN still wins when set.)

Environment-variable fallback

If you’d rather not store a token, set one of these and PaddleBoard answers git auth from it:

export GITHUB_TOKEN=...      # or GITLAB_TOKEN / BITBUCKET_TOKEN

Notes

  • PaddleBoard sends the conventional token username per provider unless you set your own: x-access-token (GitHub), oauth2 (GitLab), x-token-auth (BitBucket).
  • OAuth sign-in is GitHub-only — GitLab and BitBucket don’t offer a comparable device flow, so they use tokens.
  • HTTPS only. SSH key passphrases and host-key confirmations are untouched and still prompt as usual.

Manifest: Your Git State at a Glance

The Manifest panel is a dockable tree that lays out the project’s entire git world in one place — the ship’s manifest. Open it with the tree icon in the dock, or run manifest: Toggle Focus from the command palette.

Everything in the panel reads from state PaddleBoard already tracks in the background, so it renders instantly and never runs git commands on the UI thread.

The five sections

Each section is a collapsible header with a count; click the header (or its disclosure arrow) to fold it away.

Repositories

Every repository in the workspace — multi-repo projects and worktree-backed workspaces included — each flying a sailboat. The active repository is highlighted with a check; click any other repo to make it active. The Branches, Commits, and Stashes sections below always describe the active repository, so this row doubles as the panel’s scope switch.

Branches

The active repo’s local and remote branches, sorted current-branch-first, then local before remote, then by recency. Branches with an upstream show ahead/behind counts (↑2 ↓1) so you can see what needs a push or pull without running anything.

Commits

The current branch’s recent history — up to 250 commits. Subjects stream in as commit metadata loads (rows briefly show Loading… on first open). Click any commit to open its full diff in a commit view tab.

For history beyond the overview — the full graph, searching, other branches — use the Git Graph (the Git panel’s History tab); Manifest deliberately stays a summary.

Stashes

Every stash@{n} with its message. Click a stash to open it in the stash view, which shows its diff and offers Apply, Pop, and Drop.

Contributors

Everyone who has committed to the repository, with their commit count, busiest first. Computed locally with git shortlog when the panel loads and refreshed when the branch head changes.

Note: in a collaboration session on a remote project, the Contributors section is empty — the query currently runs only against local repositories.

Tips

  • The panel docks left by default; drag it (or use the dock context menu) to move it right.
  • Repo switching from the Repositories section is the same operation as the Git panel’s repository selector — the two stay in sync.

Sandboxed Execution & MCP

PaddleBoard can run agent-invoked code and MCP servers inside an isolated container instead of directly on your host.

Secure agent sandbox

Tool calls that execute code run in an isolated environment rather than on your host. Your project is bind-mounted; the rest of the host filesystem is not exposed. Permissions still flow through the normal approve / deny / always-allow UI.

There are two tiers.

Native — zero-install, and the default on macOS. Apple’s container framework on macOS 26+, otherwise a bundled libkrun microVM. Nothing to install; it ships with PaddleBoard. On Linux it’s libkrun over KVM.

Podman + gVisor. An ephemeral ubuntu:latest container via Podman with the runsc kernel runtime. This is the default on Linux and Windows, and you install it yourself.

⚠️ The native tier currently covers one-shot commands only. Long-lived services, sandboxed MCP transports, and REPL kernels still require Podman + gVisor — with the native tier alone, those paths behave exactly as they would with no sandbox stack installed, and follow the policy below.

The status-bar shield shows which tier is active. Your choice is honored exactly: native is used even when Podman is installed, and podman is never silently rerouted to native when it’s missing. See preferred_backend.

If the required prerequisites aren’t available, paddleboard_sandbox.on_missing_runtime decides what happens:

ValueBehavior
block (default)refuse to run and open the install modal; the agent gets a clear error rather than a hang
fall_back_to_hostrun the command on the host, unsandboxed
warn_onceproceed sandboxed, logging a one-shot warning with install guidance

Note that warn_once does not drop you to the host — it’s the quiet variant of block, not of fall_back_to_host. fall_back_to_host is the only setting that runs agent code unsandboxed.

Sandboxed MCP servers

A sandboxed_stdio context-server transport runs MCP servers inside Podman + gVisor too, proxying stdin/stdout transparently so the JSON-RPC framing is unchanged. It’s opt-in per server; the plain stdio transport still works for servers that don’t need isolation.

Manage servers from the MCP tab of the AI Dock, or the dedicated MCP Servers settings page (command palette → zed: Mcp Servers), which lists configured servers and surfaces status and logs without hand-editing JSON.

Build an MCP for any service

When a service has no MCP server, the Build an MCP button at the top of the AI Dock’s MCP tab generates one. You provide:

  • a service (e.g. Substack),
  • an optional API-docs URL,
  • an optional auth env-var name (e.g. SUBSTACK_API_KEY), and
  • a sentence describing what it should do.

PaddleBoard then seeds a visible agent thread that researches the service’s API, writes a Python (FastMCP) server, tests it in the sandbox, and installs it into the AI Dock. Because the thread is visible, you can watch the build and course-correct.

The install runs host-side (via the install_mcp_server tool, which you approve): it writes the server under PaddleBoard’s data directory — on macOS ~/Library/Application Support/PaddleBoard/mcp_servers/<id>/ — and registers it as a plain stdio context server that runs with uv run. The generated server reads its API key from the environment PaddleBoard was launched with, so no secret is ever written to settings: just export the variable (e.g. export SUBSTACK_API_KEY=…) in the shell you launch PaddleBoard from. Once installed, the server appears in the MCP tab and starts automatically.

Requirements. uv must be on your PATH — it provisions the server’s Python dependencies on first launch. Open a project before building, since the agent needs an active workspace to work in.

Search & Status Bar Extras

Quality-of-life additions on top of Zed’s editor.

Search as you type

Project search runs automatically as you type — results update a beat (~200ms) after you pause, no Enter required. This matches VSCode’s behavior and one of upstream Zed’s most-requested changes (zed#9318).

Prefer the classic press-Enter behavior? Turn it off:

{
  "search": { "search_on_type": false }
}

Agent context gauge

While an agent thread is running, a percentage appears in the status bar showing how much of the model’s context window the active thread has used:

  • The color follows the agent panel’s thresholds — muted, yellow as you approach the limit, red past it.
  • Hover for the token breakdown: used / total, input vs. output.
  • Click to jump to the agent panel.
  • It hides itself when no thread has token usage.

The gauge is purely local: it displays counts the agent thread already tracks on your machine. Nothing is collected or reported — PaddleBoard’s telemetry stays hard-disabled.

The rest of the status bar

PaddleBoard adds several other status bar items, each documented with the feature it belongs to:

ItemWhat it does
Shieldwhich sandbox tier is active; click to switch backends
MCPMCP server status, with streaming logs
SailboatSet Sail deploy status
Placidtoggles Placid mode
Updateappears only while an update is downloading or installing, then as Restart to update

Any of them — and the context gauge above — can be hidden with paddleboard_ui. Hiding an item doesn’t disable the feature; everything stays reachable from the command palette.

Linux

PaddleBoard ships a Linux build as a .tar.gz. This page covers what’s in it, what the system needs, and the two places Linux behaves differently from macOS.

Install

Download paddleboard-linux-x86_64.tar.gz from Releases and unpack it. The archive contains no installer, and there is no curl | sh bootstrap — PaddleBoard runs no hosted release server, so the tarball on the Releases page is the whole distribution.

To try it without installing anything, run it in place:

tar -xzf paddleboard-linux-x86_64.tar.gz
./paddleboard.app/bin/paddleboard

To install it for your user, unpack into ~/.local/ and link it onto your PATH:

tar -xzf paddleboard-linux-x86_64.tar.gz -C ~/.local/
mkdir -p ~/.local/bin ~/.local/share/applications
ln -sf ~/.local/paddleboard.app/bin/paddleboard ~/.local/bin/paddleboard

That’s enough to run paddleboard from a terminal, provided ~/.local/bin is on your PATH. To also get PaddleBoard into your application launcher, install the desktop entry and point it at absolute paths:

desktop=~/.local/share/applications/dev.paddleboard.PaddleBoard.desktop
cp ~/.local/paddleboard.app/share/applications/dev.paddleboard.PaddleBoard.desktop "$desktop"
sed -i "s|Exec=paddleboard|Exec=$HOME/.local/paddleboard.app/bin/paddleboard|g" "$desktop"
sed -i "s|Icon=paddleboard|Icon=$HOME/.local/paddleboard.app/share/icons/hicolor/512x512/apps/paddleboard.png|g" "$desktop"

The archive is an ordinary prefix tree, so it can live anywhere you prefer:

PathContents
bin/paddleboardthe launcher and command-line interface — this is what you run
libexec/paddleboard-editorthe editor itself, started by the launcher
libexec/paddleboard-krun-helperhelper for the microVM sandbox tier
libexec/llama/the bundled llama.cpp runtime for managed local models
lib/bundled shared libraries the binary needs
share/applications/the .desktop entry
share/icons/hicolor/{512x512,1024x1024}/apps/application icons
licenses.mdthird-party licenses

script/install.sh in the source repo is not an installer for this archive — it installs a tarball you built yourself, via script/install-linux, and exits with an error if you run it without one.

x86_64 only

The published build is x86_64. There is no aarch64 (ARM) Linux release.

This matters beyond just “no download”: the updater maps your platform to a release asset, and aarch64 Linux has no mapping, so an ARM machine running a self-built PaddleBoard is never offered an update. It won’t error — it simply never finds anything. On ARM, build from source and pull updates by rebuilding.

glibc requirement

The published binary requires glibc 2.35 or newer — the same floor as the ubuntu-22.04 image the release is built on. The editor asks libm.so.6 for GLIBC_2.35. On anything older it fails at load time with a message about a GLIBC_2.3x version not being found.

DistributionglibcRuns
Ubuntu 22.04 and newer2.35+yes — verified
Debian 12 (bookworm) and newer2.36+yes
RHEL / Rocky / AlmaLinux 92.34no — verified to fail
Ubuntu 20.042.31no — verified to fail
Debian 11 (bullseye)2.31no
RHEL 82.28no

RHEL 9 and its rebuilds miss by a single glibc release. That’s close enough to look like it ought to work, and it doesn’t.

On an older distribution, build from source against your own glibc.

The floor comes from the CI image rather than from a deliberate policy, so it moves only when someone changes that image. The release job is pinned to ubuntu-22.04 precisely so it can’t drift upward unnoticed — a newer image would silently raise the minimum distro that can run PaddleBoard.

How this was checked. The rows marked verified were tested by running the shipped binary inside that distribution’s container image, not by reading the binary’s headers. Header-reading got this wrong once: a sweep that looked only at the libc.so.6 version-reference block concluded the floor was 2.34, because the GLIBC_2.35 requirement lives in the libm.so.6 block. If you re-derive this number, take the maximum across every required from block — or just run it.

System libraries

Almost everything the binary links against ships inside the archive — libstdc++, libssl and libcrypto, libxcb, libxkbcommon, and the X11 shims are all in lib/, and the binary carries an RPATH of $ORIGIN/../lib, so it finds them without LD_LIBRARY_PATH.

One library is not bundled and has to come from your system:

# Debian / Ubuntu
sudo apt install libasound2        # libasound2t64 on Ubuntu 24.04 and newer
# Fedora / RHEL
sudo dnf install alsa-lib
# Arch
sudo pacman -S alsa-lib

libasound.so.2 is a hard link-time dependency, so when it’s missing PaddleBoard fails before it starts, with a dynamic-loader error rather than a PaddleBoard one:

error while loading shared libraries: libasound.so.2: cannot open shared object file

Desktop installs nearly always have it already. Minimal, container, and server images often don’t. Verified by running the shipped binary in a stock ubuntu:22.04 container: it fails with exactly the error above, and once libasound2 is installed it loads with no unresolved libraries at all — this is the only external dependency.

If you’re on both an old distribution and a minimal image, you’ll see the missing-library error first: the dynamic loader reports libraries it cannot find before it checks symbol versions in the ones it can. Installing ALSA can therefore turn a libasound.so.2 error into a GLIBC_2.35 one. That’s progress, not a new problem — see glibc requirement.

Vulkan is a runtime requirement too, but it’s loaded dynamically and degrades more gracefully — see PaddleBoard fails to open windows.

Build from source

Install the build dependencies:

script/linux

PaddleBoard needs a few packages beyond Zed’s set, because the embedded browser panel uses wry, which wants the GTK3 + WebKit2GTK stack:

sudo apt-get install -y libwebkit2gtk-4.1-dev libgtk-3-dev librsvg2-dev \
                        clang libssl-dev pkg-config

Then:

cargo run --release

To produce a distributable archive exactly as CI does, run script/bundle-linux.

What differs from macOS

Most of PaddleBoard is identical across platforms. Two things aren’t.

Local Models

Managed local models work on Linux — both x86_64 and aarch64 — so a self-built ARM install still gets local inference even though it gets no automatic updates.

Acceleration differs: macOS uses Metal, Linux uses the CPU build unless your setup provides otherwise. Expect slower tokens-per-second than an equivalent Apple silicon machine.

The sandbox

The sandbox tier available to you depends on what’s installed. On Linux, PaddleBoard looks for libkrun in the usual distribution library directories for the microVM tier, and falls back to Podman + gVisor, then to the native tier.

Click the shield in the status bar to see which tier is active on this machine. Your choice is honored — PaddleBoard never silently downgrades you to a weaker tier.

Troubleshooting

These are the failures PaddleBoard links here from directly, so the headings below are the link targets — keep their wording if you edit them.

Could not start inotify

PaddleBoard watches project files with inotify, and the kernel caps how many watches and instances a user may hold. On a large project, or with several editors open, you can hit that cap and see inotify_init returned ... at startup.

Check the current limits and raise them:

cat /proc/sys/fs/inotify/max_user_instances   # often 128
cat /proc/sys/fs/inotify/max_user_watches     # often 65536 or 524288

sudo sysctl fs.inotify.max_user_instances=1024
sudo sysctl fs.inotify.max_user_watches=1048576

To make it stick across reboots, put the same two settings in /etc/sysctl.d/60-paddleboard.conf and run sudo sysctl --system.

I can’t open any files

If the file picker never appears, PaddleBoard has no xdg-desktop-portal implementation to talk to. The portal is what a sandboxed or Wayland-native app uses to show a native file dialog; without a backend installed and running, there is nothing to show.

Install the backend that matches your desktop:

# GNOME / most desktops
sudo apt install xdg-desktop-portal xdg-desktop-portal-gtk
# KDE
sudo apt install xdg-desktop-portal xdg-desktop-portal-kde
# wlroots compositors (Sway, Hyprland)
sudo apt install xdg-desktop-portal xdg-desktop-portal-wlr

Then log out and back in, or restart the service:

systemctl --user restart xdg-desktop-portal

PaddleBoard fails to open windows

PaddleBoard renders through Vulkan on Linux. If no usable Vulkan driver is present, the system falls back to software emulation (llvmpipe) — which technically works and is far too slow to edit in, so PaddleBoard warns rather than letting you discover it as mystery lag.

Install the Vulkan driver for your GPU (mesa-vulkan-drivers covers AMD and Intel; NVIDIA ships its own), then confirm the loader can see it:

vulkaninfo | head        # from vulkan-tools

If you know you’re on software rendering and want to proceed anyway — a VM, a remote session, a screenshot run — set:

PADDLEBOARD_ALLOW_EMULATED_GPU=1 paddleboard

Remote development

The remote server is built as a statically linked musl binary, so it runs on hosts whose glibc is older than the one above.

Updating a remote server over SSH uses rsync. If it’s missing, PaddleBoard tells you and names the install command for your distribution — it reads /etc/os-release to get the package manager right rather than guessing.

Windows

There is no Windows release. PaddleBoard publishes signed builds for macOS and Linux only. On Windows you build from source, and you should know what you’re taking on before you do.

The honest status

Windows code is inherited from Zed and is still present — PaddleBoard hasn’t removed it, and script/bundle-windows.ps1 exists. But:

Status
Published release assetNone
Built in CINo — the compile gate covers Linux and macOS only
Tested in CINo
Automatic updatesNot available
Managed Local ModelsNot available

Because nothing in CI compiles for Windows, Windows-only breakage can land on main and stay there without any check going red. If you build on Windows and something is broken, that is genuinely useful information — please open an issue.

Build from source

Prerequisites:

  • Rust, via rustup
  • Visual Studio with the C++ toolchain
  • the Windows SDK
  • cmake

Then:

cargo run --release

script/bundle-windows.ps1 produces a distributable build. It is inherited from Zed and is not exercised by PaddleBoard’s CI.

What won’t work

Two PaddleBoard features are unavailable on Windows, and both fail as absence rather than as an error — the surfaces simply won’t offer you anything.

Automatic updates

The updater maps your platform to a release asset. Windows has no mapping, so no update is ever offered. “Check for Updates” cannot find a build for you. Update by pulling and rebuilding.

Managed Local Models

The bundled llama.cpp runtime ships for macOS (Apple silicon) and Linux (x86_64 and aarch64) only. On Windows the Local Models section has nothing to offer, and PaddleBoard reports the platform as unsupported rather than downloading a runtime that can’t run.

Everything else in the AI stack is platform-independent — bring your own API keys, or point PaddleBoard at any OpenAI-compatible endpoint, including one you run yourself on the same machine.

Troubleshooting

PaddleBoard links here from two Windows failures.

Could not start ReadDirectoryChangesW

PaddleBoard watches project files with ReadDirectoryChangesW, which network filesystems and WSL paths do not reliably support. Opening a project from a UNC share, a mapped network drive, or a \\wsl$\... path can fail at startup with ReadDirectoryChangesW initialization failed.

Open the project from a local NTFS path instead. If the files genuinely live in WSL, run the Linux build inside WSL rather than reaching into WSL from Windows — see below.

Software-emulated graphics

PaddleBoard renders through DirectX on Windows. Without a usable GPU driver the system falls back to software emulation, which is too slow to edit in, so PaddleBoard warns instead of letting it look like an unexplained stutter.

Install your GPU vendor’s driver. To proceed on software rendering anyway — a VM, or a remote session — set:

$env:PADDLEBOARD_ALLOW_EMULATED_GPU=1

WSL

If you want a supported PaddleBoard on Windows hardware today, WSL2 is the shortest path: install the Linux build inside WSL and run it there, where releases, automatic updates, and local models all work normally. See Linux.

Roadmap

A Windows release is wanted but not scheduled. The blockers are the ordinary ones for a small project — CI capacity to build and test it, and somewhere to get it signed so it doesn’t trip SmartScreen. If Windows support matters to you, say so on the issue tracker; demand is what moves it up the list.

Settings Reference

PaddleBoard-specific settings, on top of all of Zed’s. Add them to your settings.json (Cmd-,, or Cmd-Shift-Pzed: open settings file).

Every value shown below is the default, so a block you paste unchanged does nothing. Only the settings PaddleBoard adds are listed here — for the inherited ones, Zed’s documentation still applies.

{
  "search": { "search_on_type": true }
}

Project search runs as you type, debounced, instead of waiting for Enter. Set false for the classic behavior. See Search & Status Bar Extras.

Updates

{
  "paddleboard_auto_update": { "include_prereleases": false }
}

Whether in-app updates may install prerelease builds. PaddleBoard’s pipeline publishes every release as a prerelease and promotes it afterwards, so leaving this off follows promoted releases only. Turn it on to ride beta builds as they’re cut.

Chrome visibility

{
  "paddleboard_ui": {
    "browser_button": true,
    "llm_picker_button": true,
    "orchestration_button": true,
    "manifest_button": true,
    "sandbox_status": true,
    "mcp_status": true,
    "usage_status": true,
    "set_sail_status": true,
    "placid_status": true,
    "update_status": true
  }
}

Every piece of chrome PaddleBoard adds can be hidden. The first four are dock panel buttons; the rest are status bar items. Anything you hide stays reachable from the command palette — these settings control visibility, not the feature.

update_status is worth knowing about: it only appears while an update is downloading or installing, and then as a Restart to update button until you restart.

Personas

{
  "paddleboard_personas": { "enabled": true }
}

The persona system. On by default, and inert until a PERSONA.md exists, so it costs nothing until you use it.

Semantic search (local RAG)

{
  "paddleboard_rag": {
    "enabled": false,
    "store_backend": "local",
    "store_url_env": null,
    "store_table_prefix": null,
    "store_ssl": true
  }
}

When enabled, agents get a semantic_search tool that indexes the current project on demand with the built-in local embedding model (EmbeddingGemma) and answers natural-language queries entirely on-device.

store_backend selects where the vectors live: "local" for the built-in on-device sqlite store, or "pgvector" for a bring-your-own Postgres. The pgvector tier sends your vectors and chunk text to your own database — embeddings are still computed on-device.

store_url_env is the name of the environment variable holding the libpq connection string, not the connection string itself. PaddleBoard reads it from the environment at run time so credentials never land in settings. store_table_prefix lets several projects share one database. store_ssl should stay true unless you’re on a trusted local link such as the Cloud SQL Auth Proxy.

Usage tracking

{
  "paddleboard_usage": {
    "enabled": true,
    "granularity": "daily",
    "directory": null,
    "auto_commit": false
  }
}

Records per-provider, per-model token counts to a local flatfile so you can see how your usage is distributed over time. All of it stays on your machine — this is not telemetry and nothing is ever reported anywhere.

granularity is "daily" (one rolled-up total per day, per provider, per model) or "session" (additionally broken down by agent session). directory defaults to PaddleBoard’s data directory and supports a leading ~; point it inside a git repository of your own and set auto_commit to have PaddleBoard git add + git commit after each flush.

Sandbox

{
  "paddleboard_sandbox": {
    "on_missing_runtime": "block",
    "prereq_check_enabled": true
  }
}

on_missing_runtime controls what happens when a sandboxed tool tries to launch but the host prerequisites aren’t satisfied:

ValueBehavior
block (default)refuse to launch and surface the install modal; the agent gets a clear error rather than a hang
fall_back_to_hostrun the command on the host, unsandboxed
warn_onceproceed sandboxed, with a one-shot notification carrying install guidance

prereq_check_enabled turns off host probing entirely; the gate then always allows tools to proceed.

There’s also preferred_backend, normally set from the shield in the status bar rather than by hand:

{
  "paddleboard_sandbox": { "preferred_backend": "native" }
}

"native" is the zero-install tier — Apple container on macOS 26+, otherwise the bundled libkrun microVM, or libkrun over KVM on Linux. "podman" is the Podman + gVisor tier. Your choice is honored exactly: native is used even when Podman is installed, and podman is never silently rerouted to native when it’s missing. Left unset, it defaults to native on macOS and podman on Linux and Windows. See Sandboxed Execution & MCP.

Scion

{
  "paddleboard_scion": { "enabled": false }
}

Enables the Scion integration. Installing the scion CLI alone does not activate it — this toggle does. When on (and scion is on your PATH), PaddleBoard polls the local Scion daemon, shows the Scion section in the orchestration panel, and exposes the spawn_scion_agent tool to agents.

OpenTelemetry (Scion tracing)

{
  "paddleboard_otel": {
    "enabled": false,
    "endpoint": "http://localhost:4317",
    "protocol": "grpc",
    "service_name": "paddleboard"
  }
}

Exports Scion agent-lifecycle traces over OTLP to a collector (Jaeger, Tempo, etc.). protocol is "grpc" (port 4317) or "http" (port 4318).

Two environment variables override this: PADDLEBOARD_OTEL_ENABLED=1 turns it on, and OTEL_EXPORTER_OTLP_ENDPOINT replaces endpoint.

Vertex AI

Configured under the Vertex provider settings — project_id, optional location (default global), and optionally credentials_path (service-account JSON) or an Express key. See Configuring LLM Providers.

Telemetry

There is nothing to configure: telemetry is hard-disabled in PaddleBoard. Events are dropped at the source and never reach the network. Note that usage tracking is a different thing — it’s local-only and never transmitted.