Server CLI & environment¶
Flags and environment variables for the default server invocation — painapple [flags] (or explicitly painapple serve [flags], or python -m painapple_code [flags] from a repo checkout).
painapple help (or a leading -h/--help) prints a curated command overview — serve, setup, docker, list — with the most common flags; painapple serve --help prints the full flag reference below. painapple list shows every instance on the machine: running local server processes plus configured Docker sandboxes.
Saved defaults — painapple setup¶
painapple setup is an interactive wizard (same widgets and step machine as painapple docker setup) that saves host-mode serve defaults — workspace, bind address, port, TLS mode, instance name, accent — to ~/.painapple-code/serve.yaml. A bare painapple then starts with those values; any explicit flag still overrides its saved default. Three quick sections plus a review screen; nothing is written until you confirm.
# ~/.painapple-code/serve.yaml — written by `painapple setup`, editable by hand
workspace: /home/me/code
host: 127.0.0.1
port: 8765
tls: auto
instance_name: HOME
accent: green
Recognized keys: workspace, workspace_root, host, port, tls, instance_name, accent — each maps 1:1 onto the flag of the same name below. Unknown keys or invalid values are skipped with a warning in the server log; the wizard's "Directory I launch from" workspace choice simply omits the workspace key so a bare painapple keeps using the current directory. The file lives under PAINAPPLE_CODE_HOME (default ~/.painapple-code). Precedence: built-in default < serve.yaml < explicit flag — so systemd units and the Docker entrypoint, which pass everything explicitly, are unaffected.
Container mode lives elsewhere
The painapple docker … subcommand group runs the bridge in Docker/Podman instead of directly on the host — see the Docker CLI reference.
Flags¶
Defaults shown are the built-ins — values saved by painapple setup replace them; explicit flags override both.
Server — where it listens and what it works on¶
| Flag | Default | Description |
|---|---|---|
--host |
127.0.0.1 |
Host interface to bind — 127.0.0.1 = this machine only, 0.0.0.0 = every interface (reachable on your LAN) |
--port |
8765 |
Port to bind to |
--workspace |
. |
Workspace directory — the directory Claude operates in. Mapped to /workspace inside Docker. (--cwd is an alias.) |
--workspace-root |
--workspace |
Directory scanned for sibling project folders surfaced on the welcome screen (the "Unvisited" chips) |
--instance-name |
— | Instance label for the PWA icon and UI (e.g. DEV, STABLE) |
--accent |
— | Accent color: a preset name (see below) or a hex value like #f87171 |
Network security¶
| Flag | Default | Description |
|---|---|---|
--tls |
auto |
TLS mode: auto, on, or off (see below) |
--tls-cert |
<config-dir>/cert.pem |
TLS certificate path (auto-generated if missing) |
--tls-key |
<config-dir>/key.pem |
TLS key path (auto-generated if missing) |
Advanced¶
| Flag | Default | Description |
|---|---|---|
--default-provider |
claude-sdk |
Provider for new sessions (existing sessions keep their recorded provider) |
--enable-eruda |
off | Enable the Eruda mobile-devtools quick action (loads from a CDN) |
-v, --version |
— | Print version and exit |
Multi-instance — isolate state when several servers share one user¶
| Flag | Default | Description |
|---|---|---|
--shadow-db |
~/.painapple-code/shadow.duckdb |
DuckDB path for the shadow turn store |
--log-dir |
~/.painapple-code/logs/ |
Log directory |
--state-suffix |
— | Per-tier suffix for UI-state files (tab-state, shortcuts, presets, favorites, global config) so co-located instances don't share them. --state-suffix dev gives tab-state-dev.json; a leading - is added automatically. Project and session history stays shared. |
--auth-config-file |
~/.config/painapple-code/config.yaml |
Auth config file path |
TLS behavior¶
--tls auto(the default) enables TLS only when binding to a non-loopback host. On127.0.0.1,::1, orlocalhostthe server stays plain HTTP.--tls onforces TLS;--tls offdisables it even on non-loopback binds (the server logs a loud warning — your auth token and chat contents travel the LAN unencrypted).- When TLS is enabled, a self-signed certificate is auto-generated at
<config-dir>/cert.pem/key.pem(next to the auth config file). There is no OS trust-store install; browsers show a one-time certificate warning.
Non-loopback binds
Binding to a non-loopback host also makes the server trust X-Forwarded-Proto from any client (forwarded_allow_ips is *). For real exposure, put the bridge behind a reverse proxy that sets that header itself — see Read this first.
Environment variables¶
| Variable | Purpose |
|---|---|
PAINAPPLE_CODE_HOME |
Override the data directory (default ~/.painapple-code). Set to /data in the Docker image. |
PAINAPPLE_CODE_CONFIG |
Override the config directory (default ~/.config/painapple-code) — where config.yaml and the auto-generated TLS cert/key live. |
BRIDGE_ALLOWED_ORIGINS |
Comma-separated CORS allow-list. Defaults to localhost / 127.0.0.1 on ports 8765, 8800, and 8880. Set this when serving from a public hostname. |
PAINAPPLE_REVEAL_CMD |
Exact "reveal password" command shown verbatim on the login page. Launchers (the Docker wrapper) set this because they know the host-side container name and engine; unset, the page falls back to a per-environment guess. |
PAINAPPLE_IN_CONTAINER |
Set to 1 inside the official image. Gates the filesystem probes that distinguish Docker from Podman for the login page's environment detection — never set this on a bare-metal host. |
Accent color presets¶
--accent accepts any of these preset names, or an arbitrary hex color (--accent '#e11d48'):
| Preset | Hex |
|---|---|
blue |
#58a6ff |
green |
#22c55e |
red |
#f87171 |
orange |
#fb923c |
purple |
#c084fc |
cyan |
#06b6d4 |
gray (or grey) |
#9ca3af |
yellow |
#facc15 |
pink |
#f472b6 |
teal |
#14b8a6 |
indigo |
#818cf8 |
lime |
#a3e635 |
Running multiple instances¶
Use --instance-name, --accent, --state-suffix, --shadow-db, and --log-dir together to run several tiers side by side under one user without them stepping on each other:
painapple --port 8880 --instance-name DEV --accent red \
--state-suffix dev \
--shadow-db ~/.painapple-code/shadow-dev.duckdb \
--log-dir ~/.painapple-code/logs-dev
Each instance needs its own shadow DB — DuckDB is single-writer.
painapple list shows everything running on the machine — every local server process (with its port, PID, and workspace) and every configured Docker sandbox.
Known limitations¶
This is an MVP; some corners are honestly rough:
- Windowing system — works, but doesn't support multiple instances of the same widget and could use a rethink.
- Code editor — currently a notepad with syntax highlighting. The plan is a review-driven workflow rather than a VSCode-grade editor; the markdown inline editor is the exception and works well for plan and doc tweaks.
- GUI for OS-level features — the git widget and file explorer exist, but the embedded terminal is often the better tool for
grep/sed/find/du, so these widgets haven't been a priority.