poly/code

Polycode data lifecycle

Polycode stores conversations, files, and credentials locally on your Mac, and does not require an account. Providers (Anthropic, OpenAI, Google, OpenAI-compatible endpoints, Apple Foundation Models, plus enterprise cloud gateways: Vertex AI, AWS Bedrock, Azure OpenAI) are reached directly from your Mac using your own credentials, which are stored in your macOS Keychain. No Polycode-operated server stores or relays user content. Polycode sends anonymous usage metrics and automatic crash reports by default — see Diagnostics below for the full list of categories and the one-click opt-out.

Polycode is a sandboxed Mac App Store application that uses an App Group container — a sandbox affordance for cross-target shared storage — for its primary state (sessions, messages, model metadata, caches, indexes, and user preferences):

~/Library/Group Containers/group.com.izzo.polycode/Library/Application Support/Polycode/

A small number of macOS-managed preferences (@AppStorage toggles) live alongside the app’s per-app sandbox at ~/Library/Containers/com.izzo.Polycode/. Everything else Polycode reads or writes lives under the App Group path. That structure shapes the four workflows below. In-app controls for these actions are tracked for a subsequent release; this article describes the manual-equivalent procedure available today.

Wipe

To remove every piece of local Polycode state from your Mac:

  1. Quit Polycode (⌘Q).
  2. In Finder, open ~/Library/Group Containers/ (use ⇧⌘G and paste the path).
  3. Delete the group.com.izzo.polycode folder. The Finder trashes it like any other folder.
  4. In Finder, open ~/Library/Containers/.
  5. Delete the com.izzo.Polycode folder. This removes the macOS-managed Preferences plist alongside the app’s per-app sandbox.
  6. Empty the Trash if you want the bytes gone immediately.

Alternatively, drag Polycode.app to the Trash. macOS deletes the per-app sandbox container alongside the app, but does NOT delete the App Group container — that persists across re-installs because it is shared with other targets in the developer team. To wipe the App Group data, delete ~/Library/Group Containers/group.com.izzo.polycode/ separately.

Keychain note: API keys and MCP auth tokens are stored in the macOS Keychain, not inside either container. Deleting the containers does not remove them. To clear credentials, open Polycode → Settings → Privacy → Clear all credentials (a single action that removes every provider key from the Keychain). Keychain items are also wiped when you uninstall the app via macOS’s standard uninstall flow.

Back up

Polycode’s App Group container is an ordinary directory. To back it up manually:

  1. Quit Polycode.
  2. In Finder, open ~/Library/Group Containers/ (use ⇧⌘G).
  3. Copy the group.com.izzo.polycode folder to your backup location (external drive, cloud folder, archive utility — whichever you prefer).
  4. (Optional) Also copy the small ~/Library/Containers/com.izzo.Polycode/ folder if you want to preserve macOS-managed Preferences (@AppStorage toggles).
  5. Relaunch Polycode. Your session resumes unchanged.

What’s inside the copy:

Time Machine, Arq, Backblaze, and any other backup tool that walks the user library captures both paths automatically.

Restore

To restore a previous backup onto the same or a different Mac:

  1. Quit Polycode.
  2. In Finder, open ~/Library/Group Containers/ (use ⇧⌘G).
  3. Delete the current group.com.izzo.polycode folder (or move it aside).
  4. Copy your backup group.com.izzo.polycode folder into ~/Library/Group Containers/.
  5. (Optional) If you also backed up ~/Library/Containers/com.izzo.Polycode/ for the Preferences plist, replace that folder too.
  6. Relaunch Polycode.

Version compatibility: the SwiftData schema version is embedded in the store. Polycode runs its migration plan on launch when it detects an older schema, so restores from an older Polycode into a newer Polycode work as long as the schema remains within the supported migration window. Restoring a newer container into an older Polycode is not supported — install the matching version or newer.

Keychain credentials do not travel with the container. On a restore (or a new Mac), re-enter your provider API keys via Settings → Providers.

Migrate between Macs

Polycode has no cloud sync and no account system, so migration is exactly the backup + restore workflow above, run across two machines:

  1. On the source Mac: quit Polycode, copy ~/Library/Group Containers/group.com.izzo.polycode/ (and optionally ~/Library/Containers/com.izzo.Polycode/ for the Preferences plist) to portable storage (AirDrop, external drive, file-sync folder).
  2. On the destination Mac: install Polycode from the App Store (or your TestFlight build), launch it once to let macOS create an empty App Group container, then quit.
  3. Replace ~/Library/Group Containers/group.com.izzo.polycode/ on the destination Mac with the copy from the source. If you brought the per-app sandbox too, replace ~/Library/Containers/com.izzo.Polycode/ as well.
  4. Launch Polycode on the destination.
  5. Open Settings → Providers and re-enter your API keys (they live in the per-Mac Keychain and do not travel with the container).

Because nothing Polycode needs lives outside these two containers, this is the complete migration procedure.

Attachments

Polycode lets you attach files to a draft in two ways: drag-drop or paste from anywhere on disk (an inline-content attachment), or pick a file from a project you’ve added in the sidebar (a scoped-file attachment). The handle and byte semantics differ:

Pressing submit transmits attachment bytes off your device. Each attached file is sent to every LLM provider that is enabled in the current fan-out and to the primary provider’s synthesis call. A single chip therefore produces N provider calls + 1 synthesis call, all carrying the bytes. Anthropic / OpenAI / Google receive the file as a native content block (document / input_file / inlineData); OpenAI-compatible endpoints (Ollama / LM Studio / xAI / OpenRouter / Custom) receive a banner-wrapped text fallback and reject non-text binary attachments. Apple Foundation Models receives a text projection of the file inline in the prompt.

To remove a persisted attachment from the local store, delete the conversation that contains it (Settings → Privacy → Clear all data, or the per-session delete in the sidebar). Wiping the sandbox container per Wipe above also removes every attachment Polycode has stored.

Project context

When a session is bound to a project (the project chip on the chat titlebar is set), Polycode synthesizes a project context block and sends it as the system prompt on every chat submit and every regenerate. The block contains the project’s name, its absolute root path, today’s date, your macOS marketing version, your project’s excludedPatterns, a depth-2 directory listing, and the contents of any recognized convention files at the project root: AGENTS.md, CLAUDE.md, GEMINI.md, .cursorrules, every *.md file under .cursor/rules/ (alpha-sorted), CONVENTIONS.md, with README.md as a fallback only when none of those exist. The directory listing honors your project’s excludedPatterns; the convention files do not (a stray *.md exclusion does not silently disable an authored AGENTS.md).

The block is sent to every LLM provider you have configured — Anthropic, OpenAI, Google, OpenAI-compatible endpoints, and Apple Foundation Models — as part of the standard fan-out + synthesis flow. It is not sent to PostHog or Sentry. The block is rebuilt on every submit (no cache), so edits to your context files take effect on the very next turn. Per-model systemPromptOverride settings (Settings → Providers → Provider Detail → advanced drawer) take precedence: when you’ve set an override, the project context block is replaced by your override for that model and is not transmitted.

To opt out per-project, toggle off “Inject project context into chats” under Settings → Projects. The opt-out persists locally in the same SwiftData container as the rest of your settings; subsequent submits on sessions bound to the opted-out project send systemPrompt: nil (or the per-model override if set).

Usage

The Settings → Usage tab summarizes how much you’ve spent across providers and where that spend is concentrated. It is a read-only dashboard computed entirely on your Mac:

Cloud gateways

Polycode supports three enterprise cloud gateways alongside the direct provider APIs: Vertex AI (Google Cloud), AWS Bedrock (Amazon), and Azure OpenAI Service (Microsoft). These are configured under Settings → Providers → Cloud Gateways with one row per per-account / per-project / per-resource instance. A user may configure many instances per gateway.

Credential flow. The credential you provide (Vertex service-account JSON, AWS access-key + secret + optional session-token, or Azure resource api-key) is read once at add-instance time, JSON-encoded, and stored in your macOS Keychain under a per-instance slot (cloud.<uuid>.credential). The credential is never logged, never sent to a Polycode-operated server, and only used to mint per-request auth headers against the cloud you configured:

Where prompts go. Cohort prompts flow only to the cloud gateway you configured. Vertex AI prompts go to <region>-aiplatform.googleapis.com. Bedrock prompts go to bedrock-runtime.<region>.amazonaws.com. Azure prompts go to <resource>.openai.azure.com. Polycode does not relay cohort prompts through any Polycode-operated server.

Diagnostics scope. Cohort traffic is out of scope for the diagnostics pipeline. Disabling diagnostics under Settings → Privacy → Diagnostics has no effect on cohort prompt routing, because cohort prompts never go through PostHog or Sentry to begin with — they go directly to the cloud you configured. See Diagnostics for what diagnostics actually does cover.

Removing a cohort instance. Settings → Providers → Cloud Gateways → Remove deletes both the CloudInstance row from your local config and the matching cloud.<uuid>.credential slot from your Keychain. A launch-time orphan-reconciliation pass also runs every time Polycode starts, so a credential whose CloudInstance was deleted by another path is cleaned up on next launch.

Diagnostics

Polycode sends two kinds of anonymous diagnostics by default to help improve the app:

Neither pipeline collects your IP address, your macOS username, your email, a device serial, or any account identifier. The product-interaction pipeline uses an anonymous install UUID generated on first launch so retention can be measured; that UUID is scoped to PostHog only — it is never passed to Sentry, and it never appears in crash payloads.

Opt out. Open Settings → Privacy → Diagnostics. Two toggles — “Share anonymous usage metrics” and “Share crash reports” — each default to on and can be flipped off independently. Turning a toggle off flushes in-flight events and stops the corresponding SDK from sending further data; turning it back on resumes collection with the existing install UUID.

Reset diagnostics ID. The “Reset diagnostics ID” button in the same section generates a new anonymous UUID, discarding the prior one. Use this if you want to break continuity of anonymous analytics for this install — the SDKs re-initialize and the next event carries the new UUID.

Debug builds never phone home. Development builds running under Xcode short-circuit both SDKs regardless of toggles, so engineer activity does not pollute production diagnostics.

Data residency (current release-runner configuration). The v1.0 release runner injects PostHog US cloud (https://us.i.posthog.com, the default POLYCODE_POSTHOG_HOST in Config/Shared.xcconfig) and Sentry US cloud as the diagnostic ingest endpoints. Both DSNs ship empty in the committed Shared.xcconfig and are CI-injected per build, so other release-runner configurations — or self-hosted builds — may target different clouds (TelemetryConfig.swift accepts US or EU Sentry DSNs and any PostHog host); this paragraph describes what the v1.0 release runner does, not a hard product guarantee. The retention and deletion policies of PostHog and Sentry govern already-shipped data; the in-app Reset diagnostics ID button changes future identifier association, not historical data. EU-cloud migration is tracked as a follow-up item under 2026-04-22-telemetry-posthog-sentry in TODOS.md.