Documentation

How to use pm7Code

pm7Code is a macOS workspace around the coding agent of your choice. This guide covers the agents it drives, how it talks to them, the layered prompt system, interactive questions, the background Git Service, and the rest of the workspace — so you can treat it as the reference when you need one.

Agents

Bring your own agent, hand sessions over

pm7Code does not ship its own model. You pick a coding agent per topic, and pm7Code is the workspace around it. Six native agents are supported, and you can switch between them or hand a running session over to a different one at any time. New topics default to pm7 unless you pick another agent.

AgentRuntime
pm7Same engine as Pi, plus a project-rules harness that refuses violating tool calls
PiMulti-provider coding agent, defaults to Google Gemini
Claude CodeAnthropic, via the Claude Agent SDK
OpenAI CodexOpenAI's Codex
CursorCursor's agent over ACP (Agent Client Protocol)
GrokxAI's Grok over ACP

One agent per topic

Each topic runs a single agent at a time. The topic, its transcript, prompts, and history live inside the project, not inside the agent.

Handover keeps identity

Switching agents mid-session keeps the same topic and the same conversation. Only the agent flips; the prior transcript is replayed to the new agent as a primer.

Guest turn

Prefix a message with @pm7, @pi, @claude, @codex, @cursor, or @grok to send that one turn to another agent without switching the topic's agent. Add + (@claude+) for the full session; without it, the guest sees recent context only.

Agents

Local gateway (Settings → Agents → General)

In Settings → Agents → General, the Local gateway section routes agent traffic through a gateway on the machine that runs the agents — for example CLIProxyAPI — instead of connecting straight to each vendor. That can pool several subscription accounts behind one endpoint while pm7Code stays your workspace.

Address, key, and per-agent toggles

Set the gateway address (for example http://127.0.0.1:8317) and the gateway key — the gateway's own secret, not a vendor API key. Agents stay on the direct route until both are filled in. Then turn on Route Claude, Route Codex, and/or Route Grok separately. Changes apply to new sessions only; a session already running keeps its original path.

Machine-owned settings

These settings belong to the machine that runs the agent, not to your account. One always-on machine can keep them for all machines; others fetch from there. The Where these settings liveblock shows which machine is main, which follows, or whether nothing keeps them yet. On a standalone machine you can adopt so that machine keeps the settings you are using. The desktop app and WebApp use the same engine lookup for status, read, merge, and adopt, so they cannot disagree about who keeps them. If the keeper machine is unreachable, that is an error — not “nobody keeps them,” which would wrongly offer adopt and create a second keeper. Two machines both claiming main is reported as a conflict, not silently resolved by list order. On the desktop, the first load can still run before the configured server list exists; opening Settings → Agents → General asks the keeper again on the same path as load, then re-fills gateway and other engine-owned fields from that answer together with the heading block. If the keeper did not answer, the form shows a warning and Save refuses to write engine-owned values — saving would push this device's stale copy to every machine. Save also refuses when the keeper answered after the screen was filled in (close Settings and reopen to edit its values). Account sync never includes engine-owned keys while a keeper is active.

Gateway key from config

Optionally enable Take it from the gateway's own configuration on the agent machine. A key typed above wins over the config. Check on the agent machine reports whether a key was found in config — not whether the gateway is reachable.

Route Claude

While on, Claude CLI prefers the gateway over your claude.ai login, which disables claude.ai connectors for those sessions.

Route Codex

Passed as command-line overrides so your ~/.codex/config.toml stays untouched.

Route Grok

Grok only accepts a redirect for a model it does not already know. pm7Code routes models under an alias that drops the vendor name — for example grok-4.6 becomes pm7gw-4-6. Add a matching alias in the gateway for every Grok model you use.

Usage collection

Collect usage for the Gateway viewreads the gateway's usage queue. Nothing is collected until you switch this on. The queue is emptied by whoever reads it, so pm7-Code becomes its only reader when collection is on. Set a separate Management key(not the gateway key) — the gateway's management secret for usage and configuration.

What the gateway does not cover

The management panel covers agent sessions, not every model call pm7-Code makes: summaries and tools that start their own CLI keep using the direct route.

Gateway view

The Gateway view is separate from pm7-Code Usage. Usage recomputes token cost from session transcripts; Gateway counts what a gateway actually served on the machine that collects usage. Open it from the usage block in the sidebar footer — choose Gateway in that menu (not pm7-Code Usage). It opens as a draggable, resizable dialog over the workspace (same in desktop and WebApp), with Refresh and Close in the footer.

Which machine is shown

With configured engines, desktop and WebApp both ask those engines — not the local Electron shell — and pick one stable source: the engine that has been collecting gateway usage the longest (not the period you selected). Numbers are never summed across engines. If another configured engine fails to answer, or another engine also collects gateway traffic, a warning says that history is not included. With no configured engines, the desktop may fall back to its local shell; the WebApp reports none.

What it shows

Pick Today, 7 days, or 30 days. Serious and warning alerts about collector health (lost or rejected records, interrupted fetches, clock skew, and similar) appear above the figures. Totals highlight requests, with failures, input and output tokens, and median latency alongside. Breakdowns per account and per model include request-share meters; a table lists recent requests. The subtitle names the host and period.

Coverage caveats

Counts are requests observed at this gateway, not everything pm7-Code does. Another client sharing the same gateway is counted here too; traffic that bypasses the gateway is not. The usage queue is emptied by whoever reads it first, so only one collector should be enabled when you rely on these numbers.

Claude Code default reasoning effort

In Settings → Agents → Claude Code, Default reasoning effort sets the baseline for new Claude Code sessions on the machine that runs agents. Leave it empty for Use Claude Code default, or pick Low, Medium, High, or Extra High. Like other engine-owned agent settings, it is stored on the keeper machine and follows the same save-safety rules as gateway and install settings — not in your account sync while a keeper is active.

Precedence

Session override wins, then the per-model choice in the model picker, then this Settings default, then Claude Code's own default. An explicit per-model None still omits effort on spawn. In the picker, Use default clears the per-model choice so the Settings default applies again.

Where it applies

New and restarted Claude Code sessions use the same resolver for spawn and for the agent pill in CView — what you set is what runs, not a separate client copy.

Agents

Install Status and CLI binary (Settings → Agents)

Playwright (Agent Browser) and Remotion install checks no longer run on the machine where your window lives. They ask the engine on each machine that runs agents — the same split the WebApp needs, because the old desktop-only IPC bridges never existed there.

Install Status — one row per machine

In Settings → Agents → Agent Browser or Remotion, the Install Status block lists every configured machine. Each row shows CLI, npm, and browser-or-runtime badges. Use Check status on one row for a deep check (including the slow browser-runtime inspection), or Check all machines for a shallow overview across machines — not deep on every row. Nothing runs automatically when you open the tab; one round is too expensive to fire unasked.

Reachable vs not checked vs missing

Three facts stay separate: whether the engine is reachable, whether you have measured yet, and whether the tool is installed. An unreachable machine shows an error — never “not installed.” Until you check, the row says not checked yet.

Install on the agent machine

Install actions run on that engine along the same PATH the agent CLIs use. Failures are readable sentences (missing binary, timeouts) instead of raw Node spawn errors. A deep check can overturn a shallow “Missing” on the browser runtime when the CLI reports it is actually present.

CLI binary on each agent tab

On an agent tab (for example Codex), the CLI binary card shows which codex (or other agent binary) is on each machine that runs agents. Check version asks every engine; update runs on the machine you pick, not on the window machine. The same three-way split applies: engine reachable, agent known to that engine, binary installed with version. This card shares data with Settings → Agents → Versions so both views stay in sync.

Assistant

A second session beside your work

The right sidebar sits next to the workspace and shows one of six panes, chosen from the header: the Assistant — a full CView and Command Center bound to a single window-tab — the Browser (BView), Files, Todo, Note, or Trace. The header groups the choice: Assistant with General, Project, Topic, and Tab sub-modes, plus separate Browser, Files, Todo, Note, and Trace buttons. Only one pane is visible at a time; the others stay mounted so their state survives when you switch. Older clients that do not know the note view fall back to Assistant, the same way unknown files did earlier.

The Assistant is not a seventh native agent. It is an ordinary topic session parked in its own column so you can keep a helper conversation open while you work in the main view.

General

The session you assign with Use as Assistant — the assistant for pm7-Code as a whole, independent of whichever topic is active in the main view. Right-click a topic in the sidebar and choose Use as Assistant; choose Stop Using as Assistant to clear it. On every non-silent turn it receives a compact [General Assistant]context block (Prompt Context, source Active): a source map of Settings surfaces — prompts, protocols, skills, slash commands, app themes, colors, agents, and other Settings screens — not a dump of secrets. Topic, Project, and Tab assistants take priority over General (Topic > Project > Tab > General); a bound assistant never holds two roles at once. Cmd/Ctrl-click the Assistant splitter to equalize the main column and Assistant widths.

Project

Follows the active project in the main view and shows that project's own assistant. Switch projects and the column switches with you; switching topics within the same project leaves it in place. Start it with Start Project Assistant when none exists yet.

Topic

Follows the active work topic and shows that topic's own assistant. Switch topics and the column follows. A topic assistant is never created automatically — click Start Topic Assistant when you want one.

Tab

Follows the active window tab and shows that tab's own assistant. Start with Start Tab Assistantwhen none exists — you need an active project in the main view; that project is only the session's work folder and server, while the assistant's context is the tab itself. Each turn gets a [Tab Assistant] block: which projects belong to this tab under Visible items (same denylist reasons as the dialog — server hidden, ROOT off, group unchecked, project unchecked) plus sidebar state facts (SHOW filters, parked, search, selectors, view, auto-show). Membership is not the same as what is currently painted in the sidebar.

Hidden from the sidebar by default

The topic used as General assistant stays out of the project list unless you turn it on. Earlier sessions of that same Assistant topic — same topic slot after Start a New Session in the Assistant column — are also hidden by default and marked with 🤖 instead of the agent icon. Use the Show menu in the Projects sidebar and enable Assistant to list them alongside your regular work.

Neighbor-agent review for General, Project, Topic, and Tab assistant sessions is controlled separately in Settings → Assistant. It is off by default, so the Assistant answers on its own even when the main topic has neighbor review switched on. The setting applies when the assistant session (re)starts.

Files pane

The Filesbutton opens a lazy folder tree of the active project's Project.cwd— the project folder, not the active topic's worktree path — so the tree does not jump when you switch topics. The header shows the real path on disk.

Engine reads, no local fallback

Listing, preview, search, and text edits go through the project's engine. If the engine is unreachable, the pane shows an error with Retry — there is no silent read from your local disk, which would be wrong for remote projects.

Clicks and deliberate actions

Only folders respond to an ordinary click (expand or collapse). A click on a file does nothing — every file action, including View, is an explicit choice from the right-click context menu (same in the search dialog results).

Lazy tree and paging

Folders expand on demand. Each loaded page holds up to 500 names alphabetically from the engine; Show N more loads the next page. Folders sort before files within each loaded page. There is no file watcher — use the refresh button in the header to clear the cache and reload expanded folders. Switching projects resets the whole tree.

Shortcuts

Cmd+Shift+B from Files switches to the Browser (from Assistant it still toggles Browser as before). Panes stay mounted so expanded folders survive when you switch to Assistant or Browser and back.

Filter this folder

A text field under the header (placeholder Filter this folder…) filters case-insensitively on names in the project root listing only — client-side on already-loaded entries, not recursively into subfolders. Expanded subfolders show their full contents. Show N more still loads more root-level names into the filtered list. Escape or the clear button empties the field. Use the magnifying-glass button for a full-project search.

Search dialog

The magnifying-glass button opens Search files on the engine op projectSearch. Modes: File names or Text in files. Options: Match case, Whole word, Include subfolders (default off), and a comma-separated type filter with globs and !exclusions. Ignored files follow the tree's Hide ignored files checkbox. Search runs on Enter or Search (no live search, no regex, no start-folder picker). Stop cancels by searchId. Name hits appear as a flat list; content hits group by file with line snippets. Clicks on results do nothing; right-click uses the same context menu. View from a line opens the text dialog at that line. The footer reports counts, elapsed time, and when results were cut off (hit, scan, time, output size, or cancel limits on the engine).

Hide ignored files

The Hide ignored files checkbox in the header is an app-wide preference (default off). When on, directory listing uses git check-ignore per folder before paging. The search dialog uses the same preference. .git is never included. Symlinks are not followed.

Context menu

Right-click a file or folder (in the tree or search results) for View (files only), Copy path (full path on the engine), Get info (engine fileInfo), and on files Edit as text. When the project folder is a git repo, Add to .gitignore appends an anchored pattern to the project root .gitignore (folders get a trailing /). A notice under the header reports Added or Already in .gitignore; if git still tracks the path, the notice says it stays in the repo until you untrack it. With Hide ignored files on, the tree refreshes after a new pattern so the path can disappear. Each item has an icon like other context menus.

View and Edit as text

View and Edit as text share one dialog (FilesTextDialog, mode prop) in a DialogFrame with the same id, so size and position are remembered together. View is read-only (no Save) and works without an open topic; images render as images via filePreview; .md files get a Preview toggle (renderMarkdownPreview). Edit uses a textarea with textFileRead/textFileWrite(path must stay inside the project folder, no symlink in the path, 1 MB limit, save conflicts detected by content sha256). The old preview overlay route for project files is gone; PreviewOverlay remains for agent-output links only.

Todo pane

The Todo button shows two stacked groups: Projecton top (the active topic's project, or the project you opened Todo from in the sidebar), then Topic below for the active work topic. Each group has a header you can collapse, an open-count badge, and a + to add a todo to that list. The filter pill ( Open, Closed, Archived, All) applies to both groups; the badge on the Todo header counts open items from both lists. Collapse state is stored locally on this machine.

Todo text renders safe inline markdown like CView: bare URLs become links, bold, code, and [label](url). Clicking a link follows Settings → Link Routing (Default Browser or Preview) and does not enter edit mode; double-click outside a link still edits and shows the markdown source. Raw HTML and javascript: links do nothing; angle-bracket text stays visible. Content goes through DOMPurify via renderInlineMarkdown.

Edit a row inline: the field is an auto-growing textarea so long text wraps instead of scrolling off screen in a single-line input. Enter still saves; Escape cancels. Each todo stays one logical line in storage — line breaks are normalized when saved.

Short numbers such as Todo 231 are unique for your account across allprojects, not per project. A ledger on the first server of your account assigns numbers starting at 100; the client claims there, then writes the number to the project's engine with the todo. Once assigned, a number never moves to a second item. Items without a number yet cannot be referenced by number until the next sync assigns one.

Each row ends with a ⋯ actions menu (not a single delete button): Copy copies the todo text; Copy ID copies a short phrase with the todo number (disabled with a tooltip until the number exists); Edit opens inline edit (disabled for archived rows); Delete asks for confirmation in the row — open todos move to the archive (Delete this todo? It moves to the archive.), archived todos delete permanently (Delete permanently? This cannot be undone.). Create Topicopens the New Topic window for this todo: your first account server suggests a project (TypeSafe/jev choice over the same project list as the New Topic picker, plus the todo's own project) and a short title (Codex gpt-6-luna). While the suggestion runs, the dialog shows a loading overlay; partial failures appear as a notice but you can still edit and create. After Create, the todo text seeds the new topic's Command Center draft (only if that shelf is empty), and the todo is archived in its old list and recreated on the new topic's todo list.

When an agent proposes ticking items off after verified work, see TopicTodoDone under the agent protocol.

Topic note pane

The Note button opens a free-text note for the active topic in the main view — the same tab.note field as in Topic settings (EntitySettingsDialog). The old NOTE pill in the CView filter bar and the sticky note overlay in the CView header are gone.

Follows the main-view topic

Like Todo and Browser, the Note pane tracks whichever topic is active in the main workspace. Switch topics and the pane shows that topic's note. Notes on assistant-session topics are only editable through EntitySettingsDialog — the assistant already lives in this column.

Limit and counter

Notes are capped at 1000 characters. The pane header shows the topic name and a live length / 1000 counter. There is no placeholder text in the textarea.

Yellow dot on Note

When the active topic has a non-empty note, a yellow dot appears on the Note button — the same signal the old yellow has-note pill gave in the CView header.

Note font settings

Settings → Appearance still exposes Note font (cvStickyNoteFont*): family, size, weight, and color. The live preview targets [data-el="note-pane-textarea"] in the open settings sheet.

Trace pane

The Trace button (after Note; tooltip Topics you visited, newest first) lists topics you opened in the main view, newest visit at the top. Each row is the same SessionItem row as in the Projects sidebar, including the hover time of the last agent reply. There is no visit-time column and no selected-row highlight — the topic you have open is always the top visit when it counts.

When a visit counts

A topic counts as a visit only after three seconds uninterrupted active in the main view. The Assistant column, archive preview, and a solo Assistant window (?panel=assistant) do not record visits. Hidden browser tabs do not record. If the topic is already at the top of the list, switching back does not add a duplicate row.

Full log vs once per topic

By default you see every visit (A, B, A = three rows). Toggle Show topic only once to keep only the latest visit per topic.

Show limit and retention

Footer menu Show: 17, 50, 100, or All (default All). The limit applies after the only-once filter. The account keeps the last 150 visits; there is no Clear button.

Parked topics

A parked topic is hidden from Trace while it stays parked. The visit remains stored and reappears when you unpark. Filtering runs before consecutive-visit merging and before the Show limit, so hidden rows do not consume the visible cap.

Account-wide, one Trace

The only-once toggle, Show limit, and visit list sync across the Mac app, WebApp, and devices. One Trace is shared across all window tabs in your account.

Click a row

Switches to the window tab where you visited (if that tab still exists), opens the topic, keeps Trace visible, and reveals the topic in the Projects sidebar — zooming to that project or server when the sidebar was zoomed elsewhere, then expanding the path like Command-L. Rows are not draggable.

Empty and hidden topics

Empty state: No visits yet / A topic appears here once it has been open for 3 seconds. Visits to archived, deleted, or not-yet-loaded topics stay in data but are not shown.

Solo Assistant window: account avatar

A solo Assistant window (?panel=assistant) has no Projects sidebar and no tab bar, so sync or sign-in problems used to look like nothing more than No topic selected. The solo header now shows your account avatar on the right (Google picture or initial).

Signed out

A neutral user icon opens the menu → Sign in. On the WebApp that reloads through LoginGate.

Sync alert dot

When workspace sync is stalled, a warning dot appears on the avatar: orange when changes are not saving or the server is unreachable; red when identity was rejected (Sign-in could not be verified).

Solo menu

Opens to the left: name and email, the same sync problem text the sidebar would show, Sign in again, and Retry when sync is stalled. The account menu and Assistant mode menu close each other when one opens.

Main title bar unchanged

The full (non-solo) account badge in the main title bar keeps its existing role — Refresh, Settings, Agents/Prompts/Theme/Server Settings, About, Log out. Only the solo variant shows the sync alert dot.

Protocol

How pm7Code talks to any agent

pm7Code needs every agent to behave consistently — to ask questions the same way, hand off Git the same way, and respect the same conventions. It does this by injecting its own protocol into each agent through that agent's native system-prompt channel, built once when the agent starts.

One source of truth

The protocol is assembled in a single place and shared by every agent. Change it once and all agents pick it up.

Each agent's own channel

Claude Code gets an appended system prompt, Claude CLI gets an appended-system-prompt flag, and Codex gets developer instructions. Same protocol, agent-native delivery.

Independent by design

pm7Code actively keeps outside instruction files from reaching Codex, Grok, and Pi so only its own assembled protocol and your layered prompts apply. Claude Code already loads none of those files by default unless you opt in under Settings → Agents.

Pi runs with noContextFiles and a system-prompt override — no AGENTS.md or CLAUDE.md from the global agent directory, the repo, or parent folders, and no SYSTEM.md replacing the base prompt. Codex sets project_doc_max_bytes=0 so the repo AGENTS.md is not loaded; daemons use a private CODEX_HOME under ~/.pm7-code/codex-home/<hash> that symlinks the real ~/.codex except AGENTS.md and AGENTS.override.md. Auth, config, and sessions stay shared; SQLite is pinned to the real home via CODEX_SQLITE_HOME. If that private home cannot be prepared, Codex does not start — there is no fallback that would reload global AGENTS.md. The pm7-Code skill catalog injected for Codex is capped at about 20,000 characters; if your account skills exceed that, pm7Code shortens the longest descriptions equally until the block fits — names and paths are never dropped. Grok sets GROK_CLAUDE_AGENTS_ENABLED=0, which drops ~/.claude/CLAUDE.md and .claude/CLAUDE*.md; a top-level repo CLAUDE.md or AGENTS.md may still load under folder trust. Claude Code is unchanged: by default it does not load global, project, or local CLAUDE.md unless you enable those sources in Settings.

Proposing to tick off todos (TopicTodoDone)

Open topic and project todos (with their short numbers) are part of the agent's context each turn. After work that fully completes an item, the agent may emit a fenced TopicTodoDone block with { "items": [{ "todo": 231, "reason": "..." }] }. pm7Code shows a CView card with one row per item and Tick off / Keep open buttons. The engine never ticks off from the block alone — only your click on the card (or the Todo pane checkbox) marks an item done.

Keep open = declined

Keep open stores declinedAt on the todo and syncs it like any other todo field. The agent then sees the item as declined in context and should not keep re-proposing the same todo every turn. A later proposal after that decline can be judged again — the card derives state from the todo, not from local-only memory.

Numbers and scope

Proposals use the short todo number, not the internal id. The card resolves each number in the active topic list and its project list only; numbers from elsewhere show as not in the todo list. Items without a number yet cannot be proposed until sync assigns one. At most one TopicTodoDone block per turn, with every item in it.

Vocabulary

Topic, session, agent session

Three words come back everywhere in pm7Code, and the difference between them decides when a prompt is sent. Read this section once and the rest of the prompt documentation falls into place.

WordWhat it isHow long it lives
TopicA subject you work on, with its own settings, prompts, notes, and history. Every row in the sidebar is a topic.Stays. A topic survives closing the app, and it survives starting a new session about it.
SessionOne conversation about a topic, identified by its own PM7 Session ID. It starts with your first message and runs until you start a new one.Ends when you pick Start a new Session. The topic stays exactly where it is; the conversation gets a clean context window and a new PM7 Session ID.
Agent sessionThe technical connection behind a Session: the agent process, its resumable native session ID, and its provider transcript on disk.Comes and goes on its own. An agent session can sleep and resume without you noticing. Switching agents replaces it while the Session continues.
You never start a topic — you start a session about a topic. That is why the Topic prompt is not sent “when the topic is created”, but once with the first message of every session about it. A long topic can hold ten sessions, and each of them opens with the same topic context.

A topic is a place

Rename it, give it a note, set its prompts, pin it, archive it. All of that belongs to the topic and outlives any single conversation.

A session is a conversation

Start a new Session when the context window is full or the conversation drifted. You keep the topic and its settings, and you get a fresh conversation with the topic context restated.

An agent session is plumbing

An agent session is the provider connection behind your Session. It can sleep, resume, or be replaced when you switch agents without changing the PM7 Session ID.

Prompt context

The pm7Code prompt flow

pm7Code does not treat every prompt field as the same thing. Some prompts describe stable behavior, some describe the current project, some describe the topic you are working on, and some are temporary instructions for one turn.

System
Global default
Group override
Shared team or customer context
Project override
Project-specific operating manual
Topic prompt
What this topic is about

User prompt

What you type now

Every message prompt

Added to every message in this topic

Interview prompt

Only when Interview-me is active

Inheritance flows downward: the left column is sent once, with the first message of a session. The right column is the message itself — what you typed, the Every message prompt, and an optional interview prompt.

The practical result is simple: the first message of a session carries the inherited context down to and including the Topic prompt, and every message after that stays lean — what you typed plus the Every message prompt.

Inheritance

Lower layers can override higher layers

Each layer inherits from the layer above it. When a lower layer enables an override, that value becomes the effective prompt for everything below it. If the override is enabled but left empty, that prompt is intentionally disabled for that branch.

PromptEdited inWhen it is sentWhat it controlsOverride rule
SystemApp / global settingsOnce, with the first message of a sessionStable behavior for the agent: how it should work, communicate, and respect pm7Code conventions.Can be overridden by Group, Project, and Topic. An enabled empty override disables the System prompt for that lower layer.
GroupGroup settingsOnce, with the first message of a sessionShared context for a customer, team, business area, or collection of related projects.Can be overridden by Project and Topic. A Project override becomes the Group prompt inherited by the topics in that Project.
ProjectProject settings, stored as Project-prompt.md in the project folderOnce, with the first message of a sessionProject-specific operating manual: goals, architecture, conventions, constraints, and important decisions.Can be overridden by Topic. This lets a single topic suppress or replace project context.
TopicTopic settings, Prompts tab, Topic field, stored as Topic-prompt.mdOnce, with the first message of a sessionWhat this topic is about: the assignment, the relevant files, the goal you keep working toward. It travels with the startup context of every new session about the topic.The lowest inherited layer. A topic can also override the System, Group, and Project prompts it inherits.
Every messageTopic settings, Prompts tab, Every message field, stored as Every-Message-prompt.mdWith every message you send in this topicA standing instruction you want repeated on every turn, such as a house style or a language rule. Keep it short — it costs tokens on every single message.Not inherited by anything. It only applies to this one topic.
InterviewInterview-me toggleOnly on the turn where Interview-me is activeA temporary follow-up mode that makes the agent ask questions before it acts.Not inherited. It is a one-turn suffix that switches off again after sending.
Example: if a Project overrides the Group prompt, every new topic in that Project inherits the Project's version of the Group prompt. The topic can still override it again.
Editing a System, Group, or Project prompt does not interrupt a session that is already running: the new text lands in the next session you start. If you want it in the current conversation right away, set the prompt-mode button to its blue state for one message. Project and Topic prompts are read from disk while a turn is built, so editing their files counts from your next message.

Injection

When prompts are sent with your message

A session opens with startup context and then stays lean. The first message carries System, Group, Project, and Topic; every message after that is just what you typed plus the Every message prompt.

First message of a session

Startup context
  1. 1Effective System prompt
  2. 2Effective Group prompt
  3. 3Effective Project prompt
  4. 4Topic prompt
  5. 5User prompt
  6. 6Every message prompt
  7. 7Interview prompt, only when Interview-me is active

Every message after that

Normal turn
  1. 1User prompt
  2. 2Every message prompt
  3. 3Interview prompt, only when Interview-me is active

Startup context is one-shot

System, Group, Project, and Topic go out together with the first message of a session, and then not again. Start a new session and they are sent once more.

Every message is per turn

The Every message prompt is appended to every single message you send in this topic, in every session. Use it only for instructions that must genuinely be repeated.

Interview is optional

The Interview prompt is added only when Interview-me is active. It is meant for guided follow-up questions and switches off again after one turn.

Overriding it for one message

The prompt-mode button next to the input field decides what rides along with the next message. Grey sends your text without any prompt context, black is the normal turn, and blue forces the full startup context — handy right after you changed a Project or Topic prompt and want it applied immediately. Grey and blue spring back to normal after one message; the struck-out state stays silent until you change it back.

Start context card (new sessions)

At the top of CView for a new session (not on resume), a Start context card lists what startup context the session will carry. It is distinct from the per-turn Prompt Context card — Start context is frozen once the first message is accepted and survives resume via the durable session mirror. The card stays open by default; you can collapse it; it remains at the top of the transcript.

Prompt layers

System, Group, Project, Topic, and Every message — each with status File / Inherited / Set in app / Default / Off / None, optional origin (this topic, this project, the group, Settings), and a link to the .md file when present. System and Group often link to readable copies such as System-Copy.md / Group-Copy.md. Clicking a path opens the file read-only in ProjectDocOverlay via the project engine.

Also in context

Memory, Todos, Topic state, Fork, Build policy, Unlanded work, and Topic context — not protocols (Prompt Context still shows protocols on each turn).

Instruction files the agent loads itself

Listed only when this agent's current settings actually load them — for example CLAUDE.md or AGENTS.md — with openable paths.

Mode note and preview

A mode line explains whether startup context goes with your first message, waits, or is off (for example Goes with your first message. or Not sent: the session started with automatic prompts off.). Before the first message, when there is not yet a session, a preview card can appear above the message list; after the first accepted message the card freezes in the transcript cache.

Settings

Where to edit and inspect prompts

Group, Project, and Topic settings all have a Prompts tab. Each tab shows the prompt layers that make sense at that level. Project and Topic prompts are plain .mdfiles under the project's Folder — see Prompts live in your repo — in pm7-Code/<Project-UUID>/. There is no separate Home folder setting; only Folder remains in Project settings. If the Folder is unreachable, the window reports that the prompt files could not be read, or shows “Loading from the Project folder…” while it tries.

Group settings

SystemGroup

Use this for context shared across projects in the group. Group can override System.

Project settings

SystemGroupProject

Use this for project-specific context. Project can override System and Group.

Topic settings

SystemGroupProjectTopicEvery message

Use this for the subject you are working on. A topic can override the inherited startup context and adds its own Topic and Every message prompts.

Suggest prompt

The Suggest prompt button uses a hidden background request to propose a prompt for the exact field you are editing. It can use the current folder, inherited prompts, project files, git context, and recent topic history. The result appears in a preview with Original prompt, User prompt, and Suggested prompt tabs before you replace or append anything.

CView makes prompt injection visible

When pm7Code injects prompt context, CView shows a Prompt Context card. Each row is labeled with its kind and source: Inherited, Group override, Project override, Topic override, Disabled, Topic, Every message, or Active. Open the card and you see the exact text that went out with that message.

Language Directive

Settings → Agents → Prompts includes a Language Directive (ccLanguageAppend) that is appended on every turn. The default requires Dutch for all user-facing prose. Established English technical and IT terms stay English — the default no longer coins Dutch calques for words like watcher, child process, listener, or thread. Accounts that pinned the older default via Reset to default are upgraded automatically when pm7Code detects the stale copy. This is separate from built-in slash-command prompt text — see Built-in slash prompts.

Your own slash commands

Settings → Agents → Prompts → Commands lists built-in slash commands and your own. Your commands use the same collapsible card pattern as the built-ins: collapsed, the card shows the command name, description, and an Edit prompt affordance; expanded, it shows the name, description, and prompt fields. Each built-in and custom command has an on/off toggle on the card header. Switched off, the command is omitted from Command Center autocomplete and cannot be sent; the card shows Switched off: hidden from the Command Center and not sent. The Commands search bar filters your commands too — it matches name, description, and prompt text.

Built-in slash prompts

The bundled prompt text for /check-fresh, /check-with-*, /map-codebase, /pause, /remember, /image-tool, and /skillifyis Dutch and no longer ends with lines such as “Answer and report in English.” Shell command strings, template variables, the /remember header, and JSON schema fragments stay literal English or technical where required. English originals are kept only so older transcripts can still collapse sent prompts, and so a stored override that is exactly the old English default follows the new bundled Dutch text (Settings shows Dutch; the next save drops the stale copy). A truly customized override still wins. This does not change the Language Directive — slash prompts no longer force English on top of your language settings.

Storage

Prompts live in your repo, as files

Project and Topic prompts are not stored inside pm7Code once a project has a Folder. They are plain .mdfiles under the project's Folder, in pm7-Code/<Project-UUID>/, so they are versioned, reviewed, and shared through git like any other file. The settings windows read and write exactly those files.

<Project folder>/pm7-Code/
  <Project-UUID>/
    Project-prompt.md      the project layer
    System-override.md     project overrides the System prompt
    Group-override.md      project overrides the Group prompt
    System-Copy.md         generated reference copy, overwritten
    Group-Copy.md          generated reference copy, overwritten
    <Topic-UUID>/
      Topic-prompt.md          the topic layer
      Every-Message-prompt.md  sent with every message
      System-override.md       topic overrides System
      Group-override.md        topic overrides Group
      Project-override.md      topic overrides Project

The two *-Copy.md files are different from the rest: pm7Code writes them but never reads them. They exist so you can see in the repo which System and Group prompt apply to this project — the source of truth is the app itself. They are refreshed when the app starts and when a prompt changes, so they can briefly lag behind. Editing them is pointless: every edit is overwritten.

No file

Inherit

The layer is not set here, so the layer above it applies. Clearing a prompt deletes its file; a prompt you never set never creates one.

File with text

Apply

The text in the file is the prompt. It is read fresh while your turn is built, so an edit in your editor counts from the next message.

Empty file

Off

Zero bytes means the layer is deliberately switched off for this project or topic — the same as an enabled but empty override.

A project without a Folder keeps its prompts inside pm7Code until you set one. The move to files happens per project and per topic, the first time a Folder is set: the text is written, read back, compared, and only then removed from the internal store. What is already in a file is never overwritten.
Two consequences worth knowing. Switching git branches switches your prompts along with the branch, without a warning — that is what putting them in the repo means. And prompts now travel through git instead of through the pm7Code sync, so a machine that has not pulled yet does not have them.
New projects seed the Project prompt from an empty Default-Project-Template.md— there is no built-in “Finalize, publish, and deploy” block anymore. Put release and deploy steps in Deploy procedure on the Build & Deploy tab, or in this project's own Project prompt. Existing Project-prompt.md files are not changed automatically.

Releases

Dedicated Build & Deploy topic

Some projects want one topic that owns releases and deploys while every other topic finishes work in its own worktree and hands over. Project Settings → Build & Deploy (next to Algemeen, Links, and Prompts) turns that model on. The engine applies a per-turn Build policy from the on-disk role record — client claims do not override it. Sub-agents (delegates) always get the work-topic policy, never Build.

Project checkbox (default off)

This project has a dedicated Build & Deploy topic. When on, the tab shows which topic currently holds the role (or that none is marked yet), a Deploy procedure textarea stored as Deploy-procedure.md under pm7-Code/<Project-UUID>/, and a warning if the Project prompt still contains a “Finalize, publish, and deploy” heading block — that conflicts with a dedicated Build topic; remove that block on the Prompts tab.

Topic checkbox (project feature on)

In Topic Settings → Algemeen, This topic is the dedicated Build & Deploy topic. Taking the role from another topic asks for confirmation; Save moves the role and clears the previous topic's checkbox. If another window saved first, Save can fail with a conflict — re-check which topic holds the role and save again.

Sidebar 🚀

The topic that holds the Build & Deploy role shows a rocket icon after its name (title and aria: Build & Deploy topic). Only that marked topic builds releases and deploys; other topics finish work and hand over.

CView: Build policy row

Prompt Context includes a Build policy row with source labels such as No Build topic, Work topic, or Build topic. Open the card to see the exact policy text for that turn.

Per-turn policies

The engine picks none, work, or build each turn from project settings and which topic holds the role. Deploy only when the user asks in the Build topic; follow Deploy procedure exactly there.

No Build topic (checkbox off)

Build, release, and deploy run only when you explicitly ask this turn. The agent never starts them on its own after finishing a task.

Work topic (checkbox on, not the Build topic)

Never release, deploy, bump, production push, or land on the default branch. Local test, typecheck, or build in this topic's worktree is fine. If you ask to deploy, the agent points you at the Build topic (or “(none designated yet)” when no topic is marked) and stops.

Build topic (checkbox on, this topic has the role)

Only this topic releases and deploys. Work happens in the project base checkout on the default branch. The agent does not change product code — report code failures and stop. Deploy when you ask in this topic only; follow Deploy procedure exactly.

Unlanded work (Build topic only)

Before a deploy-minded turn, the Build topic can receive an advisory Unlanded work block in prompt context. It lists other topics whose worktrees still have work not on the base branch, or notes that the check is still running or stale.

What the agent should do

Tell you first and name the topics. You land work in the app; the agent does not merge for you. If you still want the build after that, it can proceed.

When you might not see policy

Silent turns (prompt mode off) and turns that start with / or ! get no Build policy. Skip-word turns include policy only when it changed since your last send.

Auto generate and review Deploy procedure

On Project Settings → Build & Deploy, above the Deploy procedure field, Auto generate runs a read-only Claude investigation on the project's engine machine (not the window machine). While it runs the button reads Stop generating. The textarea updates only on a valid result — you still press Save. Unverified findings appear in a list under the field (not persisted). Errors, timeout (about six minutes), or Stop leave the field unchanged.

Continue in new Topic

Under the unverified list, Continue in new Topic saves first, closes the dialog, and starts a normal topic named Deploy procedure nakijken. That session walks unverified points one-by-one with you. The agent must not edit the Deploy procedure file (it works in a worktree); it ends with full markdown for you to paste back into Project settings.

Interaction

Agents ask you structured questions

When an agent needs a decision from you, it does not bury the question in a wall of text. pm7Code renders a structured question card with numbered options and an always-present free-text field, right inside the transcript. You answer in the workspace and the agent continues from your choice.

Numbered options

Each question offers a short set of options, numbered by the UI. Pick one, or several when the question allows multiple answers.

Always room for nuance

Every question has an optional text field underneath, so you can add detail, combine it with a choice, or answer in free text alone.

The agent waits for you

Your selection and any free text are returned to the agent as your answer. Nothing is assumed on your behalf while it waits.

Second opinion

Neighbor-agent review

Neighbor-agent review is an optional per-topic setting. When it is on, the active agent consults a designated buddy agent before asking you a question, and presents both recommendations so you can decide with a second opinion in front of you.

Off by default

Review is a per-topic toggle and starts off. Nothing consults a second agent unless you turn it on for that topic.

Both views, clearly labeled

The question card shows the active agent's preference and the buddy agent's recommendation as separate, clearly attributed advice.

Applies from the next session

The setting is baked in when the agent starts, so toggling it takes effect from the next session — like the model and permission settings.

Five-minute consult cap

Each neighbor consult is capped at five minutes. If the buddy agent hangs, the consult ends with a timeout instead of blocking your question indefinitely.

Codex in non-git folders

Neighbor consults that shell out to Codex pass --skip-git-repo-check so codex exec can start in directories that are not a git repo or trusted project — for example a project without git, or after cd /tmp for a brief.

Agent protocol

Starting a topic from the agent (TopicStartRequest)

An agent can ask pm7Code to start a new topic by emitting a fenced TopicStartRequest block. pm7Code shows it as a CView card with Start and Reject. Nothing runs until you press Start — topics never start on their own.

Want the agent to hand off a subtask without a click, and get the result back by itself? That is delegation: a DelegateRequest block starts a sub-agent in its own worktree — in this project, another project, or on another pm7Code server — and its outcome returns to the agent as a new message.

After you press Start

The new topic is created in the background, your first-turn prompt is sent immediately, and you stay on the source topic. The card gains an Open topic button when the destination is ready.

Required fields

name (short topic title) and prompt (a self-contained first message — written as if the new agent has not read this conversation).

Optional fields

project — existing project by name, or { "name", "server" } when the same name exists on several servers; omit to use the current project. newProject — { "name", "cwd", "server" } to create a project (the folder is created on that server when missing). agent — agent id for the new topic (defaults to the requesting agent). waitFor: true— only when this topic must wait for the result: a waiting marker on the source topic and the new topic's first-turn answer delivered back as a visible message once it finishes (only while a pm7Code client is open).

Claude Code: background Agent tasks

Claude Code can launch its built-in Agent tool in the background (async_launched). pm7Code treats that as work that still belongs to the current turn: the Agent card stays in the running state, the session status shows (waiting for background agents...), and the turn does not return to idle or show completion until each background agent sends its task notification and Claude Code finishes the follow-up turn that incorporates the results. Stopping the turn or losing the stream releases the wait without deleting the cards — a late notification can still settle the card later.

This is separate from pm7Code delegation (DelegateRequest sub-agents with their own worktrees).

Keyboard

Stopping a turn from the Command Center

When the agent is in the middle of a turn, pressing the Escape key while the Command Center input has focus stops the active turn. This is the same action as the Stop current turn button in the CView title bar.

Only stops a running turn

Escape only sends the stop signal when the agent is actively thinking, running a tool, or compacting. If no turn is in flight, the keypress is forwarded to the terminal as a normal Escape, so terminal apps and TUIs keep working as expected.

Works for every agent

The shortcut calls the matching interrupt API for the active agent: Claude Code, Claude CLI, OpenAI Codex, Pi, Cursor, and Grok. The topic, its CView history, and the underlying agent-session ID are preserved.

Nothing gets closed by accident

Escape only interrupts the current turn. It never ends the session and never archives the topic. Use the CView title menu when you want Start a new Session or Archive.

Status resets immediately

After the interrupt is acknowledged, the CView status returns to idle and the stalled indicators are cleared, so you can send a new prompt without waiting for the agent to wind down.

Projects sidebar

Project display

Each window tab remembers its own Projects sidebar layout and visibility. Open Project display from the sidebar hamburger → Tab Settings, or right-click the active window tab → Settings…. The dialog title is Project display; the subtitle is Settings for tab "…" — the active window tab you are editing. If the active window tab or the window tab set changes while the dialog is open, it closes so you are not editing the wrong tab. Two tabs — Display and Visible items — apply changes live as you toggle them; dismiss the dialog when you are done (there is no separate Apply step).

Display tab

Sort order, the Show toggles (checked on top, active section, last 12 hours, Pinned only on top, and similar), and which sidebar view modes the cycle button rotates through — all scoped to this window tab.

Pinned only on top

On the Display tab, Pinned only on top keeps pinned topics out of the project list and flat Topic List while their pinned section is open — Pinned in this tab or Pinned in all tabs. Collapse that pinned section and the same topics reappear in the list below, so nothing vanishes. The choice is per window tab (default off).

Hide Build & Deploy topics

On the Display tab, Hide Build & Deploy topicsleaves each project's dedicated Build & Deploy topic (🚀) out of the normal project and topic lists for this window tab. A Build & Deploy topic that is pinned still appears in the pinned block on top. Default off.

Visible items tab

Per server, checkboxes for the server itself, ROOT(that server's loose root projects), each root project, each group, and each project inside a group (indented). Each checkbox reflects what the sidebar actually shows, not only that row's own flag. Search filters the table. Counts show shown/total per server; partial counts highlight when something on that server is hidden.

Visible items — per tab, per project

Hiding is stored on the current window tab and applies to every project — loose or inside a group. A group is the master switch: hide the group and everything under it disappears; show a project inside a hidden group and pm7Code reveals the group chain so the project can appear. Auto-select new items controls whether new groups and projects arrive checked in this tab or stay unchecked until you pick them.

Held check when a parent is off

If a row is on but a parent ROOT or group is off, the checkbox looks dimmed — a held state with a tooltip that a parent is hidden. Click still shows the item; pm7Code reveals the ROOT or group chain so it can appear in the sidebar.

Sync across clients on the same tab

Visibility for a window tab syncs between clients on that tab. When both sides change the view, pm7Code merges hidden* denylists per id with a three-way merge, so an unrelated change elsewhere — collapse a group, switch topic — does not wipe a hide or show you just made on another client.

Servers start collapsed

When you open Visible items, each server block starts collapsed — shown/total counts stay visible in the header. Click a server row to expand its groups and projects. While you search, matching servers expand automatically; clearing search collapses again. Expand/collapse is not persisted — reopening the dialog starts from collapsed.

Hide from the project menu

Right-click a project → Hide unchecks it for this window tab only. Hidden projects drop out of the sidebar, Projects search, the flat topic list, the new-topic menu, the project picker, title-bar TOPICS, and the window-tab attention badge. Topics pinned in this tab can still show.

Same scope as search filters

Qualifiers and text search respect the same visibility — see Filter by project, group, or topic.

New Topic — pick the project in the header

When you open New Topic, the project name in the window header is a control. Click it to open a project picker and choose which project the new topic belongs to before you fill in the rest of the form. The default list is the same set of projects this window tab shows in the sidebar (respecting Visible items). Turn on Show all projects to include hidden servers, groups, and projects as well. The filter searches project names only.

The temporary project or server picker in the sidebar is intentionally not mixed into this list — otherwise, after you pick a project in the sidebar, nothing else would remain to switch to inside New Topic. Worktree and Hotfix options for the new topic still follow the selected project's isolation settings — see Starting and landing a worktree session.

Git Service

How the Git Service works

At the end of a coding turn, an agent can emit a fenced GitServiceRequest block. pm7Code detects that block in the conversation, creates a visible Git Service card, and enqueues a background Git job in the main process.

The important detail is that the request is asynchronous from the user's point of view. Once pm7Code has accepted the request, the agent is free to continue with testing, inspection, or the next task while commit and push run separately.

1

The agent finishes files

The agent records the exact files it changed in this turn.

2

pm7Code enqueues Git

The app validates the request and creates a background job.

3

Work continues

The Git Service commits and pushes while the session can move on.

User interface

What you see in pm7Code

A GitServiceRequest appears as a dedicated card in CView. The card shows the job state, the repository path, the files included in the request, and any error returned by the Git Service.

When a turn starts with a tool or card message, CView still shows the agent avatar and name on that turn. Rows nested inside an Agent group card still suppress redundant headers there.

StatusMeaning
Queuedpm7Code accepted the request and placed it in the Git Service queue.
Validatingpm7Code checks the exact files, working tree state, and request shape before touching Git.
StagingOnly the files listed in the request are staged. Directories and broad pathspecs are rejected.
CommittingThe Git Service creates the commit with the message supplied by the agent.
PushingThe commit is pushed while the agent can already continue with other work.
SucceededThe requested files were committed and pushed.
FailedThe request was stopped before completion. The card shows the reason and no hidden retry is performed.

Safety

What pm7Code protects

The Git Service is intentionally strict. It is designed to commit exactly the files from the finished turn and to stop when the repository state no longer matches the request.

Exact file list

The request must list concrete files. Directories and broad patterns are rejected so an agent cannot accidentally commit unrelated work.

Snapshot validation

pm7Code records the file state when the request is enqueued and checks that the same content is staged before committing.

No mixed staged work

Existing staged changes that do not belong to the request are a reason to fail, not a reason to create a mixed commit.

Visible failures

Conflicts, drift, hook failures, and push errors are surfaced on the Git Service card for the user to inspect.

Advanced

GitServiceRequest format

Most users do not need to write this block by hand. pm7Code's agent protocol emits it automatically at the end of a turn when files changed. Advanced users and agent authors can use this shape:

```GitServiceRequest
{
  "cwd": "/Users/patrickmast/Dev/pm7-code",
  "files": [
    "site/app/docs/page.tsx",
    "site/app/page.tsx"
  ],
  "scope": "docs",
  "commitMessage": "docs: document Git Service"
}
```
pm7Code does not build the project as part of this Git flow. The Git Service only commits and pushes the requested files.

Memory

pm7Code remembers, independent of the agent

pm7Code keeps its own memory of durable facts, preferences, and conventions. Because the memory belongs to pm7Code and not to any one agent, it works the same whether you are running Claude Code, Codex, Pi, Cursor, or Grok — it is not tied to a single agent's own memory store.

It mirrors the Git Service model: the agent only proposes a memory write, and pm7Code is the authority that decides what is actually stored. A proposal shows up as a Memory card in CView with its own status, just like a Git Service card.

Agents propose, pm7Code decides

During a turn an agent can emit a memory proposal. pm7Code validates and stores it; the agent never writes memory directly and never needs to know where it lives on disk.

Stored by the engine, not the panel

The engine that runs the session applies each proposal the moment it is complete — with the panel closed, over a dropped connection, and in headless jobs. Each proposal has one durable identity, so a reconnect, a replay, or an engine restart never stores it twice. The Memory card only shows the outcome.

Scoped and typed

Items are scoped globally or to a project, and typed as a user fact, feedback, project note, or reference. The most important items can be pinned so they are always in context.

Recalled automatically, in either language

Each turn pm7Code weaves in a few concise, relevant memories. Recall understands Dutch and English spellings of the same thing, so a convention written as “build” is found when you ask about “bouwen”. A short follow-up such as “ga verder” searches with the topic's own context instead of finding nothing.

Readable, with provenance

Every recalled item names the file that holds its full text and its provenance — where it came from, its status, and when it was last updated — so an agent can check how current a memory is before acting on it. Replaced or deleted items are never recalled as current instructions.

No duplicates, no invented truth

Literal duplicate matching still stores a lesson once. On top of that, a semantic check can mark a proposal as covered by an existing memory — then nothing new is written, you get a durable duplicate receipt, and the Memory card shows outcome duplicate. If it marks a conflict, the proposal is still saved, both items stay on disk (the older one is not auto-superseded), they are linked in provenance as contradicts, the card shows conflict, and the message reads Saved — contradicts an existing memory. When the check is unclear, times out, or fails, pm7Code writes as before — storing is the default. Recall lines can include [contradicts <id>] when items are linked. Replacing an outdated memory keeps the old version as history; pm7Code never merges conflicting facts into something nobody said.

Private and local

Memory is stored locally on your Mac. Suspected secrets are screened out and rejected, and project facts are never automatically promoted to your global memory.

Memory is recall, not a transcript. A session keeps the full conversation history; memory is the distilled, reusable knowledge that pm7Code carries forward from it. Progress on the work at hand lives in the topic work state below, not in memory.

Topic work state

A new session picks up where the last one stopped

A topic is the workstream; a session is one agent run inside it. Starting a new session in the same topic — after “Start new session here”, an agent switch, or a restart — used to mean the new agent only had the old transcript to go on. pm7Code now keeps a compact, durable work state per topic: what the goal is, what was decided and why, what was tried and dropped, what is verified, what blocks, and what comes next.

1

The agent checkpoints

At a real progress point the agent records a small update: a decision with its reason, a rejected approach, a completed step, a verification result, the open blockers and next steps. It is a patch, not a rewrite.

2

pm7Code stamps every turn

When a turn ends, pm7Code records the outcome, the git revision and branch, and the files the agent's tools touched. A turn that merely ended never marks the topic as done; only the agent does, explicitly.

3

The next session reads it first

A fresh session in the same topic receives a bounded summary of the work state as part of its start turn, with a pointer to the full record. Another topic never sees it.

Recorded context, not an instruction

The stored next steps are shown as what was planned, never as a command. Your current request always leads.

Old evidence is marked as old

A verification result carries the revision it was observed against. When the code has moved since, the new session sees it labelled as historical instead of trusting a test that passed on different code.

Survives worktrees and restarts

The record lives with the project, next to the topic's Command Center data, not inside a disposable worktree. Concurrent updates cannot overwrite a newer decision.

Progress here, lessons in memory

Incident details, hypotheses and a failing test belong in the work state. Only a proven, reusable lesson goes to memory — so memory stays small and the work state stays current.

Reworded duplicates skipped

When appending to decisions, rejected approaches, progress, or verification, the engine can drop a line that already says the same thing in different words, so the recency cap does not push out older load-bearing lines. Keeping is the default: without a judge key, a timeout, an error, or an unsure answer, the line is appended as before. REPLACE fields are not judged — the agent owns the full list there.

The work state also sharpens recall: a short follow-up like “ga verder” retrieves memories about the work in progress, using the topic's goal, decisions and files as context.

Skills

Write a skill once, every agent uses it

A skill is a small, reusable instruction pack that teaches an agent how to do a recurring job the way you want it done — how you deploy, how you sign a macOS build, how you write a release note. It follows the open Agent Skills standard: a plain SKILL.md file with a name and a description, optionally alongside supporting scripts and assets.

The problem skills usually create is duplication. Every agent keeps its own copy, so the same skill has to be written and maintained several times. Copies drift apart, and you end up tied to whichever agent happens to hold the good version. pm7Code removes that entirely: it keeps one canonical store and shares it with every agent automatically, so a skill written once works the same across all of them.

The same mechanism covers three kinds of instruction pack: skills (used by every agent), plus guides and commands for the agents that understand those concepts. And it no longer stops at one machine: your set lives in your account and follows you to every machine and server you run agents on — see Available everywhere below, and Under the hood for what it does on disk.

One canonical store

Your skills live in a single place that pm7Code owns. There is one copy to edit, one source of truth, and nothing to keep in sync by hand.

Automatic fan-out

pm7Code shares each skill into every agent it detects, just before an agent starts and once when the app launches. You never have to push or copy anything.

Open standard, any agent

Because skills use the open Agent Skills format, every agent that follows it picks them up unchanged. Today that means Claude Code, Codex, Pi, and Grok — new compatible agents work on day one.

1

Create or edit a skill

Add a skill in Settings, or edit its SKILL.md. One copy, in one place.

2

pm7Code shares it

The skill is linked into every detected agent automatically — no manual copying.

3

Every agent uses it

Claude Code, Codex, Pi and Grok all see the same skill the next time they run.

Manage skills in Settings

Settings has a Skills tab where you create, edit, and delete skills. Each skill shows a short description, how many files and how much content it holds, and a set of badges for the agents it is currently live in. Editing opens the SKILL.md in place; a Resync button re-shares everything on demand if you ever want to trigger it yourself. The same tab has an Account sync section to push your local set up to your account and pull it back down.

Agents can propose publishing a skill

Your account is the source of truth for skills. A change that only exists on disk in ~/.pm7-code/skills is treated as drift and is overwritten the next time pm7Code pulls from your account or rematerializes skills at session start.

When an agent creates or edits a skill and wants that change to last, it proposes a publish. CView shows a Skill Publish card with Publish and Reject. Agents never push to your account themselves — only the approved card path does.

1

Agent proposes

The agent asks to publish a skill. pm7Code snapshots it immediately — not whatever happens to be on disk after later session rematerializations.

2

You decide

Publish or Reject on the card. Publish uses that snapshot. If the account version of the skill changed since the proposal, publish is refused — ask the agent to propose again on the current version.

3

Outcome sticks

After Publish or Reject, the card keeps its outcome across reloads: published (with file count and whether it came from the snapshot or disk), rejected, or failed with an error. The same outcome survives resuming the session when message ids renumber and the card timestamp shifts by a few seconds.

Snapshot at proposal time

pm7Code stores the skill under skill-sync/staged/ the moment the agent proposes it, because the local skills folder is an account cache that can be rebuilt before you click Publish.

Invalid frontmatter is refused

If SKILL.md YAML frontmatter does not parse, publish is rejected so a broken skill never reaches your account.

Available on every machine you use

pm7Code can run your agents on more than one machine — your Mac, a home server, a remote box over Tailscale. A skill only helps if it is physically present wherever the agent runs. So your set lives centrally in your account, and every machine materializes the current version automatically, right before an agent starts. You write it once and it is simply there, everywhere.

1

Push to your account

In Settings → Skills → Account sync, push your local skills, guides and commands up to your account. That is the single source of truth.

2

Connect to any machine

Open a topic on any machine you use. Just before the agent starts, pm7Code makes that machine's set match your account.

3

The agent has it

The skill is in place before the first prompt runs — no copying, no per-server setup, no drift between machines.

Your credentials never leave your device. pm7Code reads your account on the machine you are sitting at — the one that is already logged in — and hands only the skill files to the machine that will run the agent. A remote server never needs, and never receives, your login token. It just gets the files.

Does nothing when nothing changed

Each machine compares what it already has against your account and only writes what actually differs. Connect ten times with an unchanged set and nine of them do no work at all.

Delete travels, safely

Remove a skill from your account and it disappears from every machine on the next connect. pm7Code only ever removes what it put there itself — a skill you made by hand on a machine is never touched.

An agent's own skills win

If a machine already has a real skill of the same name that you installed directly, pm7Code leaves it alone. It never overwrites an agent's existing work to force its own copy in.

Under the hood

Everything above is deliberately boring machinery. If you ever need to inspect it, repair it by hand, or reason about why an agent does or does not see a skill, this is exactly what happens on disk.

Where things live

~/.pm7-code/skills/
— the canonical store. One directory per skill, each with a SKILL.md. A directory without a SKILL.md is ignored. Sibling folders guides/ and commands/ hold the other two kinds.
~/.claude/skills/, ~/.codex/skills/, ~/.pi/agent/skills/, ~/.grok/skills/
— the fan-out targets. An agent counts as installed when its config directory exists; only then is anything written for it. Guides and commands go to ~/.claude/guides/ and ~/.claude/commands/ only, because Claude Code is the harness that knows those concepts.
~/.pm7-code/skill-plugin/
— a generated plugin that carries the same store into Claude Code agent sessions. See below for why it exists.

What sharing actually does

Nothing is ever copied. Each target gets one absolute symlink per skill, pointing back at the canonical directory — on Windows a directory junction, which needs no administrator rights. The agent reads the same files you edit, so there is no second copy that can drift. Four rules keep it safe to run at any moment: a real folder at the target is never overwritten; a link that is already correct is left alone; a link that points at the wrong place is recreated; and a link into the store whose skill no longer exists is removed. Symlinks pointing somewhere else entirely — skills you installed yourself — are never touched. Every step is best-effort, so one unwritable directory cannot break the rest or block a session.

Why Claude Code gets a plugin

Claude Code only reads ~/.claude/skills/ when a agent session loads the user settings scope — and pm7Code deliberately does not load it, because that same scope would also inject your global CLAUDE.md into every single prompt. Rather than trade prompt weight for skills, pm7Code projects the canonical store a second time into a small local plugin and hands that to the Claude Agent SDK. Plugins are loaded independently of the settings scope, so skills keep working no matter how that setting is tuned. The projection uses the same links as every other target, so it is still one copy on disk, and it is rebuilt just before each agent session — a skill added while the app is running is picked up by the next agent session without a restart.

When it runs, and in what order

Sharing runs once at app launch and again just before every agent session starts, on whichever machine that session runs. There are two layers and they stack: layer 2 makes the machine's canonical store match your account — pulled on connect, and only where content actually differs — and layer 1 then fans that store out to the agents on that machine. Local and remote engines share the same code path, so a Mac, a Linux server and a Windows box behave identically.

Never overwrites your work

Sharing only ever adds links into an agent. If a real skill folder already exists there, pm7Code leaves it untouched rather than replacing it.

Edits are lossless

Editing a skill only changes what you changed. Supporting files — scripts, templates, assets — are preserved exactly, so nothing is lost on save.

Never blocks an agent

Sharing is best-effort and runs in the background of a start. If anything goes wrong, the agent still launches normally; skills can never get in the way of work.

Yours, on your Mac

The canonical store is a normal folder on your machine. You can browse it, back it up, or keep it in version control like any other project asset.

The result is that skills become a workspace asset instead of a per-agent, per-machine afterthought. Write your team's know-how once, and every agent you drive from pm7Code — on every machine, now and later — benefits from it without copying or migration.

Workspace

Panels around the transcript

Beyond the terminal, the prompt, and the agent transcript, pm7Code adds a few panels that keep the rest of the dev loop in the same window.

Assistant column

A second CView and Command Center in the right sidebar — General, Project, or Topic mode — so a helper session stays open beside your main work. See Assistant column.

Browser View

One of six right-sidebar panes (Assistant, Browser, Files, Todo, Note, and Trace — see Assistant column): an in-app browser with its own tabs. Open the deploy you just shipped or your local dev server without leaving the workspace.

Files pane

A right-sidebar pane: a lazy folder tree of the active project's directory (not the topic worktree). Browse project files via the engine; open files from the context menu. See Files pane.

Todo, Note, and Trace panes

Todo lists open todos for the active topic or project — see Todo pane. Noteedits the active main-view topic's note (same field as Topic settings). See Topic note pane. Trace lists topics you visited in the main view, newest first — see Trace pane.

Live Summary

Independent summary slots distill a long run into its gist as it happens. Each slot has its own provider and model, so you can scan progress without reading every line.

Remote engines

Route a topic through a remote websocket motor so the agent runs on another machine, while the workspace, transcript, and live status stay local. Git UI for that project runs on the same engine — see Git on the project's engine.

Pasted screenshots follow the prompt

Paste a screenshot into the prompt and pm7Code uploads it to the engine for the tab where you pasted, then inserts the file path into your draft. If you later send that turn to a different machine— Assistant column on another server, a moved project, a copied draft, and similar — pm7Code re-uploads the remembered image bytes to the destination engine and rewrites the path before send so the agent can open the file. If re-upload fails, the turn is not sent; you see an error such as “Screenshot could not be sent to the session's machine…” Paste failures use messages like “Screenshot was not pasted”. Maximum paste size is 20 MB. After a full reload, unknown paths are left alone — there is no relay without the in-memory bytes.

Title bar when window tabs are hidden

If the window tab bar is turned off, the build and agent-version status pill moves into the title bar so a running build stays visible. The tab switcher there shows the current window-tab title (ellipsis when long) with a chevron instead of the static label TABS — click to pick another tab.

GitHub button in the title bar

When the active project has a GitHub URL in Project Settings (clone or web form — for example git@github.com:owner/repo.git or https://github.com/owner/repo.git), a GitHub icon button appears in the title bar immediately after the project URL button. Click opens that repository's web page on GitHub. SSH and HTTPS clone addresses are normalized to https://github.com/owner/repo. If Settings → General → GitHub has Open in GitHub with set, the same app opens the link as Git menu Open on GitHub; otherwise the default browser is used. With no GitHub URL, only the normal project URL button remains.

Resource pill (desktop only)

On macOS desktop, a compact resource pill polls memory about every two seconds: the figure is the sum of every Electron process in this app. When the window tab bar is visible, the pill sits at the top-right of that bar (in #window-tab-bar-actions, beside the build pill); when tabs are hidden, the same pill moves to the title bar — it never appears in both places at once. Click memory to open a proof panel listing each process with its share and a total (a frozen snapshot with refresh, so rows do not jump while the pill keeps updating). The WebApp hides this entirely because a browser cannot measure app memory. An older open-shell count was removed — shells run on engines, so the local count was always misleading.

Move project to another server

From the project menu or project context menu, choose Move to Another Server… to copy the project folder and rebind it to a different engine. While a move is already running for that project, the same entry becomes Show Move Progress….

Wizard vs background job

The wizard is for setup only — pick destination server, folder, and confirm. Start move hands the transfer to a background job and closes the modal. You can keep working elsewhere in pm7Code while bytes stream through this window.

Progress on the project row

A chip on the project row shows Moving → {server} · {pct}%, then Moved or Move failed. Click the chip or use Show Move Progress… to reopen the progress view; Hide closes it without stopping the job.

One move at a time

Only one project move runs at a time in this client. Starting another project's wizard while one is active shows Another move is running.

This window, this project

While this project is moving, only in this window: new sessions and prompts on that project are blocked; Workspace and Files stay visible but are covered and not interactive; Project Settings and Permanently Delete are disabled for it. Other windows and devices do not see this lock.

Quit, reload, and notifications

Quitting or reloading asks for confirmation while a move runs, because the job lives in this renderer. When the move finishes or fails, a web notification appears unless you are already viewing that project's progress (permission is requested when you press Start).

Failure and Try again

Failure messages name how far the move got. After a completed copy, files may remain on the destination while registration still points at the source — use Try again to restart from server choice so the destination is checked again.

Window tab groups

A group tab is a tab in the window tab bar that is only a menu of other tabs — its members are hidden from the bar. The label in the bar is the current member's title (active member, else last-used, else first); the group name is in the tooltip and the member menu header. Click the label to open that member; the chevron alone expands the member list.

Member menu

The dropdown lists every member with a second line project · server (pm7Code tabs have no URL). Arrow keys and Enter navigate like a native menu; the active member shows a checkmark on the right. Footer hint: Right-click a tab to edit it.

Create and organize

Right-click a tab → Make Group Tab… (name required). Move to Group Tab lists existing groups plus None. On a group tab: Rename Group Tab… and Ungroup.

Sync across devices

Groups travel with your window tabs on the account. An older client that strips unknown fields can wipe groups on sync until every client you use is updated.

?tab= in the URL

An instance opened with ?tab=<title> keeps that window tab for this session across reloads. If the tab briefly disappears from the account without a tombstone, the first sync does not treat it as stale local data and move settings to a neighbour — merge puts the held tab back. A tab closed elsewhere (tombstone) still stays closed. Holds are per tab set and clear when you change account.

Active topic stays put on sync

Window-tab settings sync between clients on your account. When this browser still shows the tab set you are editing, a push sends the live window-tab state — not an older autosave snapshot — so your active topic and tab selection do not jump back a few seconds after you switched elsewhere (for example while typing in the WebApp).

Window tab appearance

Settings → Theme Settings → Tabs (or the floating Theme Settings window) controls how window tabs look. A live preview strip at the top uses real .window-tab markup — Active, Inactive, and Hover tabs with sample attention icons — so changes match the actual tab bar, including when no real tabs are visible in that window.

Layout and style

Tab Style (browser or pills), Tab Alignment (left or center), and Show Status Icons (attention emojis on tabs) sync with your account App Theme like before.

Colors card

One compact Colors grid sets tab bar background; active tab background and text; inactive tab text; and hover background and text. Each field shows Default when it follows the active color theme, or a hex override with swatch and reset. Reset tab colors clears all overrides at once. Per-tab colors from the tab context menu still override these globals for that tab only.

Git on the project's engine

When a project runs on another machine's engine — or you use the WebApp — git actions must run where the repository actually lives, not on your desktop checkout. Show Diff, Pull, Auto Update, Open on GitHub, Copy URL, and file Preview Diff now route through that project's engine; status and diff porcelain for the project git dot also run there and exclude uncommitted .pm7-codefrom dirty counts (same rule as Push). Before this fix, the desktop app could call local git against a path that does not exist on the Mac and report false “Everything is up to date” while the remote repo had pending changes.

Connections heal themselves. Switching networks — wifi to 5G, a hotspot, a VPN coming back — removes the old path without telling either side, so a socket can keep reporting that it is open long after nothing gets through. pm7Code therefore does not trust appearances: every connection is checked with a heartbeat. A dead one is spotted within about half a minute, and right away when you return to the window. Agent sessions reattach and replay what you missed; the terminal opens a fresh connection. Nothing to reload.

That same motor can be driven without the GUI: with the pm7code command below, or over the WebSocket API.

Sessions

Worktree isolation and path claims

Writing sessions can work in their own git worktree instead of editing the project checkout directly. That keeps parallel sessions from stepping on each other, and landing back onto the base branch is an explicit step in CView.

Project setting: Worktree isolation

Open Project settings and choose Worktree-isolatie. The choice is stored in <project>/.pm7-code/project.json and applies to that project only. Default is always.

Uit — write in the base checkout

Agents edit the project folder directly (the old behaviour). No per-session worktree.

Opt-in — choose per new session

When you start a New Session you pick whether to work isolated or do a hotfix in the base checkout.

Altijd — writing sessions isolated

Writing sessions automatically get their own git worktree (default). You can still tick Hotfix direct in basis for a one-off edit in the project folder.

Starting and landing a worktree session

An isolated session runs on a branch under the pm7/s- prefix, in a separate worktree path. The agent is told to stay inside that worktree; landing (merge back to the base branch) happens through the app, not via git worktree or push from the agent.

New Topic and New Session options

When the project's isolation is always, the new topic form shows Hotfix direct in basis — geen eigen worktree voor dit topic so you can opt out of a worktree before the first session starts. When isolation is on, the New Session menu can show Hotfix direct in basis (always mode) or Geïsoleerd werken (eigen branch) (opt-in), plus optional Taak / intent and Claim-paden (comma-separated globs such as src/auth/**). Those Hotfix / worktree / claim / intent choices are applied for every agent (Claude, Codex, Pi, and the others) — not only Claude. Start a New Sessionstays disabled while the project's worktree isolation setting is still loading (tooltip: Worktree-instelling van het project laden…), so you cannot miss the Hotfix checkbox when it appears a moment later. The Hotfix row is a plain checkbox — no plus icon.

Worktree status control (title bar + CView)

When the active session runs in a worktree, a small coloured status dot appears, using the same colour scheme as the project git dot so a colour always means the same thing: gray while loading or when none applies; blue spinner while an action runs; red for a git error (for a worktree: an interrupted Sync that needs recovery); brown when behind the reference (origin for the project, master for the worktree), meaning pull or sync first; orange for own work not shared yet (uncommitted project changes, or commits not yet pushed / merged) — uncommitted churn under .pm7-code engine state is excluded and does not turn the dot orange by itself; green when clean and even. Own work wins over behind; tooltip and menu still list every state. The primary placement is the title bar, immediately after the topic name (before in and the project name). The same control also appears in the CView header. Tooltip and aria-label show the branch, comparison against the live base branch name, dirty/ahead/behind counts, and a stale note when the server is unreachable. Click opens the worktree menu (outside click and Escape close it). About every ten seconds the control refreshes the full summary (status plus outgoing and incoming file lists), so when you open the menu the file-count pills are already there — no empty wait for a second round trip. The menu header is one line: the branch name. Below the header and file lists, a notice appears when the agent is still working on a turn — Sync and Push stay disabled until the turn finishes, because Sync temporarily resets the working tree. Then a separator, then Push as the first action (upward-arrow icon): when the file count is known the label reads Push N file(s) to {baseBranch}; otherwise Push to {baseBranch} (not hard-coded to master). Push only when there is own work to land. Another separator, then Sync with {baseBranch} (with a file count when known), Preview changes, and Reset to {baseBranch}…when there is something to discard (disabled when already even with the base). Reset asks for confirmation, then restores this worktree and branch to the live local base: it removes this topic's commits, tracked changes, and new untracked files, while keeping node_modules, .pm7-code engine state, and ignored seeded files such as .env. Git keeps a backup ref first; pm7-Code does not offer a button to restore from it. The conversation is not touched — the agent may still assume its work is there. Reset refuses unsafe conditions such as an interrupted Sync, an in-progress git operation, or the checkout not being on the session branch. Preview changes opens the git-diff overlay for the relevant file list (Changes vs {baseBranch} for own work, or Incoming from {baseBranch} via Sync when behind only). Preview is disabled when the shown list is empty.

Push to base: local first, then GitHub

There are three places: the topic worktree, the local base checkout (the source of truth) and origin on GitHub (its mirror). Push first pulls origin into the local base branch (plain merge, never a stash; a conflict aborts before anything changed), then merges the worktree, then pushes best-effort. Is the worktree behind, Push syncs first by itself (uncommitted work is snapshotted and restored on conflict) and then merges; it stops only on a real conflict, naming the files, with your work untouched. That stop offers Resolve with agent: it sends the conflict to the topic's own agent as a task (merge the base, resolve by hand, keep your intent, do not push); you push afterwards. A failed push keeps the local merge and shows a warning; the next build fetches, builds from the local base and pushes again. While a CORE build is running on that checkout, Push waits for it to finish. A successful merge lands commits onto the base branch but does not remove the worktree. The worktree resets to the new base HEAD (fast-forward for a normal merge; squash commit for squash), stays active, and baseCommit updates so you can merge again after more commits. The status dot stays. Reset clears work inside the worktree but does not remove it. Automatically, a worktree is only released when its topic is parked (or falls asleep after 48h idle), archived or deleted, and only when nothing would be lost: no uncommitted or untracked files, no commits the base lacks, and no seeded ignored file (such as .env) that differs from the base. Otherwise the worktree stays, marked sleeping, and appears in Visualise Worktrees (see below). To remove a sleeping or disposable worktree by hand, use Verwijder on its card there (confirmation when work would be lost). A parked topic that was released gets a fresh worktree when it resumes. Push can stop with stage base when the base checkout has uncommitted changes a merge would overwrite — a short message names the situation and nothing is changed. If those paths are all under .pm7-code/, the message explains that the base tracks pm7-Code engine state and suggests adding .pm7-code/ to .gitignore and running git rm -r --cached .pm7-code. Long git errors in the worktree menu scroll inside a max-height area instead of filling the menu. Push and Auto Update already treat uncommitted .pm7-code the same way: Auto Update commits skip it, and the project git dot, Show Diff, worktree dirty/diffStat counts, and Push N file(s) labels use the same pathspec, so engine rewrites after a successful Push or Auto Update no longer keep indicators orange for engine state alone. Reset still keeps .pm7-code on disk; Verwijder and delete guards can still count engine state when judging whether discard would be unsafe. Committed .pm7-code paths that differ from the merge-base can still appear in outgoing lists — a merge would take them.

Where the conversation lives

A topic's conversation history is always stored in the project folder itself (<project>/.pm7-code/sessions/), never inside its worktree. Releasing, pruning or replacing a worktree therefore never touches the conversation, and a topic opened cold after an engine restart shows its latest turn. Older engines wrote that history into the worktree; such a copy is folded back into the project folder automatically when the topic next starts and before its worktree is removed, keeping what the project folder already had and appending only the newer turns.

Start new session here — blocked on unmerged work

The header New Session control (+) runs this same guard before opening the menu: if blocked, the Unmerged work in this topic dialog opens and the menu stays closed. Start new session here (replace the topic in place) is refused while the topic worktree still has work Push would take, or while the engine cannot judge (pending: null) or is unreachable. The dialog title is Unmerged work in this topic; only OK — there is no Continue anyway, because a fresh session would mint a new worktree and hide the old one. Proceed via Push to {baseBranch} in the worktree menu, or use Fork Topic / New topic to start beside it. Topics that run as a hotfix in the base checkout skip the check. The guard uses a fresh engine round (same definition as the orange Push dot), not the polled sidebar state.

Repos with no commits yet

A folder that is a git repository but has no commits yet (git init only) no longer fails session start with a fatal HEAD worktree error. The session runs in the project folder itself, and a yellow warning banner in CView explains that it is not isolated because the folder has no commit yet. After the first commit, that same topic stays sticky in the base checkout; a new topic can receive a worktree as usual.

Push dots and filter (Projects sidebar)

Topics with an isolated worktree can show a small orange indicator on the topic row. It uses the same definition as the Push to {baseBranch} action: files the worktree changed that still differ from the live base — not merely dirty or ahead on paper.

Orange dot on the topic row

The dot replaces the agent icon on the left of the row — not a badge in the corner. A filled orange dot means the engine judged there is work Push would take. A hollow orange ring means the engine could not judge (pending: null) — never treat unknown as clean. The topic row also gets an orange border: solid when work is pending, dotted when unknown. If the topic is missing from the poll, there is no live worktree (landed, discarded, or cleaned up) and no dot appears. When the server is unreachable, the last known state stays visible but muted (stale).

Push filter in the sidebar

The Show menu and filter bar include a Push section — Push to master — narrows whatever you picked — with the same orange dot icon (not an emoji). Push is an AND squeeze like Today, not an OR status filter: Push + 🔔 shows only waiting topics that also need push. Enabling Push auto-reveals parked topics that still need push, the same way typing a topic name would.

Gray worktree icon on the topic name

When a topic has a living worktree — including a clean one with nothing to push — a small gray branching icon appears after the topic name (alongside pin and parked markers). It means this topic has its own worktree checkout, not whether Push would take work. The orange Push dot on the left is separate: filled when Push would take changes, hollow when unknown. The gray icon does notreplace the agent icon. There is no extra “has worktree” filter. The icon appears as soon as the engine finishes init or attach with a worktree — not only when you open the topic — with the periodic sidebar poll as fallback. When the server is unreachable, the icon stays but is muted (stale), with tooltip explaining last-known status.

Many WebApp tabs: background polling pauses

With many browser tabs open, background tabs (when the document is hidden) skip git and worktree-pending poll rounds; when you return to a tab it catches up once. That keeps tab switches, session open, and screenshot upload responsive instead of every tab hammering the engine. On the engine, concurrent pending-worktree scans for the same project folder coalesce, with a small global cap — failed scans stay unknown (hollow orange ring, stale) instead of clearing dots to empty.

Visualise Worktrees (project and server menus)

Open Visualise Worktrees from the project menu (project name in the CView header or title bar, next to Project Settings) or from the server menu (server name in the title bar). This is not in the worktree status menu. It works even when the current session has no worktree; if it does, that card is highlighted. The dialog stays within the viewport; the body scrolls when there are many worktrees.

Project menu scope

Shows only worktrees whose session belongs to that workspace project. The engine registry is keyed per folder and multiple workspace projects can share one folder, so the client filters here. Worktrees filtered out are counted, not silently omitted: N van andere projecten in deze map and, separately, N zonder bekend topic (deleted or unknown sessions).

Server menu scope

Shows all registered worktrees on that engine — one block per base checkout, with workspace project names that live on that base in the block header. Each card can show its project name. Only worktrees pm7-Code created appear in the registry.

Worktrees dialog

Title Worktrees. The base checkout is a card on top (label Basis). Live worktrees appear as cards below — current session first and highlighted, then active, sleeping, and orphaned. Landed and discarded worktrees sit under a collapsed Historiek section. Refresh reloads from the engine. By default only worktrees with work Push would take are shown (same judgement as the sidebar orange dot), plus any that could not be judged (hollow ring). A checkbox Ook worktrees zonder werk om te pushen tonen reveals the rest; when some are hidden, the UI shows N verborgen. Live and history worktree cards are clickable when this client knows the session: click jumps to that topic, closes the dialog, and reveals it in the sidebar. If the topic is archived (typically landed or discarded), the app opens the read-only archived preview — it does not silently restore it. Cards whose session this client does not know stay inert (tooltip: topic unknown).

What each card shows

Session name (or branch as fallback), branch, orange ↑N / brown ↓N file pills (same meaning as the worktree menu), state badge (actief, slaapt, verweesd, geland, verworpen), and a Preview button. On server scope, the project name appears on the card. Missing checkouts show why git status is unavailable. Clickable cards show a tooltip hint to open the topic or view the archived preview.

Path claims across sessions

Sessions can register which paths they intend to edit so others see the overlap early. Agents emit a fenced pm7_claim block with paths and a human-readable summary; empty paths release the claim.

A claim is a signal, not a lock. Another topic can still edit a claimed file; nothing is blocked and nothing is enforced. What a claim does is make the intent visible: the other agent gets the active claims in its context so it can steer clear or coordinate, and the human sees the overlap strip. Each worktree is its own checkout, so two topics editing the same file only meet at merge time.

Overlap strip

If your paths overlap another session's claim, CView shows a warning strip naming that session and the overlapping paths.

Release

Each overlap row has a Releasebutton that clears the other session's claim without waiting for it. Your own claim is released from the worktree status menu, or automatically when the topic closes.

Intent banner

Optional intent text from a New Session (or another session) can show as a short banner — coordination context, not a hard claim.

Worktree isolation is about where a writing session edits. The Git Service still handles commit-and-push proposals from the agent; landing a worktree onto the base branch is a separate CView action.

WebApp

App Themes

On the WebApp, an App Theme is a named profile that bundles the full look and layout of one device: the active color theme, fonts, visual style, panel visibility, and sidebar and Assistant column open state and width. The macOS desktop app does not use App Themes — there, account settings remain the source.

Each device remembers its own active theme. The theme definitions sync with your account, so the same profiles are available on every WebApp device you use. There is always one active theme; a Default theme is created from your current look the first time you need it.

Settings → Appearance

Create, rename, duplicate, and delete App Themes. Save current as App Theme captures everything the profile covers. Switching themes applies the full bundle immediately.

What travels with the theme

Color theme choice (including window-tab colours — tab bar, active, inactive, and hover — see Window tab appearance), all font settings, CView frame mode, tab bar style, shadows, Browser border color, scrollbar visibility, terminal full-height mode, tab bar visibility, CView tool visibility, and sidebar and Assistant column layout.

URL preview

Add ?theme=<id-or-name> to the URL to preview a theme in that window only. The device choice is untouched; picking a theme in Settings clears the override.

Settings

Settings Backup

Settings → General has a Settings Backup section where you point pm7Code at a private Git repository. Every export saves your settings to your account first, so the backup always matches what you see in Settings, then commits and pushes every setting, prompt, memory, skill, and theme to that repo.

GitHub Repository

Enter a remote URL the engine can already push to — SSH key or gh credentials, never a token in the URL. The repo is cloned once, then updated on each export.

Export Now

Runs an immediate export and push. If secret findings block the export, review the list and choose Export anyway to override.

Automatic Backup

On by default when a repository URL is set. Exports automatically shortly after every settings save. Secret findings always block automatic exports; only Export Now can override them.

The last automatic backup status is shown on the device — timestamp, commit, push result, or why an automatic run was blocked or failed.

CLI

The pm7code command

pm7codeis a one-shot, scriptable entrypoint that ships with pm7Code. Give it a prompt and it runs a single turn, prints the agent's final answer to stdout, and exits — the same shape as claude -p, but through the pm7Code motor. Pass the prompt as an argument or pipe it on stdin.

# One-shot against the local motor (auto-started if needed)
pm7code "summarize what changed in this repo"

# Pipe the prompt via stdin, run it through Codex
echo "write a haiku about pty buffers" | pm7code --agent codex

When you point it at a loopback address and nothing is listening yet, the CLI starts a local motor for you and reuses it on the next call. Pointed at a remote address, it never spawns anything — it only connects.

# Machine-readable output for scripts/CI: NDJSON events + a final result line
pm7code --json --agent claude "list the open TODOs"

# Continue the most recent session in this folder, then resume an exact one
pm7code --continue "now add tests for it"
pm7code --resume <pm7SessionId> "follow up on that"

# Talk to a remote motor over your tailnet (paired device + opt-in full-auto)
pm7code --server ws://100.x.y.z:8787 \
        --device-id "$PM7CODE_DEVICE_ID" \
        --device-key "$PM7CODE_DEVICE_KEY" \
        --full-auto "deploy the site"

Permission stance

Locally it runs full-auto by default so scripts are not blocked. Remote is safer-by-default: it reads, but declines mutating actions unless you pass --full-auto.

Resumable by design

CLI sessions are always persisted. The --json output gives you a durable pm7SessionId you can later --resume, or use --continue for the latest session in a folder.

Three agents

The CLI exposes claude, codex, and pi. Use --model to override the model for the chosen agent.

Options

OptionWhat it does
--agent <claude|codex|pi>Agent runtime to use. Default: claude.
--model <name>Model override for the chosen agent.
--output <text|verbose|json>Output mode. Default: text.
--verboseAlias for --output verbose. Progress lines go to stderr.
--jsonAlias for --output json. NDJSON events plus a final result on stdout.
--full-auto / --no-full-autoForce the permission stance. Default: full-auto locally, safer-by-default remote.
--server <ws-url>Server URL. Default: ws://127.0.0.1:8787 (or env PM7CODE_SERVER).
--device-id <id>Device id for a remote motor, obtained by pairing (or env PM7CODE_DEVICE_ID).
--device-key <key>Device key for a remote motor, obtained by pairing (or env PM7CODE_DEVICE_KEY).
--cwd <path>Working directory for the session. Default: the current directory.
--continue, -cResume the latest session in this directory for this agent.
--resume <id>Resume a specific pm7 session id (the one returned by --json).
--timeout <sec>Maximum turn duration in seconds. 0 means no timeout. Default: 600.
-h, --helpPrint the built-in help and exit.

Environment variables and exit codes

The CLI reads a few environment variables so you can keep the server URL and device credential out of every command line.

VariableMeaning
PM7CODE_SERVERDefault server URL for the CLI. Falls back to ws://127.0.0.1:8787 when unset.
PM7CODE_DEVICE_IDDevice id for a remote motor, obtained by pairing. The motor stores paired devices in ~/.pm7-code/devices.json.
PM7CODE_DEVICE_KEYDevice key matching PM7CODE_DEVICE_ID. Sent in the hello; the motor only stores a hash of it.
M2_PORTPort the motor listens on, and the port in the CLI default URL. Default: 8787.
M2_HOSTBind address for the motor. Default 127.0.0.1 (loopback only). Set 0.0.0.0 to expose it over your tailnet.

Exit codes make the CLI safe to branch on in scripts and CI.

Exit codeMeaning
0Success.
1Agent error — the turn itself failed.
2Usage error — bad arguments or empty prompt.
3Auth error — missing/invalid device key, or a rejected pairing code.
4Network / connection error, or a protocol-version mismatch.
124Timeout — the turn exceeded --timeout and was interrupted.
The CLI is a thin wrapper; all the power lives in the motor. When one-shot prompts are not enough — a session you keep open, the live event stream, approvals, reconnect and replay — drive the motor directly over the WebSocket API.

Claude

Claude auth errors in CView

These messages are about Claude login on the agent engine — not your pm7Code account sign-in (see Expired sign-in).

401 during a refresh race

When Claude returns 401 but the OAuth token is still valid — a refresh race — pm7Code asks you to send the message again in this session. It does not tell you to click Restart; there is no such control, and Start new session would drop your conversation context.

Login truly expired

When Claude login has actually expired, log in once in a terminal on the agent machine: run claude, then /login. Send the message again in the same pm7Code session — your topic context stays.

Sign-in

Expired sign-in

When your auth token has expired, pm7Code treats you as signed out for server-backed features. Workspace changes are not saved until you sign in again.

What you see

On native clients the login gate shows: Your sign-in has expired. Sign in again to continue.

Projects sidebar

When the server is reachable but cannot verify your identity, the sidebar names the failure and offers Sign in again alongside Retry — so you know the session expired rather than a generic sync stall.

Troubleshooting

When a Git Service job fails

A failed job means pm7Code deliberately stopped before completing the commit or push. Use the card message as the source of truth and send a fresh request after fixing the cause.

ProblemWhat to do
A file changed after the request was madeAsk the agent to inspect the latest file state and send a new GitServiceRequest.
Another topic touched the same fileResolve which topic owns the file, then let one of them create a fresh request.
There are unrelated staged changesUnstage or commit those changes separately. The Git Service will not mix them into this job.
The push failedCheck the visible error in the card. Typical causes are auth, network, or a remote branch update.
Nothing changedNo commit is needed. A well-behaved agent should silently skip the request.