Skip to main content

Setup & configuration

Privacy & Security

This page covers how Bodega One handles your data and what runs to protect it - local storage, network isolation, shell command controls, file sandbox boundaries, and content guardrails.

Your data stays local

When you use a local provider (Ollama, LM Studio, llama.cpp, vLLM, etc.), all inference runs on your hardware. Conversation history, long-term memory, and your knowledge base are stored in a local SQLite database. Conversation content is never uploaded, and there is no usage analytics. Bodega keeps a local-only diagnostics trace on disk (never transmitted). Two optional paths can reach the network, and both are disabled by Air-Gap mode: crash reporting (off unless you opt in AND a crash key is built into the release) and - on the beta build - the email you enter on the activation screen (added to our beta mailing list).

A third, audit-oriented path is the optional OTLP audit export (telemetry.otlp_export_enabled, off by default; configured via settings keys only, no UI yet): it batches telemetry events and POSTs them to a local OpenTelemetry collector you run. The endpoint is validated against the localhost allowlist before every POST, so a non-loopback URL is rejected even with air-gap off - a loopback POST never leaves the machine, which is why this path is intentionally not blocked by Air-Gap mode. It also inherits the general.telemetry_enabled master gate.

To confirm your active provider: the model picker in the top bar shows which provider is in use. To change providers, go to Settings → Models → Providers.

If you use a cloud provider (OpenAI, Anthropic, Groq, etc.), your messages go to that provider's servers. Bodega One does not sit in the middle or store copies - but those messages do leave your machine. Switch to a local provider for full network isolation.

The diagnostics bundle (Settings → About → Export Diagnostics Bundle) stays on disk. Review it before sharing publicly - it can include file paths and command strings you have typed.

Where your data lives (and how to remove it)

Everything Bodega stores lives in one per-user folder - nothing is scattered across your system:

  • Windows: %APPDATA%\Bodega One
  • macOS: ~/Library/Application Support/Bodega One
  • Linux: ~/.config/Bodega One

Inside it: the SQLite database (bodega.db - conversations, memory, knowledge base), logs/, a local-only telemetry/ trace, downloaded models (llama-models/) plus the managed llama-server binary, and code-session worktrees (bodega-worktrees/). The diagnostics bundle (Settings → About → Export Diagnostics Bundle) prints the exact path at the top of the file.

Removing Bodega cleanly: the uninstaller removes the application but deliberately leaves this data folder in place - re-downloading multi-GB models on every reinstall would be painful. To wipe everything, uninstall and then delete the folder above. On Windows the uninstaller reminds you of this on screen.

Air-gap mode

Air-gap mode is a single toggle that activates 16 independent enforcement layers across the app. When on, agent tools cannot make outbound connections, the auto-updater is disabled, cloud speech-to-text is blocked, Cloud Boost routes to local, and license verification enters a grace period.

To enable:

  1. Open Settings → Privacy & Safety
  2. Under Network Privacy, toggle Air-Gap Mode on
  3. A toast confirms the change

To turn it off, toggle it again.

When air-gap is active, an Air-Gap badge appears in the top bar (shield icon + "Air-Gap" label) as a persistent visual confirmation. It is always visible while air-gap mode is on - you never have to open Settings to verify the status.

What air-gap blocks:

  • web_search and web_fetch tool calls
  • Shell commands that make network requests (curl, wget, git clone/fetch/pull/push, npm install, pip install, cargo install, go get, docker pull, and script execution via node, python, deno)
  • Cloud speech-to-text (fall back to local faster-whisper-server)
  • Auto-update checks - the Check for Updates button shows "Blocked (air-gap)"
  • Cloud Boost (re-routed to local provider)
  • License verification calls
  • llama.cpp binary install and GGUF download endpoints (return 403)
  • HuggingFace model search and repo file access (return empty results)
  • Ollama binary install and model-hub pull (return 403)
  • Remote model-catalog refresh (the optional External Model Catalog auto-update is refused - Bodega never fetches the remote catalog in air-gap mode and falls back to the bundled/cached catalog)
  • MCP servers that are marked as requiring network access

What air-gap does not block: your LLM provider's own traffic. If you have a cloud LLM configured, those messages still go out. Use a local provider for complete isolation.

Known limitation: the warning banner in Settings only fires when your provider preset is specifically openai. If you have Anthropic, Groq, Azure, or another cloud preset configured with air-gap on, no banner appears. Check your provider selection manually.

Air-gap attestation

For audit or compliance needs, Bodega can produce a signed, tamper-evident record of its air-gap enforcement. The Copy attestation button at Settings → Privacy & Safety → Network Privacy generates an HMAC-signed artifact summarizing, over the window since the app started, the count of recorded outbound fetches and the per-category ledger of air-gap refusals.

The HMAC secret never leaves the machine, and building the attestation reads local counters only - it makes no outbound call (so it works under air-gap). The artifact can be re-verified later, even on another machine, via the verify endpoint.

Honest scope: the attestation reflects recorded outbound fetches and counted refusals - it is not a guarantee that zero bytes ever left the box. The outbound counter observes the app's fetch paths; commands run through child_process (e.g. a shell curl) bypass that counter, which is why air-gap also blocks network-making shell commands at the tool layer.

Shell command security

The shell tool that the agent uses to run terminal commands has four independent layers of protection:

1. Blocked-pattern list. A fixed list of destructive and credential-reading commands is rejected before execution. This is hard-coded and applies regardless of permission mode.

2. Filtered child-process environment. Shell commands run with a curated subset of environment variables (paths, build-tool vars, locale) - not your full process.env. This prevents API keys, tokens, or other secrets set at the OS level from leaking into command output. Added in beta.26. This filtering is configurable via the global shell.env_policy setting with three levels: core (default - the historical allowlist of path, build-tool, and locale variables), none (bare shell essentials only), and full (pass the whole process.env through - opt-in, and still credential-scanned by layer 3). The shell.env_allow_extra setting additively widens core or none with named variables you trust (e.g. a build token). Both keys are GLOBAL-only - never project-config-whitelisted, so a committed repo config cannot widen a teammate's env exposure - and FORCE_COLOR=0 is always applied last.

3. Output credential scanning. After every command, the output is scanned and matched secrets are replaced with [REDACTED: type] before the result reaches the agent. Patterns covered:

  • SSH private keys
  • AWS access keys (AKIA...)
  • GitHub PATs (ghp_, gho_)
  • OpenAI API keys (sk-..., sk-proj-...)
  • Anthropic API keys (sk-ant-...)
  • Slack tokens, JWTs, PGP private keys
  • Database connection strings (mongodb://, postgres://, etc.)
  • Inline secrets in KEY=value or KEY: "value" forms
  • High-entropy base64 strings over 40 characters (git SHA hashes are excluded to avoid false positives)

4. Project-directory enforcement. The working directory cannot be outside your project root. The Windows type command (equivalent to cat) is also blocked to prevent indirect credential reads.

Approval behavior: In Ask mode (the default for new sessions), every shell command pauses for your approval before it runs. An approval card appears in the Agent panel with Accept and Reject buttons. Shell commands never auto-approve regardless of which mode is set - this is enforced at the route layer.

To change the approval mode, use the Ask / Act / Plan pill in the Agent panel header.

Agent permission modes

The Agent panel mode controls when the agent waits for your approval:

Mode File writes Shell commands Reads and searches
Act Automatic Automatic Automatic
Ask (default) Pause for approval Pause for approval Automatic
Plan Blocked until plan approved Blocked until plan approved Automatic

Switch modes with the pill in the Agent panel header. Research, Debug, and Advisor panels are always read-only regardless of this setting.

Shell Command Sandbox (Settings → Privacy & Safety → Content Filtering) adjusts what counts as "safe" in Ask and Act modes:

  • Off - every shell command requires manual approval
  • Moderate - safe commands auto-approve after a 30-second timeout
  • Strict - only read-only commands auto-approve

Note: regardless of sandbox level, shell commands never auto-approve - that restriction is at the route layer, not just the tool. The sandbox level affects the approval UI flow, not the underlying security gate.

Smart approval - fewer interruptions in Ask mode

Ask mode pauses for approval on every tool call, which is safe but noisy when the agent is just reading around. Smart approval lets a low-risk, read-only tool call auto-approve itself when it clearly matches what you just asked for - so a grep, a glob, or a web search the agent obviously needs doesn't make you click.

The security posture is the important part. Smart approval can only ever shrink the set of things you're asked about; it can never widen it:

  • Write tools are hard-blocked from auto-approval. shell, file_system writes, and str_replace always wait for your click.
  • The classifier runs last, after every existing security gate (the read-only predicate, the shell hard-block, command-risk classification). It is the final narrowing step, not a bypass.
  • It only acts in Ask mode (Act has no approval prompt anyway).
  • This first version uses static heuristics - no model call, no network - so it adds no latency and is safe under air-gap.

When a call auto-approves, no approval card appears at all. When it can't, you get the normal prompt as before.

It is off by default. Turn it on with permission.smart_approval, and set how confident the classifier must be before it auto-approves with permission.smart_approval_confidence_threshold (default 0.80). Both are global settings - a repo's project config can never flip them on for you.

Advanced gating: permission profiles & lifecycle hooks

Beyond Ask/Act/Plan, two power-user controls let you constrain or extend what the agent does. Both are configured today via settings / project config (no dedicated UI yet) and both only narrow or gate access - never widen it.

Named permission profiles. A profile is a reusable named rule set that denies tools by name, or allows/denies file writes by path glob - e.g. a readonly profile, or one that confines edits to src/** and blocks src/secrets/**. Activate one and every tool call is checked against it (after hooks, before the mode firewall). A profile can only restrict access; it composes with Ask/Act/Plan.

Lifecycle hooks (PreToolUse / PostToolUse). Run your own shell command before or after a tool - to lint, format, validate, or block a change. A PreToolUse hook can stop the tool (exit code 2) or rewrite its input; PostToolUse observes the result. Trust model: hooks you write in your own settings are trusted, but hooks committed in a repo's .bodega/config.json are never run until you explicitly approve them for that exact command + project - so cloning a repo can't run a hook behind your back.

Plan mode and approval persistence

In Plan mode, the agent writes a plan and stops. Nothing touches your files until you approve. Plan approvals persist to the database - they survive disconnects and app restarts. You can close the app after the agent produces a plan and come back later; the approval card will still be there.

This is intentional for long-running or background sessions.

Tool-level approvals (Ask mode prompts for individual file writes or shell commands) work differently: they auto-reject on disconnect. If you close the app while a tool approval is pending, that specific operation is cancelled. The session continues when you reconnect.

File system sandbox

The file_system tool the agent uses to read, write, and delete files is sandboxed to your open project folder. The boundary is set to whatever folder you opened in Code mode.

Requests that escape the boundary are rejected:

  • Path traversal attempts (../)
  • Absolute paths outside the project
  • Symlinks whose real targets point outside the project (the symlink target is resolved against the actual filesystem, not the symlink path)

Write and append operations also block a set of dangerous file extensions.

Errors from out-of-bounds attempts appear as tool call failure cards in the Agent panel.

The shell tool uses a separate enforcement path. Its working directory is blocked from escaping the project root. These two sandboxes are independent - passing the file system sandbox check doesn't bypass the shell sandbox, and vice versa.

Web fetch SSRF protection

The web_fetch tool blocks requests to private network addresses. This prevents an agent from being tricked into fetching internal services on your network (Server-Side Request Forgery).

Blocked targets:

  • All private IPv4 ranges: 127.x, 10.x, 192.168.x, 172.16–31.x, 169.254.x
  • localhost, 0.0.0.0
  • IPv6 loopback (::1), link-local (fe80::), and unique local (fc00::/7, covers fc* and fd*)
  • IPv6-mapped IPv4 addresses (::ffff:)
  • Decimal and hex integer IP notation (e.g. 2130706433 resolves to 127.0.0.1)

Only http: and https: are allowed. Other protocols are rejected.

DNS rebinding protection: after the hostname passes the initial check, it is resolved to an IP address and that IP is rechecked against the private ranges. This catches hostnames that look public but resolve to a private address.

Read-only panel enforcement

The Research, Debug, and Advisor panels cannot write files or run shell commands. This is enforced in ToolPreExecutionGuards - the guard fires at the pre-execution layer, before any tool runs, regardless of what mode the Agent panel is set to.

If you need the agent to take an action based on what Research or Debug found, copy the relevant output and send it to the Agent panel. Research also has a Save to Knowledge Base button that pins findings without writing project files.

Content guardrails

Guardrails apply filters to user messages before the agent processes them.

To configure:

  1. Open Settings → Privacy & Safety → Content Filtering
  2. Toggle Enable Guardrails on
  3. Adjust the sub-settings below:
Setting What it does Range
Custom Blocked Patterns One regex per line - messages matching any pattern are rejected Any valid regex
Shell Command Sandbox Auto-approval behavior for shell commands Off / Moderate / Strict
Max Input Length Maximum characters per message 100–100,000
Messages Per Minute Rate limit for incoming messages 1–200
Session Token Budget Maximum tokens consumed per session 1,000–1,000,000
  1. Click Save Safety Settings to apply

When Enable Guardrails is off, the entire Content Filtering section is dimmed and none of the sub-settings apply.

Custom Blocked Patterns are validated as you type - invalid regex lines show a red error with the line number. Changes don't apply until you save.

MCP server network access control

Each MCP server has a Network Access flag set when you add it in Settings → MCP Servers. When air-gap mode is on:

  • Servers marked as requiring network access cannot connect
  • New server additions with network access return 403
  • If a network-access server is already connected, tool calls to it are intercepted and blocked at the pre-execution layer

The network access flag is self-reported at configuration time - the app cannot verify whether a server actually makes outbound calls. The flag defaults to true (network access required) for new servers, which is the safer default.

The legacy single-server MCP endpoint blocks entirely in air-gap mode, not just network-access servers.

Memory and knowledge base

Memory entries and knowledge base cards are stored in local SQLite. Every query includes a user_id filter - cross-user memory access is treated as a security bug, not a missing feature.

Nothing is synced or backed up externally. To see what the agent remembers, ask it: "What do you remember about me?" To remove a specific entry, say: "Forget [fact]".

Knowledge base entries are managed via gear menu → Knowledge.

API server authentication

Bodega One can expose an OpenAI-compatible API on port 1337 (Settings → API Server). This lets external tools - Claude Code, Continue, Cursor, custom scripts - use Bodega as an LLM backend.

The server binds to localhost only and is not exposed to your network by default. When no API key is set, it accepts unauthenticated local requests. If other users or processes can reach port 1337 on your machine, set an API key in Settings → API Server → API Key - requests will then require it as a Bearer token.

Keyboard shortcuts

KeysAction
Ctrl+1Switch to Chat mode
Ctrl+2Switch to Code mode
Ctrl+LOpen Agent panel

This page mirrors the in-app docs hub for app version 1.0.0-beta.32.1. Found something unclear or out of date? Tell us on Discord. New here? Download the free beta and follow along.