How I Replaced My Brain with a System: A Personal Operating System with n8n, Slack, Todoist, and Claude
Forgetting tasks, neglecting chores, not following through – not out of laziness, but because my brain doesn’t work that way. Here’s how I built a technical system that does the thinking for me.
The Problem
I’m a software developer, I work from home, and I have a problem: I forget things. Not the big stuff – that’s in Jira. The small stuff: taking out the trash, replying to an email, booking an appointment, putting the laundry away. Things piled up, and something was always left undone.
The pattern runs through every area of life: work, household, personal projects, admin. I see things, intend to do them – and forget. Or I can’t bring myself to start, even though I know I need to.
At some point it became clear: this isn’t a motivation problem. It’s a systems problem. And systems I can build.
The Idea: A Personal Operating System
The core idea is simple: if my brain isn’t a reliable task management system, I’ll build an external one. The system needs to do three things:
- Capture – Get everything out of my head, immediately, without friction
- Process – Classify and prioritize automatically or semi-automatically
- Surface – Show me what needs doing, without me having to look for it
The core principle: I never have to think about what to do. I only react to what the system shows me.
The Architecture
┌─────────────────────────────────────────────────┐
│ CAPTURE │
│ │
│ Slack Bot ──→ n8n Webhook ──→ Google Sheet │
│ Gmail ──→ n8n Trigger ──→ Google Sheet │
│ │ │
│ AI Pre-enrichment │
│ (Classification, Context) │
└───────────────────────┬─────────────────────────┘
│
┌───────────────────────▼─────────────────────────┐
│ PROCESS │
│ │
│ Claude Code (CLI) │
│ ├── Reads Google Sheet (MCP) │
│ ├── Asks interactively for context │
│ └── Creates Todoist Tasks (MCP) │
└───────────────────────┬─────────────────────────┘
│
┌───────────────────────▼─────────────────────────┐
│ SURFACE │
│ │
│ n8n Cronjob (daily 7:30) │
│ ├── Reads Todoist Tasks via API │
│ ├── Formats daily overview │
│ └── Sends Slack message │
└─────────────────────────────────────────────────┘
Tech Stack
| Component | Tool | Why |
|---|---|---|
| Task Management | Todoist | API-first, good mobile app, recurring tasks |
| Automation | n8n (self-hosted) | Open source, runs on my home server |
| Capture Interface | Slack Bot | I use it all day for work anyway |
| Buffer | Google Sheets | Inspectable, simple, no DB setup needed |
| AI Processing | OpenAI GPT (classification) + Claude Code (processing) | Two distinct roles: GPT classifies automatically in n8n, Claude Code processes interactively |
| Tunnel | Cloudflare Tunnel | n8n reachable without port forwarding |
| MCP Servers | Todoist MCP + Google Sheets MCP | Claude Code accesses both directly |
Part 1: The Capture Layer
Slack Bot as the Entry Point
The fastest way to capture a thought: type a message to my Slack bot. Text or voice note – both work.
Slack App Setup:
- Create a new app at api.slack.com
- Bot token scopes:
chat:write,im:history,im:read,files:read - Event subscription for
message.im - Install the app in the workspace
The bot itself doesn’t do anything complex – it’s just the entry channel. The logic lives in n8n.
n8n as the Processing Layer
n8n receives the Slack event via webhook and writes it to the Google Sheet. The flow:
Incoming Slack event
├─ URL verification? → yes: challenge response back
├─ 200 OK immediately to Slack
├─ Retry or bot? → yes: discard
├─ Parse text + metadata
├─ Voice note?
│ └─ yes: download → Whisper transcription
├─ No text? → yes: error
├─ GPT classification (+ Todoist MCP)
├─ Google Sheet: append row
└─ Slack: ✅ confirmation
The branch-merge trick: n8n has a well-known problem when two branches need to be joined back together. Instead of a Merge node, I use a Code node that combines the data via node references ($('Node Name')):
const parsed = $('Prepare Data').first().json;
let transcript = '';
try {
const whisperData = $('Transcribe voice note').first().json;
transcript = whisperData.text || '';
} catch (e) {
// Voice branch didn't run – that's fine
}
return [{
json: {
...parsed,
transcript,
text: transcript || parsed.raw_text
}
}];
AI Pre-enrichment
Before the task gets written to the sheet, it runs through an OpenAI API call in n8n. The model classifies it upfront: which project? what priority? recurring? estimated duration? relevant labels?
Todoist MCP directly in the n8n AI node: The classification node has access to the Todoist MCP server (ai.todoist.net/mcp) with the tools find-projects, find-sections, and get-overview. This means the model can look up real project IDs at classification time instead of relying on hardcoded names. When a new project is created in Todoist, the model finds it automatically.
Key prompt discipline: The LLM must only classify, not help. Otherwise you get follow-up questions and suggestions instead of structured data. The output must be a valid JSON object – no markdown, no explanations. The system prompt explicitly defines all valid projects and labels, and specifies the output schema:
You are a task categorization assistant. Output ONLY a valid JSON object.
Rules:
- Output ONLY the structured format. Nothing else.
- Do NOT ask questions.
- Do NOT suggest follow-up actions.
- If information is ambiguous, make your best guess and move on.
Output format:
{
"task": "Short actionable task title",
"project": "Personal | Work | Household | ...",
"priority": 1-4,
"due": "today | next Wednesday | null",
"recurring": "every Monday | null",
"duration": 30,
"labels": ["@quick", "@computer"],
"subtasks": [],
"context": "Additional context or null"
}
Part 2: The Processing Layer
Claude Code + MCP
Once a day I open Claude Code in the terminal and type /process-inbox. Claude Code:
- Reads the Google Sheet via the Google Sheets MCP server
- Shows me each new entry with the AI pre-classification
- Asks: “Does this look right? Project? Priority? Date?”
- I say “ok” or adjust
- Creates the Todoist task via the Todoist MCP server
- Marks the row in the sheet as processed
MCP Setup:
Two MCP servers in ~/.claude/mcp.json:
{
"mcpServers": {
"todoist": {
"command": "npx",
"args": ["-y", "todoist-mcp"],
"env": {
"API_KEY": "TODOIST_API_TOKEN"
}
},
"google-sheets": {
"command": "uvx",
"args": [
"mcp-google-sheets@latest",
"--include-tools",
"get_sheet_data,update_cells,list_spreadsheets,list_sheets"
],
"env": {
"SERVICE_ACCOUNT_PATH": "/path/to/service-account.json"
}
}
}
}
Note on the Google Sheets MCP: I use mcp-google-sheets (via uvx) with a service account instead of OAuth. Create the service account in Google Cloud Console, download the JSON credentials, and grant the service account Editor access on the relevant Google Sheet. No browser login, no token refresh – runs headless on the server too.
The “Auto All” Escape Hatch
On low-energy days I just type auto all and Claude classifies all pending entries on its own. An automatically sorted task is better than one that sits in the sheet forever.
Part 3: The Surface Layer
Morning Briefing via Slack
An n8n cron job runs daily at 7:30 AM:
Daily 7:30 AM
├─ Todoist API: tasks (due before: +1 day)
├─ Sort by priority, then time
└─ Slack: send morning briefing
The Todoist API query is due before: +1 day – this returns all tasks due today or earlier, including overdue ones. Tasks are sorted by priority, then by time. One important gotcha: the Todoist API v1 separates date (due.date) and timestamp (due.datetime) into separate fields. If you only check due.date, you’ll never see a time.
The result:
☀️ Good morning!
7 tasks for today:
🔴 Collect tax return documents (10:00) · 30 min
🟡 Deploy plugin update · 15 min
🟡 Clean kitchen & empty sink (18:00) · 15 min
🔵 Mop floors · 20 min
⚪ Go tutorial chapter 5 · 20 min
⚠️ 1 overdue
Have a great day! 💪
I don’t need to open Todoist in the morning. The overview comes to me.
Infrastructure: n8n on the Home Server
n8n runs as a Docker container on my home server. To make the Slack webhooks reachable, I use a Cloudflare Tunnel – no port forwarding, automatic HTTPS, free.
Docker Compose (simplified):
services:
postgres:
image: postgres:16-alpine
volumes:
- postgres-data:/var/lib/postgresql/data
n8n:
image: n8nio/n8n:latest
depends_on: [postgres]
environment:
DB_TYPE: postgresdb
DB_POSTGRESDB_HOST: postgres
WEBHOOK_URL: https://n8n.example.com/
N8N_SECURE_COOKIE: "false" # Cloudflare terminates TLS
cloudflared:
image: cloudflare/cloudflared:latest
command: tunnel --no-autoupdate run
environment:
TUNNEL_TOKEN: ${CLOUDFLARE_TUNNEL_TOKEN}
networks:
default:
name: n8n-network
Important: N8N_SECURE_COOKIE=false is required because Cloudflare terminates TLS and n8n only sees HTTP internally. The connection to the browser is still encrypted.
Set the service URL to http://n8n:5678 in the Cloudflare dashboard (using the Docker container name, not localhost).
What It’s Changed
After two weeks with the system:
- Household: I no longer forget recurring tasks. Todoist tells me what’s due – I don’t have to notice what’s dirty myself.
- Work: Spontaneous ideas and action items from calls land in the system immediately instead of in my short-term memory.
- Mental load: The feeling of “I’m probably forgetting something right now” has decreased noticeably.
- Reliability: I don’t need to be reminded anymore. The system reminds me.
The system isn’t perfect. Sometimes I ignore the Slack message in the morning. Sometimes entries pile up in the sheet. But the crucial difference: if I have an off day, the system just keeps running the next day. No backlog stress, no guilt. Just the next message with the next tasks.
Try It Yourself
The complete setup consists of:
- Slack app with bot (15 min setup)
- n8n on a server with Cloudflare Tunnel (30–60 min)
- Google Sheet as inbox buffer (5 min)
- Todoist for task management (10 min project structure)
- Claude Code with MCP servers for Sheets + Todoist (20 min)
- Three n8n workflows: Slack capture, Gmail capture, morning briefing
Everything is open source or available on a free tier (except OpenAI API credits and Claude Code). Todoist Free is enough too – the reminders come via Slack, not from Todoist itself.
Have you built something similar or have ideas for improvement? I’d love to hear your feedback.