Documentation

Painted Wolf Code is a local-first AI coding app. These guides are the user manual: install it, open a project, and do real work. Read straight through, or use the rail to jump — it tracks where you are as you scroll.

Building on the app — custom workflows, rules, packs — lives in the SDK. Engine contracts live in the product repository.

These guides describe Painted Wolf Code v1.

Getting started

Painted Wolf Code runs on your machine. You choose the model provider, attach the projects it may work in, and control its approvals. It collects no telemetry; see Security & privacy for what can leave your machine.

Install and first run

The v1 desktop app runs on macOS 14 (Sonoma) or later, Apple Silicon. Get the current installer from Download — a Developer-ID-signed .dmg, or a Homebrew cask.

  1. Install the app.
  2. On first launch, add an AI provider, choose your strongest tool-calling model as the default model, and optionally choose a smaller summarizer. Providers has the setup steps.
  3. Open or clone a repository from Home, then type what you want done.

You can change models later under Settings → AI providers. Readiness cards call out missing local tools before a run depends on them.

The app’s local decision model ships inside it and is ready on first launch.

When an update is available, the app shows a notice and keeps its controls under Settings → General → Updates. A direct DMG install can download, verify, install, and restart there. Homebrew installs stay on brew upgrade --cask painted-wolf-code. Turning automatic checks off is remembered; Check now still checks when you request it.

The app bundle includes a pw command for opening projects from a shell. Projects covers putting it on your PATH.

Everyday work

  • Just type for direct changes. Use /plan when you want research and a Blueprint approved before implementation; type / to browse other workflows.
  • Open cited files. Citations land on the exact line in Files, where Mod+I requests a focused edit and Review shows the finished diff.
  • Check the evidence. Answers cite their sources. Progress, Worklog, and Workers show longer runs without interrupting them.
  • Change your mind. Edit or rewind a message to review and undo the work from that point onward.

Arrange the workspace

Chat can sit beside a Context view, or either can open in another window. Open Layout at the bottom of the workspace to choose Single view or Split view. Swap chat and context exchanges the two columns; Mirror workspace also moves the sidebar and Files tree to the opposite side. Drag a pane edge to resize. The main workspace remembers these choices; each secondary window keeps its own.

Hide chat or Context with its edge arrow when you need more room, then restore it without losing your place. Layout also offers hide/show actions; the sidebar, chat, Context, and Files tree each have a customizable keyboard toggle. When a window is too narrow for both columns, one view gives way automatically and returns when there is room. Double chevrons ask the window to make room sooner.

Context viewUse it for
FilesBrowse, edit, and review project files.
SearchFind chats, files, code, evidence, and commands.
SecurityReview scanner findings.
CostTrack estimates and set a spend ceiling.
BlueprintsRevisit plans for larger changes.
ArtifactsReturn to images and other durable outputs.
ExtensionsManage project-specific customization.

Right-click the Context list to hide, reorder, or open a view in another window. For isolated work, choose Git → Work on a branch…; see Git.

Everyday shortcuts

Mod is Command on macOS and Ctrl on Windows and Linux. Press ? when you are not typing — or Mod+/ anywhere — for the complete list on this device. Rebind under Settings → General → Keyboard.

ActionShortcut
Open CrossbarMod+K
Find in the current viewMod+F
Find everywhereMod+Shift+F
Replace across the projectMod+Shift+H
Ask for an inline editMod+I
Add the selection to chatMod+L
New chatMod+N
Stop work in the current chatMod+.
Open SettingsMod+,

Press Mod+;, release it, then a letter to jump: C chat, F Files, K Search, S Security, O Cost, A Artifacts, L Blueprints, E Extensions.

The app follows System Settings → Accessibility → Display → Text size, VoiceOver, Spoken Content, and reduced motion. There is no separate accessibility mode and no second text-size slider.

Projects & chats

A project holds folders, chats, Blueprints, findings, cost history, and configuration. A chat is one conversation inside it.

Starting a project

You can start typing on Home before choosing a folder. The first message creates a draft in an app-managed private workspace. Choose Save as a project or Save to folder… to move it into an empty folder; the draft stays intact until the saved project is committed.

For existing code, choose Open folder. The confirmation summarizes the repository and any guidance or capabilities it contributes. Guidance such as AGENTS.md is readable immediately; MCP, extensions, and project settings wait for your review. If the repository changes while that review is open, the app applies nothing from the stale decision.

Choose Clone a repo… when the code is not on this device. Enter its Git URL and an empty destination folder. The app clones and opens it, then asks you to review repository capabilities.

A folder already registered with a project opens that project. To keep a second, separate project over the same folder, ask for one deliberately with pw --new <folder>.

Folders and repositories

A project may hold several folders. One is primary for unqualified paths and new Blueprints. Short labels such as @api/ or @web/ name another root in chat.

Attach, detach, rename, or choose the primary folder from Project configuration. Built-in file tools (reading, writing, editing, and searching) do not extend past the project’s attached folders and temporary scratch space; reaching an outside path requires an explicit approval. Detaching the last folder keeps the project, its chats, and saved approvals, but file and command tools stay unavailable until you attach another one.

Before removing a folder or project with running chats, pending worker changes, or open editor state, the app asks you to confirm stopping or discarding that dependent work.

Painted Wolf Code refuses the filesystem root, your whole home folder, credential stores such as .ssh, and broad folders that contain them. Choose the source folder itself. The same check runs whenever a tool uses an attached folder.

Several roots may belong to one Git repository, and one project may contain several repositories. Files and Git keep those scopes distinct.

Secrets a project tracks

Project configuration → Secrets lists the credentials this project protects: what each one is for, where it came from, its scope and current version, whether it still works, and recent attempts to use its reference. Ordinary lists, chat, tool results, and API reads never return a value.

Entries arrive in six ways: the host generates random material for an agent; you answer a protected secret question; you choose Protect when the outbound screen catches a value on its way to a model; you mark a value in a file or in a message draft; or you add one directly in Project configuration. Every path produces a stable reference the agent can carry without receiving the bytes, and the list says which path each entry came from.

From a secret’s detail view you can relabel it, set an agent-use deadline, replace or restore its value, promote a task secret to the whole project, inspect recent uses, or revoke it. Replace stored value keeps the reference and retires the old value so it can still be recognized and redacted; it changes only the app’s protected copy, never a project file or the credential at its provider. Revocation is permanent and also ends reveal.

A passed agent-use deadline stops the agent substituting the value; it does not expire the credential itself, and you can still reveal the value to recover it.

Reveal value asks the operating system to verify you on a supported packaged build, then shows the current value only in that detail view. It hides after 30 seconds and whenever the window loses focus. The reveal is recorded without recording the value. Expired values remain revealable for recovery; revoked secrets and secrets whose current bytes are unavailable do not.

This is not a secrets manager or key service. It does not provision credentials in an external system or distribute them to workloads. It keeps credentials already needed by local work away from the model while giving the agent a bounded way to use them.

Managing projects and chats

Home separates Recents, Drafts, Starred, and All. Select several rows to star, unstar, or delete them together.

Deleting a project removes its chats, source history, findings, and local project records, including an unsaved draft workspace. Attached folders and repositories stay on disk. Extensions stay installed unless you select eligible ones for removal; the confirmation shows checked references and keeps any whose status is uncertain.

Use the chat menu to Rename, Pin, Archive, Delete, or Export as Markdown or JSON. Archive preserves history and search; sending a message unarchives it. Delete stops the run and removes the chat permanently. Unbind a chat’s worktree before deleting it.

The sidebar is a working set. All chats searches and sorts every chat in the project, including archived ones.

Open from the terminal

The app bundle includes pw. Put it on your PATH and pw . opens the current folder in Painted Wolf Code.

Recommended: in the app, open Crossbar (Mod+K) and choose Install pw command. That symlinks pw and pw-logs into /usr/local/bin. Settings → Advanced has the same action.

Manual: add Painted Wolf Code.app/Contents/MacOS/ to your PATH, or symlink pw and pw-logs into /usr/local/bin yourself.

CommandResult
pw / pw . / pw <folder-or-name>Open the matching project. Defaults to the current directory.
pw --new <folder>Create a second project for a folder already in another project.
pw lsList projects, most recently opened first.
pw logsOpen the interactive local log browser.
pw completion zsh / bashPrint a completion script for eval in your shell.

Opening never silently creates or rewires a project. When the folder is new, the desktop app shows a proposal so you can confirm. Repeating pw . in the same repo always returns to the same project.

# zsh — add to ~/.zshrc
eval "$(pw completion zsh)"

# bash — add to ~/.bashrc
eval "$(pw completion bash)"

Completion reads a name cache refreshed by pw ls. Authoring verbs — packs, workflows, rules — are in the SDK Reference.

Providers

Painted Wolf Code uses a provider you bring. Cloud requests go directly to the account you pay for; local backends need no API key. Credentials stay on your device and outside project folders.

Connect a provider

Open Settings → AI providers, choose Add AI provider, and select a provider. Most cloud providers ask for an API key. Bedrock accepts either a Bedrock API key or your normal AWS credential chain; Vertex uses Google Application Default Credentials; local backends such as Ollama use their local endpoint. oMLX is macOS-only.

Cloud services often show a new key only once. Copy it immediately and replace it if you think it was exposed.

Choose a provider below for its current setup steps:

Pick your provider:

Run locally

Cloud / hosted

Custom

LiteLLM No key needed
  1. Install LiteLLM from docs.litellm.ai/docs/simple_proxy.
  2. Make sure LiteLLM is running locally.
  3. In the app: Settings → AI Providers → Add AI provider → LiteLLM, then Add AI provider. There is no key to enter.
LM Studio No key needed
  1. Install LM Studio from lmstudio.ai.
  2. Make sure LM Studio is running locally.
  3. In the app: Settings → AI Providers → Add AI provider → LM Studio, then Add AI provider. There is no key to enter.
Ollama No key needed
  1. Install Ollama from ollama.com/download.
  2. Pull a model that supports tool calling — that is what the agent needs — sized to your hardware. For example: ollama pull qwen3.
  3. Make sure Ollama is running locally.
  4. In the app: Settings → AI Providers → Add AI provider → Ollama, then Add AI provider. There is no key to enter.
oMLX No key needed
  1. oMLX is available on macOS only.
  2. Install oMLX from omlx.ai.
  3. Make sure oMLX is running locally.
  4. In the app: Settings → AI Providers → Add AI provider → oMLX, then Add AI provider. There is no key to enter.
Amazon Bedrock Key or cloud credentials
  1. Sign up or sign in with Amazon Bedrock.
  2. Bedrock takes either a Bedrock API key — left navigation, API keys, then Generate — or the AWS credentials you already have (AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY env vars, ~/.aws, or an IAM role); enter the AWS region in the endpoint field. The model picker lists active inference profiles available to that account. Enable model access in the Bedrock console first.
  3. Open Amazon Bedrock's API keys page at console.aws.amazon.com/bedrock, then create or copy a key.
  4. In the app: Settings → AI Providers → Add AI provider → Amazon Bedrock. Paste the key, or leave it empty to authenticate with the credentials above, then Add AI provider.
Anthropic API key
  1. Sign up or sign in with Anthropic.
  2. Open Anthropic's API keys page at console.anthropic.com/settings/keys, then create or copy a key.
  3. In the app: Settings → AI Providers → Add AI provider → Anthropic, paste the key, and Add AI provider.
Azure OpenAI API key
  1. Sign up or sign in with Azure OpenAI.
  2. Create an Azure OpenAI resource and a model deployment, then set the backend's Endpoint URL to your resource (https://YOUR_RESOURCE.openai.azure.com) and use the deployment name as the model id. The app uses Azure's current v1 route; there is no API version or deployment path to enter. The key is the resource's Keys and Endpoint value.
  3. Open Azure OpenAI's API keys page at portal.azure.com/, then create or copy a key.
  4. In the app: Settings → AI Providers → Add AI provider → Azure OpenAI, paste the key, and Add AI provider.
Cloudflare Workers AI API key
  1. Sign up or sign in with Cloudflare Workers AI.
  2. The token needs Workers AI with both Read and Edit; add Account Analytics Read as well if you want the app to show your usage quota. Replace YOUR_ACCOUNT_ID in the backend's Endpoint URL with your Cloudflare account id.
  3. Open Cloudflare Workers AI's API keys page at dash.cloudflare.com/profile/api-tokens, then create or copy a key.
  4. In the app: Settings → AI Providers → Add AI provider → Cloudflare Workers AI, paste the key, and Add AI provider.
Fireworks API key
  1. Sign up or sign in with Fireworks.
  2. Open Fireworks's API keys page at fireworks.ai/api-keys, then create or copy a key.
  3. In the app: Settings → AI Providers → Add AI provider → Fireworks, paste the key, and Add AI provider.
Google Gemini API key
  1. Sign up or sign in with Google Gemini.
  2. Open Google Gemini's API keys page at aistudio.google.com/apikey, then create or copy a key.
  3. In the app: Settings → AI Providers → Add AI provider → Google Gemini, paste the key, and Add AI provider.
Google Vertex AI Cloud credentials
  1. Sign up or sign in with Google Vertex AI.
  2. This backend authenticates with Google Application Default Credentials — run gcloud auth application-default login, or point it at a service-account key; Vertex express-mode API keys are not used here. Enable the Vertex AI API, and set GOOGLE_CLOUD_PROJECT and, when needed, GOOGLE_CLOUD_REGION in the environment. The configured project and ADC identity must both be present before the backend is ready.
  3. In the app: Settings → AI Providers → Add AI provider → Google Vertex AI, then Add AI provider. There is no key to paste — the backend uses the credentials described above.
Google Vertex AI (express mode) API key
  1. Sign up or sign in with Google Vertex AI (express mode).
  2. Express mode trades setup for scope: signing up issues an API key with no project, region, or gcloud login — but it serves a subset of Vertex models. The picker shows only models visible to the key that also report conversation capabilities. For the full catalog under Application Default Credentials, use the Google Vertex AI backend instead.
  3. Open Google Vertex AI (express mode)'s API keys page at cloud.google.com/vertex-ai/generative-ai/docs/start/express-mode/overview, then create or copy a key.
  4. In the app: Settings → AI Providers → Add AI provider → Google Vertex AI (express mode), paste the key, and Add AI provider.
OpenAI API key
  1. Sign up or sign in with OpenAI.
  2. Add a payment method under Settings → Billing. OpenAI rejects API requests until billing is set up, even on a new account.
  3. Open OpenAI's API keys page at platform.openai.com/api-keys, then create or copy a key.
  4. In the app: Settings → AI Providers → Add AI provider → OpenAI, paste the key, and Add AI provider.
OpenRouter API key
  1. Sign up or sign in with OpenRouter.
  2. Save the key, then use Test connection to load OpenRouter's current model catalog. The picker uses the capabilities OpenRouter reports; free models remain available when they support text conversation and the role you chose.
  3. Open OpenRouter's API keys page at openrouter.ai/settings/keys, then create or copy a key.
  4. In the app: Settings → AI Providers → Add AI provider → OpenRouter, paste the key, and Add AI provider.
Together AI API key
  1. Sign up or sign in with Together AI.
  2. Open Together AI's API keys page at api.together.ai/settings/api-keys, then create or copy a key.
  3. In the app: Settings → AI Providers → Add AI provider → Together AI, paste the key, and Add AI provider.
OpenAI-compatible Custom endpoint
  1. Get the base URL — and an API key if it needs one — from any host that speaks the OpenAI API format (most do).
  2. In the app: Settings → AI Providers → Add AI provider → OpenAI-compatible.
  3. Set the Endpoint URL field to that host's base URL, for example https://api.your-provider.com/v1.
  4. Paste the key if there is one, then Add AI provider.

After saving, use Test connection. A backend reports configuration, authentication, model discovery, and assignment readiness separately, so a reachable service can still explain that its credential is missing or that no compatible model is available.

If a provider accepts a request but returns a broken stream, the app reports that response as failed. It does not silently send the prompt a second time.

Choose your models

Only the default model is required. Use your strongest conversation model with reliable tool calling; every other role inherits it until you choose an override.

RoleGood fit
Default modelYour strongest tool-calling model; called the coordinator in project settings.
SummarizerA smaller, fast, inexpensive, or local model.
WorkersCoding models suited to parallel exploration and implementation.

Set device defaults under Settings → AI providers. Project configuration → AI providers follows them until you turn on Override; its coordinator, summarizer, and worker-pool choices then apply only to that project. You can mix backends — for example, a cloud coordinator with a local summarizer.

A local backend loads a model into memory the first time you use it, so a first request can take minutes on a large model. Later ones are quick.

The picker normally hides models known to be incompatible with the selected role. Settings → General → Display → Show all models reveals them with the reason they cannot be selected.

Vision matters for screenshots and images. Without it, the agent can still use page text, console output, structure, and measured geometry, and the app tells you when an attached image cannot be seen.

Prompt caching

Most providers charge less for the part of a prompt they have already seen. Painted Wolf Code marks the stable part of every request so those caches are used: Anthropic and Claude on Amazon Bedrock, OpenAI from gpt-5.6, OpenRouter, Fireworks, LiteLLM routes that report caching, and a warm model on Ollama. There is nothing to configure. Cached reads appear in the session cost breakdown at the provider’s cached rate; a prompt shorter than the provider’s minimum is simply not cached.

Troubleshooting

SymptomCheck
A new key is rejectedConfirm billing or account access, then paste a fresh key.
No models appearCheck the provider status; for a local backend, confirm it is running.
Azure connects but has no modelsUse the deployment name as the model id. The endpoint is the resource root.
Bedrock has no modelsConfirm the region, model access, and an active inference profile.
A backend cannot be removedReassign any device or project model roles that still reference it.

Chat

A normal message starts direct work. A slash command starts a structured workflow with visible stages and controls. Text after the command is the request — /plan add auth or /options pick postgres. If the agent suggests a workflow, it starts only when you choose Start.

Sending and steering

Type a request and press Enter to send. Shift+Enter adds a line. The composer keeps an unsent draft for each chat, including staged attachments, so switching chats or windows does not lose it.

With an empty composer, ↑ and ↓ move through recent prompts. Editing one creates a new turn; it does not change the old message.

Replies update in place as they arrive. Chat follows new output while you are at the latest message. Scroll up or select text to hold your place; chat keeps that reading position as message cards finish loading or older history is added. The button at the bottom returns to the latest messages. Older messages load when you reach the top, and Search results open the matching message, loading more history when needed.

Chat marks each new day, shows the time when a chat picks up after a quiet hour, and shows New above what arrived while you were away. Each finished turn ends with when it finished and how long the agent worked, not counting time spent waiting on you. Hover a message to see when you sent it; every time shows its full date on hover.

If you send while the chat is busy, the message joins that chat’s queue. Open the queue above the composer to reorder waiting messages by drag or arrow keys, edit or remove one, Link with next message so two arrive as one turn, Pause queue to hold everything, Send the queue now, or Send to the current turn to reach the run already in flight.

Waiting messages are recorded before work starts and resume in order after the app restarts.

When the agent needs information, its question appears above the composer. Answer there and the paused turn continues. An approval card also sits above the composer, but it authorizes a specific action — see Approvals. Typing before you answer sends direction with the denial or approval; it does not grant broader access.

When the agent needs a credential, the question uses a protected secret field. The value goes straight to the encrypted credential vault through a dedicated write-only path; it does not become a chat message, workflow variable, event, or tool result. The paused agent receives only the managed reference. Project configuration → Secrets shows the resulting entry and its scope.

To put a credential in a message yourself, select it in the composer and choose Mark as secret. The selected text leaves the draft and comes back as a chip: the agent receives a reference for this task, never the characters you typed. Writing {{secret:…}} into prose does nothing — only the explicit action creates one.

Notices about the app or a project remain visible as you move between screens. A project notice names its project; select the name to open it. Notices tied to one chat stay with that chat.

Project paths in agent replies link to Files when they match an attached file or folder. Files open at the cited line when present; folders are selected in the tree.

The steps behind a reply appear as rows beneath it. A run of related steps folds into one row named for the work — investigating, editing, terminal — with a step count and a short trail of what it touched; open the row to see each step and its output. A step that failed stays in the run, and the row reports how many failed.

When the host removes a recognized credential before storing a message or tool result, chat paints the host-stamped marker and labels the card with how many secrets were removed. A literal [REDACTED] typed by a person is ordinary text; only the host metadata creates a mask, and there is no reveal control because the removed bytes never reached the client.

Files the run changed appear as their own cards, one per file, each showing the whole change rather than every write. A file written more than once names its edit count, and a strip inside the card steps through them — Net is the combined change. When a run touches several files, the cards gather into one row naming how many changed and by how much; open a file there to see its diff, one at a time.

Replies with evidence show a Grounded or Partial chip. Open it to see cited files, pages, and evidence checks. The Source line distinguishes agent citations from observed evidence the app attached, and advisory checks are labeled for review.

Stop, retry, and rewind

Choose Stop once to cancel all work in the chat, including queued messages and workers; it shows Stopping… until the chat is idle. Messages, tool results, and file changes already committed remain, and an unstarted prompt returns to the composer.

A failed turn shows Retry, which sends the last prompt again as a new turn. Re-send on a previous message does the same without removing anything.

Hover or focus a message you sent:

ActionResult
Edit or Rewind from herePreviews removal of that message and everything after it, including their file changes. After confirmation, restores the selected message and attachments to the composer.
Re-sendSends the same text as a new turn.
CopyCopies the text without changing the chat.

Rewind is available while the chat is idle. The preview shows affected files or explains why the selection cannot be undone. Missing file history or changes that cannot be separated from your own edits block the whole rewind. Saved edits are preserved where they can be separated; save or discard unsaved work before trying again. If the files change after review, choose Refresh preview.

Rewind uses retained file history, including changes to project configuration. It records the restored content as new versions. You can also restore one file from its version menu without removing chat messages.

Attachments

Use the paperclip, paste, or drag onto the chat. Add to chat is also available from Files, Search, selected source, and existing artifacts. Both uploads and project references appear as chips before you send.

A large plain-text paste becomes a text attachment automatically. Your draft stays unchanged while its chip uploads, and Send waits until the attachment is ready or removed.

What you addWhat the agent receives
ImagesThe image when the model supports vision; otherwise a notice and a stored artifact.
Source, text, logs, and markupLabeled text in the turn.
PDFs and common office documentsExtracted text. PDF and PPTX files without selectable text show a notice.
Project file, selection, or folderA jailed reference the agent reads from the attached root.
File outside the projectAn uploaded copy; the app does not keep a live link to the original.

Executables, unknown binaries, archives, active SVG images, and folders outside the project are rejected. A turn accepts eight uploaded files, including four images, plus 64 project references.

Screenshots and other visual outputs are durable artifacts. Open Context → Artifacts to browse them. They belong to the project, not to one chat. Open one and choose Reveal in transcript to land on the step that produced it, in the chat that ran it.

Right-click a tile and choose Delete artifact. The confirmation names what still refers to it. Deleting removes the image for good. Places that already showed it keep their reference and read as deleted rather than going blank — an image the agent has already seen cannot be unshown.

For a website or local web app, the agent can open the browser surface and return screenshots as evidence. Ask it to check a route, viewport, or exact visual question. Without model vision it can still verify elements, interactions, and measurements.

Uploaded images and extracted attachment text become part of the model request when the turn needs them. See Security & privacy.

Workers and progress

Longer work has more than a transcript. The rail beside chat shows Progress, Workflows, Git, and Workers.

Progress is the current phase, steps, and context-window use. Worklog is completed steps, findings, and approvals waiting on delegated work. Workers lists delegated tasks — the same workers appear as cards in the chat. Select one for its assignment, transcript, and evidence, or cancel it without stopping the rest of the run.

Focused requests usually stay in one turn. Broad repository work may split into workers with focused assignments; linked files and text attachments stay available without copying the full chat into every worker.

Write workers make changes in private copies. The coordinator checks and lands each set of changes together, so unfinished worker edits do not alter the project.

A worker that needs a decision pauses. The coordinator usually answers and the same worker continues; when it needs you, the chat becomes Needs you and shows the question or approval above the composer.

Commands that need to stay alive run as background jobs. Their cards show recent output and a stop control.

When the window is unfocused, native notifications can tell you that a turn finished, needs input, or needs approval. Configure them under Settings → General → Notifications. Needs you also appears in Mod+K and on Home. Hold Ctrl+Tab to cycle recently visited chats across projects.

Editing

Open Files to browse the project, edit source, and review changes beside the conversation. Citations open at the referenced line; Mod+K finds a file by name; F12 or Mod-click goes to a definition.

Files and tabs

A single click opens a preview tab that the next browsed file can reuse. Editing, saving, or pinning turns it into a regular tab.

The Files tree can create, rename, duplicate, drag, and trash files or folders. Deletion confirms first and uses the operating-system Trash. Files an agent deletes skip the Trash, as they would from a terminal, but Undo in Files brings them back. Hidden and ignored folders, including .git and .paintedwolf/, remain browsable.

Use Expand all or Collapse all from the tree menu or Crossbar. Large expansions prepare in the background while you continue using the editor.

Right-click a path to reveal it in your file manager, copy its path, or add it to chat. To use another editor for citations, set Settings → General → Editor → Open citations in.

Unsaved work is recovered after a restart. Changes from another editor merge into the shared draft; if reconciliation fails, the draft stays available for reload or merge.

Open files follow .editorconfig; saving or externally changing one updates every open file under that project folder.

When you open a file in several windows, edits stay shared while each window keeps its own cursor, selection, scroll position, and undo history. The active file tab has a subtle window color; the same color marks that window’s cursor and selection elsewhere. Brief labels identify moving cursors, and hovering a selection reveals its window label.

Use Open in N windows in the editor footer to see which windows have the file open. The list marks This window and lets you focus another desktop window. Numbers stay fixed while windows remain open. Your theme supplies the colors, including a dedicated main-window color; labels keep windows identifiable when colors are similar.

Keyboard editing

Under Settings → General → Editor → Keyboard, Editing style offers Default and Vim. Default supports familiar Emacs movement, selection, and cut-and-yank commands. Vim adds modal editing, with the current mode and command entry in the editor footer. Both use the same save and undo history.

F6 and Shift+F6 move between app regions. Type a filename prefix while the file tree has focus to find an entry. Tab indents in the editor; enable Tab moves focus to use it for navigation instead. Settings → Keyboard shortcuts lists the current commands and lets you change their bindings.

Use Wrap in the footer to toggle word wrapping. Line numbers are available in View and Editor settings.

Ask from the editor

Select code and press Mod+I to request a focused edit. With no selection, the app uses the enclosing symbol or nearby lines. Unsaved work must be saved or discarded first.

An edit opens a hunk review after it is applied. Accept keeps a hunk; Reject restores it.

Right-click a selection for Explain in context, Give me the gist, Document this, Add test, Rewrite structurally, Rename symbol, or Fix this finding. These focused turns cannot use the shell, network, or MCP. Press Mod+L to attach the selection to a chat without sending it.

Secrets in your source

When a credential has to live in your source, the editor marks it and keeps the model from reading it.

Values the app recognizes are underlined where they sit: a solid underline for one already managed, a dashed underline for one it recognizes but nothing is tracking yet, and a struck wavy line for a capability that no longer works while its value is still screened. The marks are drawn over the code and repeated in the overview strip beside the scrollbar. Nothing is added to the gutter or the status bar.

No pattern list recognizes every credential, which is why you can point at one yourself. Select the value, right-click, and choose Mark as secret. Name it, and the model receives a reference instead of those bytes; the host can resolve that reference inside commands, terminal input, HTTP requests, MCP calls, and configuration file writes (such as .env). If the screen could not cover the whole file, the status bar says so, because that changes what the absence of marks means.

Marking never changes the file. Nothing is rewritten, nothing is saved, and there is no undo to press — the file keeps the value exactly as it was, and you undo the mark by revoking its reference under Project configuration → Secrets. What changes is everywhere else: those exact bytes are now screened on the way out and redacted before anything is written to a transcript, an index, or a log.

Right-click a marked value for Copy reference, Find other uses in this file, or Open in Secrets. On an untracked value the app flagged, Ignore this value in this project… reviews the exact public value, reason, folder and optional expiry before saving plaintext to .paintedwolf/ignores.yaml. Only declare values safe to commit and share. Project settings → Secrets → Ignored values shows the declarations and opens the file for editing or removal. Protected credentials remain protected.

This is not a secrets manager. The app can generate random material and rotate a stored value, but it does not provision credentials in an external system, distribute them to workloads, or replace your key service. For credentials already needed by local work, it keeps the bytes out of the model while the agent uses a bounded reference.

Search and replace

Press Mod+K to open Crossbar. Type to match app actions, recent chats, file names, code, messages, and evidence. Tab moves between result types. Choose Show all results for the full Search stage.

Installed packs can add actions to the same list. Provider-backed sources appear under Sources or behind their shown prefix, and contact their provider only after you enter that source.

Mod+F finds text only in the active view. Find everywhere or Mod+Shift+F carries that query into Search.

The Search stage adds facets, a result timeline, and filters such as kind:code, project:, path:, agent:, before:, and after:. Match case, Whole word, and Regular expression use the same matching rules for code, messages, and evidence. Select a result to open its source.

Results continue loading as you scroll. The count and status show whether the result set is complete or limited. Export broad searches as JSONL or CSV; scan-scoped searches also support SARIF, and incomplete exports are labeled.

Press Mod+Shift+H or choose Replace in project and review the preview before applying. While the selected folders are still being indexed, preparation can be canceled. A limited preview disables Apply all; review and replace individual files, narrow the scope, or refresh the preview. Each file applies only if it still matches the preview revision; a completed batch can be reverted from its receipt. Project-wide rename from F2 uses the same path.

When the agent edits

The Files tree follows files and folders as the agent or another editor creates, moves, or removes them. Worker changes stay in their private workspace until the coordinator lands them in the project.

While a chat works, the editor shows what it read in a muted agent color and outlines changes that have not landed, with a label saying why — about to edit, waiting for your approval, or a worker draft ready to land. The marks clear when the turn ends. Choose what they show under Settings → General → Editor → Agent activity.

The agent reads the shared editor draft, including unsaved changes. Its edits merge into that document and save it, preserving compatible changes from you and other windows. If the lines it read have changed, the agent must read them again before editing. Commands and tests use files saved on disk. Agents can also inspect retained ledger versions, diff across revisions, or restore earlier file states directly.

The gutter marks scanner findings and the turn that produced changed lines. F8 and Shift+F8 walk the findings in the file.

Review and verify

Switch from Files to Review for changed files and diffs. Choose Working changes, This turn, Everything in this chat, a saved pin, or Since last commit when Git is available.

Review keeps your changes, AI changes, and changes from outside the app in one list, and each row names who contributed it — You, the chat that made the change, Command, or Outside app. Choose Pin current state to record a comparison point you can return to later; the picker keeps your pins alongside the other scopes, and Review pins work even where Git does not.

Choose Walk to step through the chat’s timeline, grouped by turn. Each step opens the recorded before-and-after change in the ordinary file tab and, for agent work, highlights the matching step in chat. Review remains a current changed-file list while Walk moves through history.

The version menu in the editor lets you browse a file’s retained versions, including versions from worker workspaces. History follows the logical file when it is moved or renamed. Historical versions are read-only; choose Current to return to the editable file without replacing an unsaved draft. Restore applies a selected file version while keeping the chat. To undo a prompt and the work after it, use rewind.

While Review is open, the file briefing follows the active text or diff tab. It shows a structural overview immediately, then adds Purpose, Structure, and Key behavior. Select its file name, declarations, or source references to open the file or exact line. The briefing stays pinned to the revision it describes and is marked stale when the file changes.

Painted Wolf Code has two other review moments besides the finished diff:

Project test command. Open Project configuration → Tests. The app may detect a likely command from the repository, but it never applies that suggestion silently. The command is normally stored in .paintedwolf/verify.yaml — commit it when the team should share the same gate. After an agent edits your files, this command has to pass before the work is treated as finished. Until a command is saved, a successful check the assistant ran on the current files can satisfy the same gate.

A check that never reached a verdict is unverifiable, not a failure — usually the sandbox stopped the command. Approve the access it needs, or run the check yourself.

Edit review. Open Project configuration → Edit review and add a path glob such as infra/** — a folder name on its own covers everything under it. Matching edits pause before disk; everything else continues. Edit review does not make the matched area writable. Containment and approvals still apply underneath it.

Plans

Use normal chat for direct work. Use /plan when you want the agent to research first, write down the intended change, and wait for your approval before building it.

Running /plan

The workflow moves through a visible sequence:

StageWhat happens
RequestThe workflow opens by asking what you want it to plan.
ResearchIt reads the project and, when allowed, the web.
DraftIt writes a Blueprint under .paintedwolf/blueprints/.
ApprovalThe Blueprint opens for preview or editing. Request changes, send it for a critique pass, or approve it.
CritiqueOptional. A reviewer reads the plan and returns a verdict, then the Blueprint comes back for your approval.
BuildApproval starts the implementation workflow against that Blueprint.
DoneThe run closes with its evidence and remaining follow-ups.

Approval is a button in the review workspace or review bar. A sentence in chat does not approve the Blueprint.

Reviewing a Blueprint

The review workspace previews or edits the Markdown. Request changes sends direction through chat, Run critique adds another review pass, and Approve starts the build.

A Blueprint opens with a short YAML block above the headings, holding its status, title, and a research_depth of none, light, or thorough. Keep the block when you edit — without it the Blueprint reads as incomplete.

The review bar stays above the composer while approval is waiting, so closing the workspace does not hide the decision.

The Blueprints library

Context → Blueprints lists the project’s durable plan files under .paintedwolf/blueprints/. Edit, rename, rerun, or commit one when it should travel with the repository.

Starting another catalog workflow replaces the active structured run and keeps its transcript and Blueprint. /exit — or /stop — leaves the current structured workflow and returns the chat to ambient work.

The Workflows tab can pause, resume, advance, review, exit, or download a report. Type / to browse every workflow available in the current project. The installed catalog is under Settings; authoring your own is in the SDK.

Git

The Git panel uses the same repository and hardened Git engine as the agent. It reads and writes one repository at a time, so status, commits, and branch actions always have an explicit scope.

Choosing a repository

A project may contain several roots in one repository or roots from several repositories. The scope selector follows the chat’s active root by default. Pin a repository when you want the panel to stay there.

All repositories shows branch, changed-file count, and ahead/behind state for every repository in the project. It is an overview only; choose one repository before a write action. A folder outside Git offers Initialize repository.

Reviewing and committing

The changed-files list opens project files in Files and shows paths elsewhere in the same repository without granting the project access to them.

Review the changes, write a message, and choose Commit. Commit stages every change in the selected repository and creates one commit. The message assistant can draft from the diff; you remain the author of the commit action. A commit never spans repositories.

Commits made here are not signed — the app holds no signing keys. Sign from your own terminal when a repository requires it.

Use Stash to set all current changes aside and Discard to remove them. Discard confirms first. Line-by-line review lives in Files → Review.

Branches and remotes

Open the branch picker to switch branches or create one. Pull fast-forwards from the configured upstream. Push in the Git panel immediately publishes the current branch as a human action. Pushes attempted by the agent use the normal approval policy.

Repository-owned configuration cannot replace the app’s Git binary, install hooks into these operations, or supply external diff and pager programs. Credentials remain in the normal SSH agent, credential helper, or provider flow outside the agent sandbox.

Work on a branch

Choose Work on a branch… to bind the chat to a new branch in an app-owned worktree outside the project folder. That chat’s agent, commands, Files view, and Git panel all use the worktree; other chats keep using the project checkout.

Commit the work in the worktree before landing it. Land merges those commits into the branch the chat started from when the project checkout is clean and still on that branch. A conflict aborts the merge and leaves the project checkout unchanged.

Unbind removes the extra checkout and keeps its branch and commits. A missing worktree never falls back silently to the project folder. A bound chat must be unbound before that chat can be deleted.

Approvals

Most file edits, commands, and Git work happen without interruption. Painted Wolf Code asks when an action would be hard to undo, cross a boundary, or send something sensitive away from your machine.

Prompts stay rare on purpose, so the one that matters still gets read. Work the app can watch or undo runs quietly; work it can’t asks. Strict asks more often but never changes what an answer means.

Approval cards appear above the composer. Each names the action, who requested it, and what it affects. A card for extra command access appears before the command starts.

Answering a card

  • Enter takes the recommended action; Escape says no. Keyboard shortcuts 1 through 4 select ladder rungs directly: 1 for Once, 2 for 1 Day, 3 for This chat, and 4 for Project (or Device).
  • Type before answering to send direction such as “use the staging bucket instead.” Direction is not authorization, and the replacement action goes through the same checks.
  • In Light and Balanced postures, the primary action is chosen strictly by the durability of the action: durable subjects like package installations, write roots, read paths, and socket services face Project (7 days); subjects that end with the chat, like direct network access, local secrets, and running outside the sandbox, face Allow for this chat. In Strict posture, cards recommend Allow once.
  • Open the caret beside the main action when you want a different scope: Allow once for only the immediate action, or longer-lived access for this project or device. Available scopes depend on the action.

A card waits up to a day for an answer — overnight included. Left unanswered, the action is declined.

Remembered choices appear under Settings → Approvals → Saved approvals and can be revoked there. The conversation also shows Revoke while its grant remains active. A changed action, destination, credential, or tool definition may ask again.

How often it asks

Choose a posture under Settings → Approvals, or a stricter one under Project configuration → Approvals:

PostureWhat it adds
LightOnly mandatory checks: outbound credentials, changed tools, critical detections, work the app cannot observe, and reading or writing a folder outside the project. Local servers and loopback connections run silently, and so does a key file a command asks to read.
Balanced (default)Sensitive locations outside the project — writes to credential files and any use of key files ask wherever they are; values read from a credential file are tracked and ask when they leave — unconfigured destinations once the chat has read outside content, high-severity detections, local servers on privileged ports, and connecting to pre-existing local host services. Local test servers and connections to them run silently.
StrictBuilt-in writes to temporary and cache folders, first contact with a host, MCP use until allowed, known and remote package executions, outbound work after a credential file was read, and explicit approval for every local server listener or connection.

A project may require a stricter posture, never a looser one. Turning device approval checks off under Settings → Advanced → Approvals does not remove the sandbox, hard denials, or project requirements, but every request to reach past the sandbox is then granted without a card.

While approval checks are on, some actions always ask, including disabling an audit control, granting lasting access, irreversible cloud destruction, credential-shaped command arguments, and direct disk writes.

Approving a path grants only the access printed on the card, for the displayed scope, and read access never grants writes. Every posture asks before the agent reads or writes a folder outside the project; only the app’s own settings folder is refused without a card. Approving a read of an outside folder covers that folder and everything under it, and approving a read of an outside file covers the folder that holds it, except for a file directly in your home folder or a sensitive location, which stays exact. When a command writes inside another repository, the card names the whole repository, so one approval covers every folder a build writes there; outside a repository it names the folder that holds the file. Your home folder and the filesystem root are never offered.

A broad grant such as ~/.config or a whole repository keeps its protections inside it: the app’s own settings folder stays refused, and credential stores and key files such as ~/.config/gh or ~/.ssh still ask for their own approval. The card lists the files it leaves out. A write folder or host resource remembered for this device covers that folder or resource on later projects, including a host resource’s catalogued local route. A local-service socket is the exact socket on the card, not its folder and not everything the service can do. A dev server or container the agent starts can be previewed without a prompt. From Balanced up, connecting to a service that was already running, or to a server reachable from your network, asks. Revoking a remembered local-service or direct-network grant applies to the next process start.

Project Git remotes configured in .git/config and official package manager registries (npm, PyPI, crates.io, Homebrew, etc.) are recognized configuration sources, avoiding cold destination prompts. Once a chat has read outside content, Balanced also asks before a command connects somewhere you did not configure. Package manager commands (npm install, pip install, cargo add, brew install) and remote package executions (npx, uvx) are recognized by package coordinate. Approving a package coordinate covers all subsequent executions and flag variations of that package under the reviewed manager for the project. In Balanced posture, known packages older than 7 days run without interruption. After a chat reads a web page or MCP result, later cards label it External content. The label is context; the checks above still apply.

For work on running processes, the agent can request inspection or signaling access. A command can also request Run outside the command sandbox, including for setuid programs and passwordless sudo. That approval removes the command’s filesystem, network, and process restrictions, including the protection of the app’s own settings. Allow for this chat covers further uses of that access, including different commands; detections and your own approval rules still ask. Allow once covers one action. Revoking access prevents future use but does not stop a running command; its warning remains until it exits.

Credentials on their way out

Before model requests, searches, page fetches, and MCP calls leave your machine, the app screens them for credential-shaped values. Nothing has been sent when the card appears. You can Send redacted, Send unchanged, or No. Command and terminal arguments cannot be rewritten safely; on those cards Send redacted is unavailable and the card says why. This check runs at every posture. Turning device approval checks off turns it off as well: with no card to answer, the value leaves as written.

Values you stored yourself are stricter. These are answers to a protected question, values you marked in a message or chose to Protect, and values you added in Project configuration. Each new destination asks at every posture, even with approval checks off, and the value leaves only while you have unlocked the chat. The first approval in a locked chat asks you to confirm with Touch ID, Windows Hello, or your device password, which unlocks that chat; later destinations need only a click. The unlock ends after 15 minutes without use, after 4 hours, or when your computer locks or sleeps. A key icon in the composer shows an unlocked chat; select it to lock right away. On Windows, locking the computer does not end it yet.

Send redacted changes only the outbound copy reviewed on that card. Its caret can also record Keep redacting for this project or device: a standing instruction to strip those exact bytes from later sends. That is the opposite of permission to disclose them, so it survives even with approval checks off.

Separately, the host removes recognized secret bytes before it stores transcript, search, evidence, diagnostics, or log content. Chat shows a host-stamped mask and a short explanation for those durable removals; disabling approval cards does not turn that storage rule off.

Strict adds a broader safeguard: after a chat reads a credential file such as .env, it asks before that chat sends anything out, even when no recognizable credential appears in the outgoing text. Committed templates — .env.example and friends — hold placeholders, not credentials, so reading one does not trip this and the app can edit them.

You can also keep known credentials out of model context. In Files, right-click a value and choose Mark as secret: the model receives a reference, while the host resolves the bytes only inside a supported outbound execution copy or configuration file write and screens the real destination before dispatch. Marking does not change the file — see Secrets in your source.

Actions you can’t take back

Detection packs read the command line, its arguments, and structured tool calls before an action runs, and a mediated connection’s destination before it is dialled. They recognize consequential operations by their exact identity — emptying a storage bucket, deleting a Kubernetes namespace or a Terraform-managed resource, disabling an audit trail, minting or reading a credential, detaching an account from its organization, publishing a release — across cloud command lines, the structured cloud calls an MCP tool makes, and the local shell.

Severity and your posture decide when a match asks: critical at every posture, high from Balanced, medium at Strict. Work whose every target the app can prove sits inside your project stays quiet. A detection can add a prompt, never remove one, and a miss is never read as proof an action is safe — containment and the approval floor decide on their own.

Manage packs under Settings → Approvals → Detections; inactive, shadowed, or disabled rules stay listed with reasons, so a rule that never ran cannot look like one that ran and found nothing. Authoring and the approval ledger live in the product repository: detection packs and authorization.

Settings

Device and project

Most device-wide setup lives in Settings. Choices for only the open project live in Project configuration. Device settings remain the defaults. Shared team behavior belongs in committed project customization.

A repository can contribute guidance, such as AGENTS.md and project skills, or capability, such as MCP, extensions, and settings overlays. Guidance does not grant access. Capability waits for your project-specific review, and a later repository change may require review again.

Project configuration → Trust lists what the open project supplies to the agent, grouped by whether it steers the agent, replaces app defaults, or suggests device installs. Every row starts on and can be switched off. Use the Trust chip to open the change list and inspect file diffs. Opening Trust clears its unread indicator while keeping the comparison available.

A project’s approval rules can only make things stricter. The one thing it can relax is a detection pack, which it may switch off for its own tree. Disable a repository-contributed surface device-wide under Settings → Advanced → Project trust.

Appearance

Settings → General → Display sets whether the app matches your system appearance or stays light or dark, and which theme each one uses. Your appearance choice belongs to this device. A project can offer a theme, but opening one never changes how the app looks. If a chosen theme is unavailable, the app names it, uses its stock theme, and keeps your choice for when it returns.

First-time tips appear with a view when it is ready. Choose Got it to dismiss one, or turn off Show first-time tips in this section.

Message times shows when you sent each message on hover, or always.

Web research

Web research runs from your device. Open Settings → Web research. The master Allow web research switch removes outbound search, page, and research-worker tools when it is off; the agent cannot turn them back on for itself.

The Providers tab starts with keyless Direct search. Remove it to use only providers you add, or choose Add provider for a supported search service or a SearXNG endpoint you operate. Searches fill a local index so repeat topics stay fast; Clear under Local index rebuilds it without removing chats or credentials.

The site or search provider receives the request from your network. See Security & privacy for the data path.

MCP providers

Add and manage MCP providers under Settings → MCP providers. The list and add picker group them as Local or Web / hosted. Secrets stay in device configuration.

Choose Add provider and pick a recipe, Custom local, or Custom web. Local providers run a command or connect to a loopback URL such as http://127.0.0.1:…. Web providers connect to https://… and use the token placement or Sign in method the provider supports.

Enable the provider, then choose Test connection. Its tools work automatically in chats whose tool profile allows them: small sets load directly, while larger sets are found as needed. Turn on Always load tool definitions when every model call should receive that provider’s tools. A changed remote tool definition asks before use.

A repository may include .paintedwolf/mcp.yaml, but Project configuration shows Local providers only and limits project entries to unauthenticated loopback URLs. They cannot start a program, send credentials, or expand a restricted tool profile. Only providers enabled in device settings register callable agent tools.

Cost and budgets

You pay providers directly. A cost chip under the project name opens the session breakdown. Context → Cost shows project totals and CSV export, including model work outside a chat and an aggregate for deleted or expired chats. Estimates are marked partial when some usage could not be priced or fully measured. Tracking is on by default under Settings → Cost.

A per-session spend ceiling is off until you set one — device default under Settings → Advanced → Budgets, or a project limit under Context → Cost. When a session reaches the ceiling, new prompts and workers do not start. A running turn finishes what is in flight unless you turn that soft landing off. If usage cannot be priced, the ceiling is not enforced and the app says so.

Mix models by role to keep the bill down: the coordinator needs your strongest tool-calling model; the summarizer and worker pool usually do not. See Providers.

The local decision model

Bialy, our tuned local engine built on Convai Innovations' Laya, reads each request before your provider does and prepares the turn. It loads what the work needs: the tools the request will call, and the best-fitting skill, read ahead of time. It prunes the rest: tool definitions, guidance, and skills the request doesn’t need stay out of the prompt. It reranks code: when the agent summarizes files or reads its repository map, the most relevant files and definitions come first. The agent has what it needs from the first call, so turns take fewer model calls and finish sooner.

It only chooses among what the chat already allows. It never adds a tool the chat couldn’t use, changes a permission, or answers an approval. It cuts only what it is confident the request doesn’t need, and anything it cut, the agent can still ask for. It runs on your Mac’s GPU; your request never leaves the machine for this step.

It ships inside the app and needs nothing from the network. If it can’t answer, a readiness card says so. Everything still works; the agent just reads a little more and finds a little less on its own.

Extensions

Settings → Extensions installs and updates extension packs for this device. Context → Extensions shows the active catalog and lets you turn off eligible units for the current project.

Packs can add skills, workflows, Crossbar commands, menus, shortcuts, themes, and explicit provider-backed search sources. Their actions still use the app’s input, permission, and result handling.

Type / in a chat to browse the built-in workflows, or start one by name:

Start it withWhat it does
/bugbashHunt bugs in parallel, choose what to fix, then verify
/optionsResearch the codebase, then debate the decision with a neutral skeptic
/planResearch, expand, approve, then build. Optional critique from approve.
/reconCoordinated codebase orientation.
/security-surveySurvey a project against its threat model.
Always onThe default ambient workflow attached to every chat session; direct build, no plan gate.

Install from Git or from a local authoring folder. Enable or disable individual packs; the built-in suite stays enabled. Repositories can suggest device installs; each suggestion waits for your review.

Changes apply immediately. Clearing Extension packages under Settings → Advanced → Cache removes downloaded copies but keeps device pack choices and project unit disables.

For a procedure or team convention, add a folder containing SKILL.md under .paintedwolf/skills/ or .agents/skills/. A skill is guidance, not a script or an access grant. Domain-specific procedures (such as cloud platforms, specialized data stores, media tools, or browser design) install as extension packs, keeping your core chat prompts focused. Commit it when the team should share it.

Which installed units a project may disable is fixed by kind. See Unit kind properties. Authoring custom workflows, rules, and packs is in the SDK. Put provider and MCP credentials in their device settings, and managed project values under Project configuration → Secrets; never put credentials in configuration you commit.

Host resources

Settings → Advanced → Host resources lists detected command-line tools and local services. Write agents can see which are present; that is not permission to use them. Choose Refresh after changing one, then leave its normal policy, Ask before use, or Block it. This can add a check or denial; it never bypasses containment.

Security & privacy

Painted Wolf Code collects no telemetry: no analytics, crash reporting, usage beacons, account, or device identifier.

What can leave your machine

ActivityDestination
Prompts and code contextThe AI provider configured for the chat.
Web researchSearch providers and sites contacted directly from your connection.
Agent HTTP requestsA host the agent names when a turn calls an API, webhook, or local service.
MCP toolsThe provider endpoint and its sign-in host.
Extension installation or updatesThe Git remote you chose.
App update checksThe static release manifest on Painted Wolf’s download domain.
Optional catalogsThe configured model, pricing, or browser download source.

Dependency advisories come from the public OSV database; your dependency list stays local. Before a command installs or runs a named package, the app may look that one package up on a public package index to put its identity and age on the approval card. Any provider or website you contact can see your IP address and handles the request under its own terms.

Model requests, web research, agent HTTP requests, and MCP calls screen their content for credentials before sending. With approval checks enabled, a recognized value pauses the send for a decision at every posture — see Credentials on their way out.

An app update check is one static-file request. It carries no account or device identifier and no usage data. New releases reach devices gradually over their first two days; the timing comes from a random draw made on your device, and Check now always offers the newest version. Turning automatic checks off stops the request.

Uploaded images and extracted attachment text become part of the model request when the turn needs them.

What stays local

Chats, uploaded attachment copies, settings, project records, keys, and local indexes stay on your device. The local decision model runs here too: what it reads to trim a turn is never sent anywhere. Keys are stored outside project folders and never pass through a Painted Wolf service.

Provider keys, MCP sign-ins, and managed-secret values share one encrypted credential vault in the app’s configuration folder — owner-only, outside every project folder, and excluded from backups, restores, and diagnostics bundles. On macOS the key that opens it is a device-only Keychain item, so there is no app password to remember. The database beside it keeps only value-free records: what a secret is for, its scope, version, and when it was used or revealed. Ordinary API reads never return a value. On a supported packaged build, Reveal value requires a fresh operating-system user-presence check, shows the value briefly in the active native view, and records the event without recording the value or proof. Replaced values remain protected matching evidence until the project is deleted.

Native file tools do not extend past attached project folders and temporary scratch locations without an explicit approval. On macOS, commands start in an operating-system sandbox: writes are limited to attached project roots, temporary or cache locations, and paths you approve. Anything else, including credential stores and SSH keys, needs an approval naming the exact path. The sandbox keeps the app’s own settings and provider keys out of reach. Linux source builds have no kernel sandbox: containment there is the approval layer only, so every command asks. There is no Windows installer in v1.

A sandboxed command’s connections pass through the app, which records each destination.

With your approval, a command can reach past the sandbox: direct network access, a local service such as Docker (which then acts with its own permissions), or running outside the sandbox entirely, including passwordless sudo. A command outside the sandbox has the access of your OS account, including the app’s own settings. Settings → Approvals controls these requests; see Approvals.

Containment reduces risk; it does not prove a command is safe or protect an external account from every mistake. The threat model and outbound inventory live in the product repository: security and privacy.

Scanners

Scanning is organized around three jobs.

JobWhat it looks forDefault
Static analysisInsecure patterns in your codeOpenGrep
DependenciesKnown CVEs in the packages you depend onosv-scalibr
SecretsCredentials committed to the repositoryGitleaks

Exactly one tool holds each job. Context → Security opens on the project’s findings: Open lists what scanners report that you have not ignored, and All adds findings that were fixed, ignored, or are no longer reported. Filter, sort, and open a finding for details. Select findings to Fix with agent, which drafts a chat message for you to send, or Ignore… them with a reason and an expiry. Ignores are saved in the findings section of .paintedwolf/ignores.yaml, so they can be reviewed and committed like any other change. Export the current view as SARIF or OpenVEX. Findings also appear beside affected editor lines. Results stay on your machine. Fix this finding asks for a targeted, reviewable edit.

Install a supported scanner and choose it under Settings → Security scanners to replace a built-in job with a tool you already trust:

ScannerFindsInstall
Trivy — dependencies
Scans lockfiles and manifests for known CVEs. One binary also covers secrets and IaC — add those separately.
Dependenciesbrew install trivyDocs
OSV-Scanner
Google's OSV CLI — the same advisory database as the built-in OSV-Scalibr, a different tool around it. Reads lockfiles; writes the report to stdout.
Dependenciesbrew install osv-scannerDocs
Grype
Anchore's vulnerability scanner. Accepts directories or SBOMs.
Dependenciesbrew install anchore/grype/grypeDocs
OpenGrep — your rules
The same engine as the built-in code scanner, running your rules from .opengrep/ instead of ours. Create that directory before selecting this.
Static analysisSee the project's siteDocs
Semgrep — code
Reads your rules from .semgrep/. Registry rulesets (p/default and friends) work if you point --config at them.
Static analysisbrew install semgrepDocs
gosec — Go
Go-only. Receives the exact host-selected source path for each invocation.
Static analysisbrew install gosecDocs
Gitleaks
The same engine as the built-in secret scanner, run as your own install with upstream's rules and your .gitleaks.toml. Writes its report to a file rather than stdout, so the host supplies the path.
Secretsbrew install gitleaksDocs
Trivy — secrets
Same trivy binary as the dependency scanner, pointed at its secret rules.
Secretsbrew install trivyDocs

Some names appear in both the defaults table and the catalog. The built-in code and secret scanners are OpenGrep and Gitleaks running inside the app against our rules; the catalog rows are your copies of those tools, running your rules and your configuration. Picking one trades the curated ruleset for full control of it.

A catalog or custom scanner is a program you installed and runs with your account. The commands we ship read rules from the project: OpenGrep from .opengrep/, Semgrep from .semgrep/. Create that directory before you select the row. A scanner that cannot load its rules is a failed scan, not a clean one.

Opening a project scans nothing. As work happens, every selected scanner re-checks the files that changed once a burst of edits settles, including changes workers land. A full scan of the whole project runs only when you start one in Context → Security, or when an agent or workflow asks for one; until then, an empty findings list speaks only for the files that have been scanned. Scans run at low priority and chat never waits on them. You can turn scanning off with Use Security scanners, which also hides Context → Security.

Custom SARIF tools and the supply-chain contract live in the product repository: scan-supply-chain.

Outbound credential screening, managed references, and transcript redaction are separate from the secrets scanner and cannot be turned off from scanner settings. See Approvals, Secrets in your source, and Secrets a project tracks.

Ignored public values

The secrets section of .paintedwolf/ignores.yaml is the single source of persistent exceptions for exact public examples and fixture values. Use Ignore this value in this project… from an untracked editor highlight or a live secret detection in chat, or edit the file directly. Security continues to manage scanner predicates in the same file’s findings section.

Valid, unexpired declarations apply when the project’s Scanning and ignores trust surface is enabled. There is no separate per-entry acceptance step. Edit the file to change an exception; remove its entry to stop applying it. Values are plaintext and must be safe to commit. Persistent classifier exceptions are not stored in Saved approvals.

Project configuration → Secrets → Ignored values shows active, expired, protected and trust-disabled declarations. Select an entry to review its exact value and open the source file. The compact view switch retains your place in both Secrets lists.

Saving an ignore does not approve a held request; that request still needs its own decision.

The file requires integer version: 1 and overlay_format: 3 in .paintedwolf/overlay.yaml. Existing empty, unversioned, or unsupported ignore documents are refused without modification. Keep any existing findings entries and add exact public values under secrets:

version: 1
findings: []
secrets:
  - value: "an-exact-public-fixture-value"
    reason: Published example, never used as a credential
    expires: 2027-01-01

Whitespace is significant. expires is optional and stops the exception at midnight UTC on that date. There are no regex, prefix, or path exceptions for secret values.

With the project’s Scanning and ignores trust surface enabled, declared values stop ordinary secret warnings and masking in project-attributed work, including scanner findings with exact value evidence. Protected credentials always remain protected. Scanner finding ignores alone do not disable runtime secret screening, and previously redacted history cannot be reconstructed. The ignore file has the same agent-write approval protection as the other policy files in .paintedwolf; reading it does not need additional approval.

Backups and reports

There is no support contract. Reports are welcome; a reply, a fix, and a timeline are not guaranteed.

Settings → Advanced → Data can Back up now (a zip that excludes API keys) and Restore…. Restoring on the same device leaves the credential vault in place; a fresh installation needs those secrets entered again. Restore replaces chats, projects, and durable settings after saving a recovery copy.

Settings → Advanced → Cache clears named scratch-data buckets without removing chats, credentials, or projects.

Settings → Advanced → Diagnostics offers a scrubbed diagnostics bundle that stays local until you share it. From a shell, pw logs opens the same local capture browser. To file a report, open Settings → General → About → Report a bug…. Nothing is sent automatically.

How to route a report: the product repository’s REPORTING.md. For a security vulnerability, use the private security reporting instructions.