Data storage & logs¶
Everything the bridge writes lives in two directories — data under ~/.painapple-code/, credentials under ~/.config/painapple-code/ — never inside your project folders.
Data directory: ~/.painapple-code/¶
Override with PAINAPPLE_CODE_HOME. The Docker image sets it to /data (a named volume by default).
~/.painapple-code/
├── config.json # Global settings
├── tab-state.json # Open tabs + active tab (server-side, survives PWA quirks)
├── shortcuts.json # Keyboard-shortcut overrides
├── favorites.json # Favorited sessions
├── prompt-favorites.json # Favorited prompts
├── presets/ # Prompt/config presets (one JSON per preset)
├── shadow.duckdb # Turn metadata database (DuckDB, + .wal sidecar)
├── logs/ # Server logs (auto-rotating, see below)
└── projects/
└── {hash}/ # 12-char SHA256 of the resolved project path
├── path # Original project path (reverse lookup)
├── config.json # Project-specific settings
├── sessions/
│ └── {id}/
│ ├── meta.json # Session metadata (~350 bytes)
│ ├── messages.jsonl # Parsed conversation + cost (append-only)
│ ├── raw.jsonl # Raw Claude I/O (debugging/audit)
│ ├── tools/ # Large tool outputs (Read_xxx.txt, Bash_xxx.txt, …)
│ ├── stash.json # Comments-stash items
│ └── uploads/ # Uploaded images/files
└── shadow-git/ # Per-project shadow git repository (auto-journal)
Notes:
- One project per path. The
{hash}is derived from the absolute project path, so two clones of the same repo at different paths are separate projects. - UI-state files are per-tier. With
--state-suffix dev, the top-level state files becometab-state-dev.json,presets-dev/, and so on; project and session history stays shared. See the Server CLI reference. - Uploads before a session exists land in
uploads/tmp/at the top level.
Config directory: ~/.config/painapple-code/¶
Override with PAINAPPLE_CODE_CONFIG. Kept separate so credentials survive wiping the data directory.
| Path | Purpose |
|---|---|
config.yaml |
Auth password (mode 0600, parent 0700) |
tokens/ |
Optional token-profile files (alternate API credentials selectable per session) |
cert.pem, key.pem |
Auto-generated self-signed TLS cert/key (when TLS is enabled) |
fingerprint |
Cert fingerprint sidecar (only with --tls-fp-url) |
Log files¶
All in ~/.painapple-code/logs/ (override with --log-dir):
| File | Content | Rotation |
|---|---|---|
server.log |
All events, INFO and up | 10 MB, 5 backups |
access.log |
HTTP/WebSocket requests with timing | 10 MB, 3 backups |
error.log |
Errors with tracebacks | 5 MB, 10 backups |
crash.log |
Redirected stderr — uvicorn errors, unhandled exceptions | Append-only, no rotation |
server.pid |
PID of the running server (for post-mortem analysis) | Removed on clean exit |
Docker¶
In the container, PAINAPPLE_CODE_HOME=/data and /data is a named volume (or a bind mount, depending on your DATA_VOLUME setting). To copy the volume out to the host:
See the Docker CLI reference.
Backup, cleanup, and wipe¶
# Back up everything (sessions, journal, DB, settings)
tar czf painapple-backup.tgz -C ~ .painapple-code
# Find which project a hash belongs to
cat ~/.painapple-code/projects/{hash}/path
# Remove one project's history (sessions + shadow git)
rm -rf ~/.painapple-code/projects/{hash}
# Full wipe — auth config survives (it lives in ~/.config/painapple-code/)
rm -rf ~/.painapple-code
Stop the server before touching shadow.duckdb
DuckDB is single-writer and keeps a .wal sidecar. Back up or move the database only while the bridge is stopped, and copy the .wal file together with it.
Resuming sessions in the plain CLI¶
Sessions created through the bridge are regular Claude Code sessions. The provider session ID is stored in each session's meta.json (provider_session_id), and you can pick any conversation up from a terminal: