Chief of Staff OS
A local system for tasks, decision preparation and context across AI sessions, replacing my paid Todoist workflow.
Why it exists
I used to run my work out of a paid Todoist workflow and notes. The task list was fine. I needed decision context, the reasons behind earlier decisions, what needed my attention, and a way to give an AI session that context without re-explaining it.
I started building this for myself at work in March 2026. I use Claude to capture incoming work, prepare decisions and maintain the task list. I decide what context each session loads, and keep Markdown and YAML records that sessions, scheduled jobs and the desktop app share.
One pattern, two instances
Named commands read and write local records. Deterministic helpers and scheduled AI jobs prepare work for my review. The system writes suggestions to the records only after I approve them.
Claude Code built it. Codex reviews and maintains parts of it, using a compatibility layer I wrote so either tool can run the same commands.
Work is the larger instance, with Python, shell, launchd scheduling and MCP connections to Slack, calendar, email, documents and a data warehouse. At home, the smaller instance has commands for decisions, premortems and writing, a six-pass voice editor that edits drafts against my writing rules, a decision journal and project memory.
Session-start hooks load context, and the config syncs through git between two machines. For this site, Codex drafts, the voice editor edits, and I edit the Markdown.
commands → structured local records → deterministic helpers + scheduled AI jobs → review queue → approved writes → Cockpit
The layout of the work instance, simplified, with the private folders left out.
chief-of-staff/
CLAUDE.md operating instructions every session reads first
commands/ the slash commands: task, deadline, project, ideas, think, write, review, morning, wrap, ...
agents/ specialist reviewers, each with its own fresh context
rules/ standing corrections, applied automatically
hooks/ checks that fire on session start, on edits, and before commits
records/
tasks/ the shared task store, written only through one locked writer
projects/ milestone records that tasks link back to
decisions/ the decision journal
knowledge/ what the system has learned, each entry with a source and a freshness date
launches/ ideas/ a date-change log; idea capture
automation/
shared/ gates, atomic writers, evidence ledgers, notifications
slack-monitor/ the mention watcher
proactive-worker/ bounded background jobs
morning-briefing/ signal-sweep/ focus-time/ meeting-prep/ ...
retired/ meeting auto-draft, news briefing, midday triage
apps/
cockpit/ the native Mac app (Tauri, Rust, React)
session-monitor/ a menu-bar app for parallel Claude Code sessions
fronts/ the attention board
integrations/
slack-mcp/ the Slack MCP server
metrics-registry/ verified metric definitions and their queries
How a session works
Each session reads the operating instructions, saved plan, project state and memory index before starting. Memory entries include sources, freshness dates and confidence. I use an authority table to assign ownership so memory points to live state instead of duplicating it.
The system records information without prompting, but asks my assent before recording a decision. I can explore an option without committing to it. Decision records include alternatives, confidence, reversibility and a revisit condition. Corrections become rules that load automatically.
The Slack mention watcher checks for mentions during working hours, under a daily model budget. It drops duplicates and anything older than a set age, and for actionable mentions prepares a plan and a draft reply for review without posting to the conversation. Background workers run bounded jobs under the same gates, a run limit per job type and a daily notification limit. I review completed results before accepting them.
Atomic replacement didn't prevent concurrent writers from overwriting changes. I route task updates through a shared writer that serializes read-modify-write with an advisory lock and centralizes IDs and duplicate checks. Automated task creation requires explicit consent, and automatic refreshes don't count as real activity.
The parts
Cockpit
Cockpit replaces Todoist with a native Mac workspace for tasks, calendar, meeting prep and approvals, built with Tauri 2, Rust, React 19 and TypeScript. It watches record files, writes atomically and sends approvals through the shared task service, so acceptance means the same thing everywhere. I fixed calendar focus blocks appearing as meetings and expired reminders suppressing later reminders.
Slack MCP server
I wrote the Slack MCP server in Python and FastMCP for structured search, reading and approved actions. Listing and reading direct messages used different identities, so successful API calls could return the wrong identity's view, making data appear intermittently missing. I corrected the identity handling, added structured missing-scope errors and normalized attachment-only messages.
Slack monitor and proactive worker
The Slack monitor and proactive worker apply attention and spending limits to background work. I built two worker types, document review and task execution. Five more have configuration but no implementation.
Metrics registry
I keep verified definitions, saved queries and schema knowledge from running them in the metrics registry, so the model finds a checked definition instead of guessing table names. Queries follow an established path, but a successful connection doesn't validate what a query measures. I haven't built the planned refresh or alerting.
What runs on a schedule
Three of the scheduled jobs. A morning briefing prepares the day's meetings, with a separate AI check for unsupported claims before delivery. A signal sweep scans my sources on a schedule and writes a situation report with proposed updates for review. A focus-time planner reserves blocks on the calendar around explicit rules for which meetings are protected.
Fronts
Fronts ranks responsibilities without deadlines by time since engagement, within explicit priority tiers. Automatic edits made everything look recently attended. I changed the resolver to use dated, topic-specific evidence. Missing evidence now appears as a gap rather than as neglect.
What I turned off
My rule is: "an automation that runs without producing something you consume is worse than no automation, because it looks like coverage." I've retired four automations. A retired job "ran on schedule, it cost money, it reported healthy, and the output was zero."
Nightly meeting drafts went stale after calendar changes or another session's edits. I replaced that job with staged preprocessing that prepares grounded notes before interactive review. I stopped a newsletter-based AI news digest because the volume wasn't actionable. A narrower weekly job finds published techniques to improve this system.
A midday inbox scan duplicated the signal sweep and mention watcher. An email-backend migration job switched delivery, verified the result and disabled its schedule.
I added a scheduled health check for outputs, freshness and deployment. A nightly freshness job merged an empty file over a real document. I required a dry run and re-enabled it after it refused four destructive scenarios with zero writes across two full runs.
What it taught me
Instructions didn't reliably prevent incorrect writes or stale summaries. Locks, consent checks and durable evidence worked better.
I accumulated overlapping readers, instructions and status surfaces. I simplify ownership of each fact and check what the consumer receives. A fresh timestamp doesn't establish revalidation.
A hook that appeared to run wasn't a reliable quality check, so I moved the commit check into git. I verify the artifact, never the exit code, and make the manual process work before automating it.
I wrote an internal guide to this and shared it with senior leadership. A peer PM used it to set up their own system. A team version of the shared-context idea, a repository my product org's AI agents read from, sits under Work on this site.
Status
I've used this daily at work since March 2026. As of August 2026 it ran about forty commands, twenty-eight scheduled automations, thirteen integrations, and two native Mac apps. Some scheduled jobs are healthier than others, so I check them rather than assuming they ran. The code stays private because the records it operates on are my employer's context.