Claude Code and Codex already write down everything they do, in files on your disk. Nothing reads them together. Plancia does: one row per project tells you what to do next, Resume reopens the conversation that wrote the task, and a spoken recap of the day closes with what is worth doing. The rest stays folded, one click away.
Website: plancia.
Local-first: no telemetry, no account, no server of ours. The only thing that
goes out is the work you explicitly hand to an agent, and it goes through the
claude or codex command already on your machine, under your own
subscription. No dependencies to install: Python 3 and its standard library,
Swift for the app.
Every screenshot in this README is the app running on the demonstration archive
(tools/demo-data.py), never on anyone's real data.
Plancia 2.0 is a native SwiftUI app for macOS 26 or later: the system controls and the Liquid Glass materials, a sidebar with six sections, the system search field in the toolbar and an inspector on the right. No logo, no web page inside a window.
Memory as a map. Every note is a node, coloured by kind, and every project (or kind of note, for the ones that belong to none) is an island with its name on the edge. The links between islands are drawn as ribbons, so you see at a glance which projects share what you know. Hover lights a note and its neighbours, drag a node and its island follows, pinch or scroll to zoom. The physics runs off the main thread and stops by itself when the picture is still.
Zoom in and the nodes carry a short human title instead of their file name:
Wood. Settings has a Style: System, or Wood, a modern take on the skeuomorphic dashboard of the app icon. Mahogany boards in the sidebar and under the toolbar, solid brass for the selection, warm paper for the content. Controls and glass stay the system's.
Light and dark, and text size on ⌘+, ⌘- and ⌘0:
The sections have their own pictures further down: Search, Jarvis, All tasks and Projects.
| source | where | what it gets |
|---|---|---|
| Claude Code sessions | ~/.claude/projects/**/*.jsonl |
date, project, opening prompt, turns, tools, tokens |
| Claude memory | ~/.claude/projects/*/memory/*.md |
project descriptions, [[wiki]] links |
| skills, plugins, routines | ~/.claude/skills, plugins, scheduled-tasks |
what your Claude Code can do |
| GitHub | gh repo list, recent commits |
repos, commits, real material for posts |
| local git | your code roots | branch, uncommitted changes |
| Codex sessions and goals | ~/.codex/sessions, goals_1.sqlite |
the same, plus what Codex is stuck on |
| Claude Code task lists | ~/.claude/tasks/<session>/*.json |
what is open right now, per session |
| session hooks | SessionStart, SessionEnd |
which sessions are open right now |
Sources are never modified. Plancia reads them and stays out of the way.
See docs/NOVITA.md for what changed recently and why.
git clone https://github.com/nerln/plancia.git ~/dev/plancia
cd ~/dev/plancia
./bin/plancia install # command, MCP server, hooks, skills, autostart
./bin/plancia init # builds your project map from repos, folders, memory
./mac/build.sh --install # builds Plancia.app into /Applications (macOS 26 or later)plancia uninstall puts everything back. Your data stays in ~/.plancia/.
macOS comes first: that is where the native app lives. The rest of Plancia is Python and a local web server, so it also runs on Windows and Linux, with the dashboard in your browser. You need Python 3.9+ and Claude Code or Codex.
Windows (PowerShell):
git clone https://github.com/nerln/plancia.git $HOME/plancia
cd $HOME/plancia
python bin/plancia install # command, MCP server, hooks, skills, autostart
python bin/plancia init # builds your project map
python bin/plancia serve --open # the dashboard, in your browserLinux:
git clone https://github.com/nerln/plancia.git ~/dev/plancia
cd ~/dev/plancia
python3 bin/plancia install
python3 bin/plancia init
python3 bin/plancia serve --openinstall also writes a plancia command. On Windows it is a plancia.cmd shim
in %LOCALAPPDATA%\Plancia\bin, and it tells you to add that folder to your PATH
if it is not there yet; bin/plancia.cmd does the same job from inside a clone.
On Linux it is a link in ~/.local/bin. plancia uninstall puts everything back.
If python is not on your PATH (the python.org installer does not add it by
default, and python can be the Microsoft Store stub), use py -3 bin/plancia install instead. pip install is not a supported route yet: the package does not carry the
dashboard files or the bin/ scripts, so use the clone.
What works the same: the dashboard, the plancia_* MCP tools in Claude Code and
Codex, the session hooks and the memory recall, the skills, search, the recap,
Resume (it opens a terminal in the right folder), and starting the server at every
login.
What each system uses underneath:
| macOS | Windows | Linux | |
|---|---|---|---|
| start at login, daily recap | launchd | Task Scheduler, or the Startup folder if that is refused | systemd --user, or ~/.config/autostart |
| Resume opens | Terminal | Windows Terminal, else a new console window | the first of x-terminal-emulator, gnome-terminal, konsole, xterm |
| clipboard | pbcopy |
clip |
wl-copy, xclip or xsel |
| spoken recap | say |
the built-in speech synthesizer | espeak-ng (or espeak) and an audio player |
| notification | osascript |
PowerShell balloon | notify-send, if installed |
On Windows and Linux there is no native app: open http://127.0.0.1:7773 in Chrome or Edge and choose Install Plancia. It gets its own window and icon, and it still opens with the server off, showing the last state it saw. Safari on macOS does the same with Add to Dock.
What does not exist outside macOS: the native app, its menu bar item, the
plancia:// URL actions and the hands-free voice panel. plancia jarvis "..."
from a terminal still works. If a piece is missing on your machine the rest
carries on: no notification tool means no notification, and no clipboard tool
means nothing is copied. With no speech engine, plancia say, plancia voice prova, plancia recap --speak, plancia ask --speak and plancia jarvis --speak
say so and what to install, the MCP speak
action answers letto: false with the reason, and plancia doctor reports the
voice as missing. The dashboard keeps working too: the recap, "Ask" and Jarvis
answer with the text and a voce: null field plus a nota_voce explaining that
there is no speech engine, and only the playback is skipped ("Listen" shows
that note instead of a generic error). Outside macOS the voice engine is reported by
its real name (System.Speech, espeak-ng) and the voice list comes from it. On Windows,
Resume needs Windows Terminal for a lost task when claude is a .cmd file (an
npm install): its multi-line prompt cannot be handed to cmd.exe safely, and
Resume says so instead of opening a broken command. On Windows the server starts at login but is not restarted after a crash, and
its errors are not logged (launchd on macOS and systemd on Linux do restart it).
A second plancia serve while the login one is running says so (and with --open
opens the browser on it) instead of failing on the busy port. plancia esporta --apri
opens the file with the system's own opener (open -R, os.startfile, xdg-open).
Folders that hold projects without being one (an external disk, another projects
folder) go in config.json under contenitori, a list of paths, next to the ones
Plancia recognises by itself (~/dev, ~/Siti, the Google Drive folders). On macOS
that includes the disks you used to add by hand: an external disk is a container
only if it is listed there ("contenitori": ["/Volumes/Disco/dev"]), and
plancia doctor prints the containers in use. Start at login and the daily recap
never load launchd, Task Scheduler or systemd jobs from a throwaway environment: if
the process HOME is not the user's real home (or PLANCIA_HOME points outside it)
the files are written but not loaded ("file scritti, non caricati (HOME di prova)").
PLANCIA_AUTOSTART_FORZA=1 forces the commands, for a machine where they are stubs.
The commands Plancia builds for each system are covered by the suite, but Windows and
Linux have had far less real use than macOS: plancia doctor tells you what is
connected.
The same data in a browser, on any system with Python: python3 bin/plancia serve --open
(python bin/plancia serve --open on Windows). It follows the Mac app: system fonts, six
sections in a sidebar, Today as one reading column, Tasks as a table with a detail panel,
Memory with a physics graph on canvas, search in the top field. It installs as a web app
from the browser menu. This is what Windows and Linux use, and a Mac that cannot run the
2.0 app.
The app. A native SwiftUI window (2.0, macOS 26 or later): a sidebar with
Today, Tasks, Projects, Social, Memory and Archive, the system search field,
an inspector on the right for whatever you select, and Settings for language,
appearance and style. Style is System (the standard macOS look) or Wood, a warm
skeuomorphic one with mahogany boards in the sidebar and brass for the selection,
drawn from the app icon. Text size follows ⌘+, ⌘- and ⌘0 (seven steps, 85% to
125%). Memory has a third mode, Map: every note as a node in a physics graph you
can drag, with levels 1, 2 and All and a smooth zoom, running off the main thread.
Plus a menu bar item and the voice panel. It supervises the backend, so there is
nothing to start by hand. On macOS 13 to 15 the 1.1.0
app is the last one that runs; the dashboard in the browser works everywhere. plancia://recap,
plancia://jarvis, plancia://ask?q=…, plancia://open?view=projects and
plancia://pdf are
URL actions you can bind to a system shortcut, Raycast or Shortcuts.
Claude Code and Codex. Seven plancia_* MCP tools in every session of both, a
SessionStart hook that hands Claude your current state as opening context, and
two skills that tell it when to read from Plancia and when to write back. Seven
and not twenty: the six that get used stay exposed, the rest sit behind one
plancia tool you call with azione. Tool schemas are paid for in every single
request of a session, so the surface is the bill. Measured: 1195 tokens per
Claude Code session and 1020 per Codex session, down from 2870 and 2196.
The terminal. plancia recap --speak, plancia ask "what did I ship this week?", plancia task add, plancia cerca "a phrase you remember",
plancia projects.
Transcripts are the largest thing you own and the hardest to get back into. A session title tells you nothing six weeks later; the sentence you are trying to find is somewhere in the middle of a conversation.
Plancia keeps an FTS5 index over the prose of every turn, yours and the agent's,
from Claude Code and Codex. Tool results stay out on purpose: they are most of
the bytes and almost never the thing you remember. On this machine that is 13,000
turns from 1,287 transcripts, 20 MB indexed out of 979 MB on disk, rebuilt from
scratch in 5 seconds and kept current incrementally, which costs one stat per
unchanged file.
Every hit comes back verbatim with the file and the line it came from, so you reopen the moment instead of reading a summary of it.
plancia cerca "the blending denominator"
plancia cerca "cookies" --project moloIn the dashboard, / opens search from any view; chips above the results count
the hits per project across the whole index, not just the page. In Claude Code
and Codex it is plancia_search.
A session used to land in the project of the folder it was opened from. That
works for Codex, which is opened inside the project. It does not work for Claude
Code: measured on this machine, 199 sessions out of 587 were opened from the
Drive root, from ~/dev or from the home folder, places you work on everything
from.
Plancia now also looks at what the session touched: the files in its tool_use
blocks and the absolute paths inside Bash commands, counted per project folder.
If the folder it was opened from says nothing, the most touched folder wins; if
that folder is already a project, it is kept unless 70 percent of the paths are
somewhere else. Every row carries the inferred folder and the reason, so the
attribution can be checked instead of trusted.
plancia sessioni # the catalogue, by project
plancia sessioni --progetto molo --giorni 30
plancia sync --riattribuisci # recompute the whole archiveA tilde at the end of a row, and the "inferred from paths" note in the
dashboard, mark the sessions attributed this way. Plancia's own internal calls
and throwaway sessions stay out of the way: --tutte shows them.
Plancia collects the day from real data, sessions and commits and tasks opened and closed and posts and what each project is waiting on, and turns it into something written to be heard: short sentences, no lists, no markdown, no file paths read out loud.
Two engines for the text. The template one is deterministic, costs nothing and
always works. The other passes the same data to Claude Code in headless mode
(claude -p) and gets a better told version in about eight seconds. If Claude
does not answer in time, the template takes over and you never notice.
Two kinds of voice. A local neural one when it answers: Kokoro (not installed by default, see Jarvis below), then Pocket, then Voicebox if its backend is up, which is how you get your own cloned voice. Otherwise the macOS system voices, which are always there, need no setup and start instantly. The system voices handle Italian, English, Spanish, French, German and Portuguese; each neural engine covers the languages its own voices do.
plancia recap --speak # today, out loud
plancia recap --lang en # in English
plancia ask "where did I leave the transcription pipeline?" --speak
plancia daily on 08:45 # every morning, as a notification
plancia daily on 08:45 --voce # every morning, out loudAsking a question goes through Claude Code with your Plancia context attached, so the answer is grounded in what actually happened, not in a guess.
The recap does not stop at the facts. Plancia looks for signals in the data and turns them into proposals, each with an action already prepared: a failed run to retry, a Codex goal out of quota, files uncommitted since yesterday, an approved post that never went out, a project whose declared next step has gone stale. Proposals only ever come from signals, never from a model's hunch, so a quiet day gives you a short recap instead of an invented suggestion. Say "do it", or "the second one", and it runs.
One row per active project, on Today, next to the recap: its first open task,
or its declared next step when nothing is open, grouped by area, sorted by
deadline and then by last activity. Up to seven rows show per group; the rest
sit behind an "N more". It needs the area map from plancia riordina to
group by anything but a flat list.
⌥Space anywhere opens a glass panel and turns the microphone on. A waveform follows
your voice while it listens, the answer scrolls in as it arrives, and it starts
speaking with the first sentence, not when the whole answer is done.
Jarvis reads, and proposes. The model behind the panel is read-only: the tools that write are denied by name, not just left off a list. Phrases like "note a task", "I did that", "archive Atlas", "do it" or "resume task 4" never run on their own. Each one becomes a card that says exactly what would happen (which agent, in which folder, whether it may edit files, which session it picks up) and nothing happens until you press Confirm on the card. Saying "yes" out loud does not confirm. Esc or Cancel throw the card away, and so does closing the panel. The only things that happen without a card are opening a view and changing how fast it speaks.
The microphone opens only when you ask, with the shortcut or the microphone button, and you can see it: an orange dot and "Microphone on" in the panel, next to the system's own indicator. Recognition runs on the Mac. If dictation for your language is not installed for on-device use, it says so and you type; audio never goes to a server. It closes by itself after each sentence and reopens only if you turn on "Continuous conversation" in the panel menu. Esc or Stop ends everything at once.
The voice is a neural one when there is one: Kokoro first, then Pocket, then Voicebox, all running locally, sentence by sentence, so the second sentence is being made while the first plays (the first sentence is cut at its commas, so the sound starts sooner). Without one it uses the enhanced or premium voices installed on the Mac and says so at the bottom of the panel. It never uses the basic robotic voice: with none installed it stays text-only and tells you where to download one.
Kokoro is not installed by default. plancia voce installa builds a Python
environment under <PLANCIA_HOME>/voce, tells you it will download about 354 MB of
model files, and asks before doing it. It then runs as one warm background process of
roughly 450 to 700 MB (about 1 GB for a moment on a long sentence) that starts when
Jarvis opens and quits after 5 minutes of silence; if it dies or is too slow, the
next engine speaks and the panel footer says so. The voice per language is
voce_kokoro in config.json (defaults: if_sara for Italian, af_heart for
English, ef_dora for Spanish; im_nicola is a male Italian one). plancia voce prova says which engine Jarvis would use and why, without playing anything. Tried on
macOS only.
The text field at the bottom covers the case where the microphone is unavailable.
plancia jarvis "remind me to write the migration note" # shows the card, asks [y/N]The terminal and the dashboard (Windows and Linux) use the same rules. There is one
Jarvis, read-only: the old second one, which kept a model with the write tools open
and ran what you typed, is gone. plancia jarvis prints the card and asks you to
confirm at the keyboard; without a real terminal (a script, a pipe, another agent
calling it) it never confirms. On the dashboard the card shows up with Confirm and
Cancel, and the Relaunch button goes through it too.
Claude Code has had voice input since March 2026: you hold the spacebar and dictate. It is input only, and by design there is no hands-free mode. This is the other half: it speaks back, and it can act once you confirm.
Claude Code keeps its task list in one folder, Codex keeps its goals in a
different database, Plancia has its own. None of the three knows the other two
exist. This view reads all of them, normalises the states to open, in progress, blocked, done, gone, and shows one list.
Resume is the first thing a row offers. A task carries the id of the
session that wrote it, so the button on its row does not relaunch anything
from scratch: it reopens the actual conversation, in one of three states.
Alive, and Resume copies to the clipboard the message to paste into the
conversation that is already running (resume task 42 of Plancia: <title>):
there is nothing to launch. Closed, and pressing Resume opens a visible
Terminal on its own, running claude --resume <id> (or codex resume <id>)
in the task's own folder; Plancia never touches a transcript from a second
process. Lost, because the session was never recorded or has expired, and
then it says so instead of pretending, and starting over, with the context
written by hand, is the only option left.
plancia lavagna # every open task, in the terminal
plancia riprendi 42 # resume task 42, in its own state
plancia riprendi 42 --apri # do it now, exactly what the button does
plancia lanci # how a background dispatch wentSending work off in the background is the other, secondary path, for when
resuming is not what you want: plancia riprendi 42 --background --scrive --istruzioni "rerun the ablation" runs it unattended, inside that task's own
session (claude -p --resume <id>, codex exec resume <id>, same id, its own
folder), and records the outcome. It never opens a new session behind your
back: if the session is still open somewhere nothing starts and you get the
message to paste (--copia asks for a copy instead), and only when the
session is really lost does a new one start, said before it does. The same
goes for the Relaunch and Resume buttons, the MCP tool and Jarvis. If the
ChatGPT/Codex desktop app holds a Codex thread open, the run stops and says
so instead of failing silently. The default is read-only; --scrive lets
the agent write, and that is a choice you make every time. plancia manda "rerun the ablation" --agente codex --progetto atlas is the older alias for
the same thing without a task id: it still works but prints a deprecation
warning on stderr and is going away in a future release. The run lives inside
that command, so it waits for the agent to finish before it exits. Inside Claude Code
and Codex, the same resume lives behind the plancia tool with
azione="riprendi" and the task's id.
Other tools should not have to poll a database to know something happened. Every
meaningful event is appended to ~/.plancia/eventi.jsonl, one JSON line, schema
plancia.evento/1:
{"schema":"plancia.evento/1","id":"9f2c…","ts":"2026-08-02T09:14:22Z",
"tipo":"lavoro.completato","titolo":"Rerun the ablation","progetto":"atlas",
"origine":"cantiere","dati":{"agente":"codex","modo":"esegui","token":22800}}Types: lavoro.avviato|completato|fallito, task.creato|chiuso,
post.pubblicato, progetto.archiviato|aggiornato, riepilogo.pronto. A
consumer keeps the id of the last event it saw and asks for what came after, with
plancia eventi --dopo <id> or GET /api/eventi. The file is append only and
rotates at 5 MB.
Plancia reads Codex sessions from ~/.codex/sessions alongside Claude Code's,
and registers its own MCP server inside ~/.codex/config.toml. Both agents see
the same projects, the same tasks, the same tools. The Agents view shows
who worked on what and when the two handed work to each other, inside the
Archive.
Every claude -p costs about five seconds of startup before it even thinks. In a
spoken conversation that is five seconds of silence per question. Plancia takes
three routes, in this order:
| route | when | cost |
|---|---|---|
| commands | open a view, note a task, close one, archive a project | 0.1 s |
| data answers | how many tasks, what should I pick up, how much did I work | 0.1 s |
| Claude, kept warm | anything else, with the plancia_* tools open |
2.7 s |
The Claude process stays alive between questions instead of being restarted, so only the first one pays the startup, and the panel warms it up the moment you open it. The daily recap is precomputed at the end of every cold pass: asking for it costs 20 ms instead of ten seconds.
bin/plancia-hook --prova prints what it would hand to Claude without queueing
anything: testing the hook must not leave a session in the archive that never
happened.
sources ──▶ sync ──▶ SQLite ──▶ briefing.md · recap · REST · voice
Two rhythms, because reading twenty repos to find out you just opened a session is a waste:
- hot, every two minutes, ~40 ms: the hook queue and the new tail of the transcripts. What you are doing right now.
- cold, every thirty minutes, ~1.5 s: memory, skills, repos, local git, project housekeeping, both search indexes, recap.
The cold pass used to take 40 seconds, and 20 of those were one folder. git status inside a cloud-synced folder has to check every tracked file with the
file provider: measured cold on a 681 file repo, 2 minutes 51 seconds, against
10 ms for a repo on disk. Folders are now read eight at a time, a folder that
does not answer within four seconds is remembered and left alone for six hours,
and a status that never arrived is stored as unknown rather than as clean.
plancia flusso prints every source, where it comes from, which pass reads it
and how fresh it is.
A project born from a folder you worked in once, three weeks ago, is not an active project: it is a memory. Plancia archives it on its own after two weeks if it has no repo, no memory note and fewer than three sessions. Anything you declared yourself is never touched. By voice: "archive the video project", or "the Ard footage is finished".
A project is whatever you say it is: a GitHub repo, a folder, a memory note, or
all three. plancia init proposes a map from what it finds; you correct it in
~/.plancia/seed.json. Sessions that run from a generic folder get attributed by
keyword, and re-attributed on every sync as you refine the keywords.
A project map is only useful if it can be corrected, and correcting 122
projects one at a time never happens. plancia riordina --proponi computes a
map of parents for every project (an area like a thesis, or a real repo with
its worktrees) and writes it to a file instead of the database, so you can
read it before anything changes.
plancia riordina --proponi # writes the proposed map to a file
plancia riordina --mostra <file> # prints it as a table
plancia riordina --applica <file> # assigns the parents, states and mergers in it
plancia riordina --annulla <batch> # puts back exactly what it changedThe file is plain JSON, one row per project, and you can edit it by hand or
have an agent that has studied your projects write it. Beyond padre (the
parent's key) a row can carry:
[
{"chiave": "old-experiment", "inglobato_in": "atlas",
"motivo": "the code now lives inside the atlas folder"},
{"chiave": "thesis-draft", "stato": "concluso",
"motivo": "handed in last June"}
]stato:attivo,archiviatoorconcluso. Missing means the state is left alone.inglobato_in: the project this one was folded into. It means parent = that project, statearchiviato, and a line "Inglobato in atlas: " added to the end of the project's summary. If that project cannot be a parent (it is automatic, or is itself a child) the parent is left alone but the state and the line are still written, and--applicasays so.motivo: the reason, one sentence. It is required on every row that has astatoor aninglobato_in;--applicarefuses a row without one and--mostramarks it[DA CORREGGERE].
--mostra prints all of it as one table (key, parent, rule, state, reason).
A row is all or nothing: if the parent is refused, the state does not change
(an inglobato_in is the one exception, see above). A file that does not parse
is one line of error, not a traceback, and --applica exits with 1 when it
refused a row.
A manual project is only touched by a row that names it with a parent, a state
or an inglobato_in; a project that is not in the file is never touched. The
format is documented in full at the top of plancia/riordina.py.
Applying is one batch, and undoing it restores each project's previous parent, state and summary, not just a blank one. Undo works field by field and only where the field is still what the batch left: a state you changed by hand afterwards, or set with a later batch, is not overwritten. Today (the recap view) and Next up group projects by area once this map exists; before it does, they fall back to one flat list, so nothing breaks for a fresh install.
Two groups of work on the same machine that must not see each other: a project
shared with someone else, and the rest. compartimenti in
~/.plancia/config.json names one or more compartments (each with its
cartelle and sessioni); everything else is the default one. Without it
Plancia does what it always did.
With it, every object gets a compartment from the data it already has: a session
from its id, its folder and its transcript; a task from the session that made it,
or from its project; a project from its paths and the memory notes linked to it;
a memory note from the file it lives in (Claude Code's automatic memory of a
folder belongs to that folder's compartment). Then each surface shows only its
own. The session briefing and the recall of notes "written in other folders"
leave the other compartments out. The MCP server filters what it reads, and a
write on another compartment's project, task or post is refused with a plain
message. The dashboard is your view, not an agent's, so it shows everything but
separated: a selector at the top picks the compartment (the default one first),
every view follows it, and what you create there belongs there.
?compartimento=name in the address opens it on one.
A session with signs of two compartments sees nothing. This decides what Plancia shows; it is not a security boundary, same user and same disk.
The plancia command in a terminal works out its compartment the way the MCP
server does, from CLAUDE_CODE_SESSION_ID and the current folder: a command run
from a session of a named compartment sees that compartment only (board, events,
runs, briefing, search, sessions, recap, ask, jarvis, export, and the rest), and
a write on another compartment's project or task is refused. A human terminal
with no session id and a current folder outside every named compartment is the
default one and sees the default one; inside a named compartment's folder it
sees that one. The dashboard's voice assistant works from the compartment picked
in the selector, and from a named compartment a free-form question is answered
with that compartment's data in the prompt, not by the warm process with the
Plancia tools. A run started from a compartment belongs to it, even when its
project has no folder. Commands that administer all of Plancia (init, riordina --applica, riprendi --backfill) are refused from a named compartment. With
compartments on, briefing.md is not written (one file per compartment instead)
and it comes back when they are removed.
Limits worth knowing: folder rules compare POSIX paths (starting with / or
~), so compartments and the guard below are for macOS and Linux only. On Windows
they are switched off, on purpose and in the code: a compartimenti or guardiano
entry in config.json is ignored, every session sees everything (the briefing is the
plain one), the guard exits at once without denying anything and says "not supported
on Windows" once per session, and plancia doctor and plancia guardiano say so.
The daily recap that a scheduler runs has no session, so it is the default
compartment's.
Transcripts are read by byte offset, not by line. They are hundreds of megabytes and they grow. Plancia keeps the offset of every file and only reads the new tail; lines over 256 KB (tool results) are never parsed, only probed. A full re-read of 430 sessions costs 1.5 seconds, and rebuilding the turn index from scratch on top of it another 5.
A record's type is matched in full. Inside message.content there are other
type fields (text, tool_use, tool_result) that come before the real one,
so searching for "type":" gives you the wrong answer. Plancia searches for
"type":"assistant" and "type":"user" whole.
bin/plancia command
bin/plancia-mcp MCP server (stdio)
bin/plancia-hook session hook, 20 ms
plancia/store.py schema and data access
plancia/ingest.py reading the sources
plancia/turni.py the full text index over what was said
plancia/recap.py the daily recap
plancia/voice.py speech, playback, listening
plancia/briefing.py what Claude sees
plancia/compartimenti_viste.py what each compartment sees
plancia/actions.py writes, shared by HTTP and MCP
plancia/api.py local server and REST
plancia/mcp.py JSON-RPC over stdio
plancia/lavagna.py the unified board
plancia/cantiere.py dispatching work to an agent
plancia/proposte.py what is worth doing, from signals
plancia/eventi.py the append only event log
site/ the website, published on GitHub Pages
mac/Sources/ the macOS app (SwiftUI, macOS 26 and later)
web/ dashboard, no framework, no build step
Data lives in ~/.plancia/: plancia.db (SQLite), seed.json, token,
briefing.md, audio/. Keep it out of any synced folder: a SQLite file inside
Dropbox or Drive will corrupt.
Today (the recap, the rhythm, the proposals, and Next up: one row per project, grouped by area, with what to resume), Search, All tasks, Projects, Social, Memory, Archive (sessions, agents, skills). Everything else goes through ⌘K. On first run a guide explains the parts that are not obvious, and it stays available under "Guide".
Python 3.9+ and Claude Code, on macOS 13 or later, Windows or Linux (see above). The native Mac app
needs macOS 26 or later, and the Xcode command line tools to build it. gh is optional and only used to read your repos.
The native Mac app 2.0 is SwiftUI and needs macOS 26 or later. On macOS 13 to 15 stay on the 1.1.0 app,
or use the dashboard in the browser (it installs as a web app). The web dashboard was redrawn in 2.0 to match the Mac app (system fonts, sidebar, tables with a detail panel, a physics graph for memory, five-step text size in Settings). The memory graph is drawn as islands: each note sits in its group (the project it belongs to, or the type for who-you-are and preferences notes), a group is a coloured region with a big name, and links between groups are bridges. From far away you read the groups, up close the note titles (the link text in the folder's MEMORY.md, or the first sentence of the description, never the slug). The server lays the map out once per memory fingerprint, in a separate low-priority process, and reuses it until notes or links change.
The server listens on loopback only. HTTP writes require the token in
~/.plancia/token; the dashboard receives it from the server inside the page.
Reads are open: it is your data, already on your disk.
bin/plancia-guardiano is an optional PreToolUse hook that keeps two groups of work
apart on one machine (see plancia/compartimenti.py). It reads POSIX paths and shell
commands, so it does nothing on Windows (see the limits above). It is a heuristic analyser of
what a tool call says it will touch: a guard against incidents, and not a security boundary.
It stops what an agent does without thinking, such as reading the other
group's files, overwriting the guard's own config, or a recursive search that walks
into a forbidden folder. It does not stop someone who is trying to get around it, and
it does not claim to: a real boundary is a separate operating-system user or a
container. Start it in solo-registro (log only), read the log, then decide.
What it does not see, honestly: paths built at run time inside programs and scripts
that already exist (a script written in one call and run in another, a build, a test
that opens files); downloaded or generated code that is then executed; child
processes that start themselves and outlive the command (a daemon, a scheduled job, a
watcher); third-party MCP tools whose file arguments it does not know by name; paths
that travel through another channel (the clipboard, the local network, a database); a
command it cannot finish analysing in two seconds (a nominated session is denied with
"too complex to check in time, split it", the default session is allowed with a
warning each time). The full list is in the docstring of plancia/compartimenti.py.
git config core.hooksPath .githooksTurns on the hook that runs python3 tools/prova.py before every push: 4954
checks in a few minutes, against a throwaway archive that never touches
yours. They cover the schema, the board, the proposals, the search index, the
recap, the MCP surface and its token budget, every read route of the HTTP API,
the hook, the skills and a full install and uninstall into a fake home.
GPL-3.0-or-later. See LICENSE and COPYRIGHT. Versions up to 0.2.0 were MIT and stay MIT.
Building from source is free and always will be. A signed and notarised build, which opens with a double click, is pay what you want from €5 on the website. It is the same program: what you pay for is the Apple certificate, the notarisation and the maintenance. See docs/RILASCIO.md for how a release is cut.












