Skip to content

Data directory layout

Pluma stores everything user-specific under a single data directory.

OS Default path
macOS ~/Library/Application Support/pluma or $XDG_CONFIG_HOME/pluma
Linux $XDG_CONFIG_HOME/pluma or ~/.config/pluma
Windows %AppData%\pluma

Override with -data-dir <path> or PLUMA_DATA_DIR=<path>.

File layout

<datadir>/
├── config.toml                # server config; see Reference → config.toml
├── connections.json           # LLM connection profiles (no keys; keyring holds those)
├── image_connections.json     # SD backend profiles (no keys)
├── credentials.json           # enrolled WebAuthn passkeys (encrypted)
├── conversations/
│   └── <id>.json              # encrypted; atomic tmp+rename; mode 0o600
├── characters/
│   ├── <id>.png               # Tavern card (PNG with v2/v3 chunks); share-ready
│   └── <id>.json              # avatar-less card (promoted to PNG when an avatar lands)
├── personas/
│   ├── <id>.png               # persona card (Tavern v2 with persona extension)
│   └── <id>.json              # avatar-less persona
├── models/
│   └── <repo>/...             # downloads from the HF browser
├── workflows/
│   └── *.json                 # ComfyUI workflow library (ships with flat-anime-portrait)
├── voices/
│   └── library/
│       ├── <id>.<format>      # voice-library audio sample (wav / mp3 / m4a / ...)
│       └── <id>.json          # sample metadata
├── tsnet/                     # embedded Tailscale node state (when tsnet_enabled)
└── attachments/
    └── <name>.png             # generated images, referenced by message id (plaintext)

Encryption

Path Encrypted?
config.toml No (plaintext on disk; no secrets in it)
connections.json / image_connections.json No metadata; keys live in the OS keyring under connection:<id> / image:<id>
credentials.json Yes (AES-256-GCM; key in OS keyring under storage-key)
conversations/*.json Yes (AES-256-GCM; same storage-key)
characters/*.{png,json} No (browseable in Finder; Tavern card is a public-share format anyway)
personas/*.{png,json} No
attachments/*.png No
models/**, workflows/**, voices/** No
tsnet/** Tailscale node state; encrypted by tsnet itself

The storage-key is generated on first boot, stored in the OS keyring (Keychain / libsecret / Credential Manager). Lose access to the keyring → ciphertext files become unreadable. Back up with pluma -export-storage-key <path>; restore with pluma -import-storage-key <path>.

What to back up

  • All of <datadir> is the simplest answer. Tar it up.
  • Just user content: conversations/, characters/, personas/, workflows/, attachments/, voices/. Plus the wrapped storage-key from pluma -export-storage-key so conversations/ can be decrypted on the restore machine.

What you can safely delete

  • models/<repo>/ for any model you don't want anymore (re-downloadable via the HF browser).
  • attachments/<name>.png for stale message attachments (the chat keeps a reference, the image just won't render).
  • tsnet/ if you want to fully unenrol the device from your tailnet (next tsnet_enabled = true will re-auth).
  • The entire data directory if you want a clean re-test of the first-run flow.