Data & Privacy

Where your data lives, how to export it, and what stays local

Everything runs on 127.0.0.1, transcripts stay in your own space, and secrets live only in the platform keychain.

python
from praisonaiagents import Agent

agent = Agent(
    name="Assistant",
    instructions="You are a helpful assistant.",
)
# This agent runs on your machine — its transcripts stay local.
agent.start("Nothing leaves this Mac unless the model does")
Diagram

👤 You

🖥️ App

📁 Local Data

🔐 Keychain

Quick Start

  1. Find your data

    The engine reports its real location at GET /health as data_dir — the app’s Reveal in Finder uses that path, so it honours any override.

  2. Export it

    Use Export all — it copies your data to the clipboard.

  3. Delete it

    Delete all removes stored conversations; Reveal in Finder opens the folder.


Where Data Lives

The data directory is platform-specific and overridable with PRAISONAI_DESKTOP_HOME. Ask the engine for the true path: /health returns data_dir, which honours every override — so the copy data folder action reports the path the app actually uses.

PlatformDefault data directory
macOS~/Library/Application Support/PraisonAI
Windows%APPDATA%\PraisonAI
Linux$XDG_DATA_HOME/PraisonAI or ~/.local/share/PraisonAI
PathContents
chats/*.jsonOne append-only transcript per conversation
settings.jsonYour settings — no secrets
runs/*/Fine-tune configs, logs, and checkpoints
Engine log ring bufferRecent engine activity (in memory, bounded)
Keychain / DPAPI / secret serviceSecrets such as api_key
secrets/<service>.json (fallback)Plaintext fallback store, mode 0o600
Diagram

📁 Application Support/PraisonAI

chats/*.json

settings.json

🔐 Keychain

api_key


What Stays Local

The engine listens only on 127.0.0.1, refuses cross-origin browser requests it does not recognise, and cloud API keys are the sole path off-device.


Secrets

Secrets go to the platform store — the macOS keychain, Windows DPAPI, or the freedesktop secret service — with a plaintext file fallback for machines with no keyring.

GuaranteeBehaviour
Store isolationPRAISONAI_KEYCHAIN_SERVICE (default ai.praison.desktop) names the service; override it to isolate test keys
Fallback location<data_dir>/secrets/<service>.json; mode 0o600, unlinked and recreated on each write
Durable readsAn unreadable store raises rather than returning empty, so a transient IO failure never causes the next set to overwrite a good secret
Clean deletesDelete clears both the keychain/DPAPI entry and the fallback file — no plaintext copy survives

Secret Store Guarantees

The secret store is durable and tightened, so a transient glitch can never quietly lose or leak a credential.

GuaranteeWhat it means
Unreadable raisesA store that can’t be read raises instead of returning empty, so the next set never overwrites a good secret with {}.
Delete clears bothDeleting an api_key clears both the keychain/DPAPI store and the fallback file — no stale plaintext survives a delete.
Tight file writesThe fallback file store uses unlink + O_EXCL + 0o600, so no reused-mode leftover can leave a secret world-readable.
Env varDefaultEffect
PRAISONAI_KEYCHAIN_SERVICEai.praison.desktopIsolate secrets under a different service name (CI/test escape hatch).

Environment & Overrides

Point the app at your own runtime, engine, or data folder with these variables.

VariablePurposeNotes
PRAISONAI_ENGINEOverride the path to the Python engine scriptOtherwise resolved from the bundle Resources, then a checkout.
PRAISONAI_PYTHONOverride the interpreter used for the engineSkips the managed venv entirely — you own the runtime.
PRAISONAI_DESKTOP_HOMEOverride the data directory (chats, settings, venv, engine log)The engine mirrors this — one variable, one place.
PRAISONAI_APP_BUNDLEThe .app path so the LaunchAgent can find itSet by the shell; contributors set it when testing Launch at Login from cargo run.
OPENAI_API_KEY / OPENAI_API_BASEModel credentialsOnly cleared on exit when the engine set them itself — existing shell values are preserved.

HTTP Endpoints

The engine speaks plain HTTP on 127.0.0.1. The routes the app relies on:

EndpointBehaviour
POST /chatStream a turn; accepts regenerate_of (message index to re-answer) and a per-turn tools override
POST /version/{cid}/{idx}/{n}Switch a message row to a specific prior version
GET /chats/{id}Returns the transcript; 404 when the id is unknown
GET /settingsReturns settings with api_key masked as bullets, never the real value
GET /updateChecks PyPI (https://pypi.org/pypi/praisonaiagents/json) for a newer release
GET /healthReports { ok: true, version: 2, data_dir }

Accessibility

The interface is built for screen readers and keyboard use, and tests enforce each invariant.

AreaBehaviour
Landmarksmain, nav, header, complementary regions, with a labelled sidebar
Transcriptrole="log" + aria-live="polite", so streamed answers are announced
Engine statusrole="status" + aria-live="polite"
Icon-only controlsCarry a word aria-label; decorative glyphs carry aria-hidden
Conversation rowsKeyboard-focusable (role="button", tabindex=0) with aria-label
Tools buttonReports aria-pressed; the sidebar toggle reports aria-expanded
DialogsDelete confirms and the first-run panel are role="dialog" + aria-modal, trap focus, and return focus to the opener on close

UI Scaling

font_size drives a --ui-scale CSS variable and everything downstream is rem, so one change scales the whole interface.


Best Practices

Back up the chats folder

Transcripts are plain JSON you can read, diff, and back up. Copy chats/ to keep your history safe across app updates.

Restoring: copy individual chats/<id>.json object files back into chats/. Do not drop the Export clipboard payload (a JSON array) into chats/ — the app surfaces it as an (unreadable) row and moves on, but the transcripts inside will not appear as chats. Split the array into per-conversation object files first, or re-import a copy of the original chats/ folder.

Diagram

📤 Export

JSON array → clipboard

💾 On-disk transcript

JSON object → file

Override the home for isolation

Set PRAISONAI_DESKTOP_HOME to point the app at a separate data directory — useful for testing or keeping profiles apart.

Use a local model for full privacy

Point base_url at a local server so even the model runs on-device and no data leaves the machine.


Related