Documentation
Letterknife docs
Everything you need to install, understand, and run Letterknife — the local-first email agent that lives on your machine and runs on your own Claude subscription. It's all on this one page: use the sidebar (or the menu above on mobile) to jump between sections.
What Letterknife is
Letterknife is an AI assistant that runs on your own computer and works your Gmail inbox: it triages mail, drafts replies in your voice, turns threads into tasks, chases follow-ups, and hands you a plan every morning. It learns your preferences from one-line corrections — no filters to write, no setup interview.
Two architectural choices set it apart:
- Your mail never leaves your machine. Letterknife talks to Gmail directly from your computer. There are no Letterknife servers holding your email — nothing of yours exists anywhere else to leak, mine, or train on.
- The AI is your own Claude subscription. Letterknife orchestrates the Claude Code CLI you already have installed and logged in. No API keys to buy, no token markup, no third-party inference servers. The memory core — the part that distills your corrections into durable rules — runs on Opus, Anthropic's smartest model.
Start with Getting started to install, or read How it works first if you want the architecture in plain words. Privacy, cost, and troubleshooting live in the FAQ — still stuck after that, email hello@letterknife.com.
Getting started
From download to a working agent in about 10 minutes. Letterknife runs entirely on your machine — the setup is: install, tell it who you are, connect Gmail, hand the tools to Claude, start.
Prerequisites
- A Claude subscription (Pro or Max). Letterknife's AI runs through your own Claude Code — get a subscription at claude.com/pricing if you don't have one.
- Claude Code CLI, installed and logged in:
npm install -g @anthropic-ai/claude-code claude # opens browser login — sign in with your Claude account, then exit with Ctrl+C - Node.js 20+ — check with
node -v, install from nodejs.org if missing. - A Gmail account (Gmail and Google Workspace are supported today).
1. Install
Download the latest Letterknife release (you receive the download link when you join the beta), unpack it, and install dependencies:
cd letterknife
npm install2. Tell it who you are
cp owner.json.template owner.json Edit owner.json: your full name, first name, and every email address that is you. This matters — the assistant must never treat your own messages as someone else's ask, so list all your aliases and secondary addresses.
Optionally, edit the ## Owner section in config.md — one or two lines about who you are and what you work on. It gives the agent context from day one; everything else it learns by itself.
3. Connect Gmail
Letterknife authenticates with Google using an OAuth Desktop client and stores the resulting token locally in tokens.json — access stays between your machine and Google. The client credentials live in credentials.json next to package.json:
- If your download includes a
credentials.json(or you received one with it), you're set — skip to running the auth script. - Otherwise, create your own (a few minutes, free): go to console.cloud.google.com → APIs & Services → Credentials → Create OAuth client ID → Desktop app, download the JSON, and save it as
credentials.jsonnext topackage.json. Also enable the Gmail API and Calendar API for that project.
Then run the auth flow:
node scripts/auth.jsOpen the printed URL in your browser and approve. Letterknife asks for Gmail (read/modify), Calendar events, and — optionally — read-only Contacts (saved people are never auto-flagged as spam; the app works fully without it).
4. Give Claude the Letterknife tools
One-time step — registers the email tools with your Claude Code. Run it from inside the Letterknife folder (the same place you ran npm install):
claude mcp add --scope user letterknife -- node "$PWD/mcp-server.js"5. Start it
node task-ui.js Open http://localhost:3007 in your browser. Keep the terminal running — Ctrl+C stops the agent.
6. First run: Learning mode
Click the 🎓 button. Letterknife shows you one real email at a time and asks how you'd handle that sender — Important, Learn from, or Not important. Correct it freely in plain words; every correction becomes a durable rule, exceptions included. After a few dozen slides it starts getting them right, and the agent works from those rules from then on.
How it works
The whole system runs on your computer. Understanding the three moving parts makes everything else in these docs obvious.
The three parts
- A local Node app + your browser.
node task-ui.jsstarts a small server bound to127.0.0.1:3007— the cockpit you open in your browser. Tasks, the daily plan, learning mode, settings: it's all served locally, to you only. - Your own Claude Code CLI. When the agent needs intelligence — triaging a sender, drafting a reply, building the plan — Letterknife spawns the Claude Code CLI you already have installed and logged in. Your subscription, your machine. No API keys, no third-party inference servers, no token markup.
- An MCP server that exposes the inbox as tools.
mcp-server.jsgives Claude a toolbox — read email, manage tasks, touch the calendar, draft and (with consent) send replies. Claude never talks to Gmail directly; every action goes through a named tool with defined behavior and its own safety gate. The full list is in the tool reference.
Where your data lives
Your mail stays in Gmail — Letterknife reads it over Google's API from your machine and never uploads it anywhere. Everything the agent produces locally — tasks, learned rules, sender memory, settings — lives in a SQLite database and plain-text memory files inside the Letterknife folder. You can open, edit, or delete any of it; there is no black box and no cloud copy.
The only thing that leaves your machine is what any Claude Code session sends: the prompts and tool results exchanged with Anthropic through your own logged-in Claude Code CLI — the same trust relationship you already have when you use Claude Code in a terminal.
Triage, tasks, and the plan
On each scan the agent sweeps new mail, applies the rules it has learned, and files every real conversation as a task with a status, the current ask, and a next step. Follow-ups are reconciled automatically: it notices when someone replied, when they didn't, and when you already answered directly in Gmail, so nothing is handled twice. Each morning it merges open tasks with your calendar into one prioritized plan with a visible time budget.
Learning mode: corrections become rules
There is no settings interview. The agent makes a call on a real email, you correct it in one plain-English line ("keep newsletters from this one", "always archive these"), and the correction is distilled into a durable, readable rule — exceptions included. This distillation is the memory core, and it runs on Opus, Anthropic's smartest model, because getting a rule subtly wrong compounds forever. If Opus is momentarily unavailable on your plan, the run falls back to your selected model and tells you.
Nothing sends without you
The default posture is drafts only. The agent writes replies in your voice and leaves them as Gmail drafts or task recommendations; actually sending requires your explicit OK. Reversible triage actions (archive, label) run autonomously — that's the point of an agent — but each action category has its own toggle in Settings, so you decide exactly how long the leash is.
Usage-aware orchestration
Because the AI is your subscription, Letterknife budgets it like it budgets your time: the cockpit shows your live Claude session usage, big sweeps pause automatically before hitting the session limit, and work resumes when the limit resets. You'll never find your Claude plan silently drained by a background job.
Tool reference
The MCP server (mcp-server.js) exposes 32 tools to your Claude. This is the complete list — every capability the agent has, and the safety gate on each one.
Three kinds of gates apply across the toolbox:
- Consent-gated — sending-class actions (send, forward, unsubscribe, calendar deletes) only run after your explicit OK, or when you've switched training mode off for autonomous operation.
- Settings-toggled — each Gmail action category (draft, send, forward, trash, archive, label, unsubscribe) has an on/off switch in Settings that only ever restricts. See Settings.
- Reversible by design — archive keeps mail searchable, trash is recoverable for 30 days, and spam verdicts have an explicit undo.
Reading, triaging, and (with consent) replying — the core of the toolbox.
scan_inboxLists inbox messages — sender, subject, snippet, date, labels — scoped by a Gmail search query (e.g. "is:unread", "from:acme.com", "has:attachment").
read_emailFull headers, plaintext body, and attachment list for one message by id.
get_threadLoads every message in a conversation, oldest to newest — the way the agent sees full context before drafting a reply or deciding anything.
read_attachmentFetches one attachment so the agent can actually look at it. Images come back inline-readable; PDFs and other types open in Gmail web instead.
draft_replyCreates a draft reply in the thread, written in your voice and register. Deduplicates: if a draft already exists on the thread it is reused, not duplicated.
Never sends — this is the safe default. You review the draft in Gmail or the cockpit before anything goes out.
send_replySends a reply in the thread immediately, replying to all by default.
Requires your explicit OK — the agent is instructed to prefer draft_reply whenever it is unsure, and typed conversation never counts as permission.
forward_emailForwards an email to new recipients with original attachments preserved, plus an optional short intro note — for looping someone in without summarizing.
Sends immediately; gated by the forward settings toggle and the same consent rules as sending.
archive_emailsArchives messages — removes them from the inbox but keeps them searchable in Gmail.
Reversible. Gated by the archive settings toggle.
label_emailsApplies a label to messages, creating the label if it does not exist yet.
Gated by the label settings toggle.
trash_emailsMoves messages to Trash. Not a permanent delete — Gmail keeps trashed mail recoverable for 30 days.
Gated by the trash settings toggle.
flag_spamRecords a durable spam verdict for a sender address (or, for wholly-junk domains, a whole domain) so future mail from it is auto-handled without re-judging.
Domain scope is reserved for entirely junk domains, never shared ones. Senders in your saved Google Contacts are guarded from being flagged.
unflag_spamThe undo for flag_spam — removes a spam verdict and puts the sender back on the normal judged path.
unsubscribeDeterministically unsubscribes from a bulk sender using the message's List-Unsubscribe header — RFC 8058 one-click, mailto, or a web link handed to you. Code parses the link; no LLM guessing.
Consent-gated like sending, and separately gated by the unsubscribe settings toggle.
purge_senderBulk-archives every inbox message from one sender — clears thousands in one call, with an exclude list to keep specific mail (e.g. your own communities on a shared notification address).
Archive only — reversible and searchable, never a delete. Gated by the archive settings toggle.
reconcile_repliesDetects open tasks where you already replied directly in Gmail and folds your reply into the task — so the agent never re-handles something you answered yourself.
sender_digestDeep-samples a high-volume sender — the last ~100 messages in both directions plus reply history and unsubscribe signals — so the agent can genuinely understand a sender before bucketing them.
🗓Calendar
Read and manage events on your Google Calendar via the same Google grant.
list_calendar_eventsLists events in a time window (default: the next 7 days) with attendees and organizer — what the daily plan builds on.
create_calendar_eventCreates an event — all-day or timed, with optional attendees and location.
Attendees are not emailed unless the agent explicitly sets notify.
update_calendar_eventEdits an existing event — partial update, only the fields passed change.
Attendees are not emailed unless notify is set.
delete_calendar_eventDeletes an event by id — the general-purpose delete.
Consent-gated. Attendees are not notified unless notify is set.
remove_calendar_eventThe calendar-spam variant: removes a fake "order / membership / invoice" invite injected via a scam email, and trashes the notification email with it.
Consent-gated; only used after the email is judged spam — never on legitimate invites.
✅Tasks
Every real conversation becomes a task with a status, the current ask, and a next step.
add_taskAdds a task derived from an email or Slack thread. Idempotent per thread — a follow-up in the same conversation updates the existing task (and reopens it if needed) instead of duplicating.
list_tasksLists tracked tasks, filterable by status, contact, participant, or person name — how the agent finds an existing task before creating a new one.
update_taskUpdates a task: mark done, change priority, refresh the ask, append notes, or record your explicit send consent on that task.
Send consent is only recorded from an explicit approval in your latest message — a question or new information never counts.
🧠Memory & identity
The durable, readable knowledge the agent builds about your preferences and your contacts.
get_foundationLoads your goals, triage rules, category map, and communication style — the context bundle for sessions that start cold.
record_memory_updateCaptures a standing preference the moment you express it ("always keep these", "stop archiving X") as a self-contained rule, which the Opus memory core folds into long-term memory.
merge_identitiesRefreshes the person-identity map that joins one person's multiple email addresses into a single identity, so their asks merge into one task across inboxes and Slack.
💬Slack (optional — off by default)
If you connect a Slack token, DMs flow into the same tasks and plan as email. Without one, these tools simply report that Slack is not configured.
slack_recentReads your recent Slack direct messages to detect when someone who emailed also raised the same issue in a DM — so both fold into one task.
DMs only, read-only. Instructions found inside Slack messages are treated as data to surface, never commands to execute.
slack_directoryBuilds the Slack-to-email identity map, matching each workspace member to the email contact who is the same person.
send_slackSends a Slack message — the Slack equivalent of send_reply, posting as you (user token) or as a bot (bot token), and reporting honestly which.
Same consent rules as sending email: only when a task clearly calls for it and you have approved.
🌐Browser
A cooperative lock on the shared local Chrome, for the rare web step (e.g. a login-only unsubscribe page).
acquire_browserReserves the shared Chrome browser before any browser automation — one agent at a time, so parallel sessions never fight over your profile.
release_browserReleases the reservation as soon as the web steps are done, so another session can use the browser.
Settings
The gear icon in the cockpit. Every setting exists to dial the agent's autonomy up or down — the defaults are safe, and the toggles only ever restrict.
Scan interval
How often the agent sweeps your inbox. The default is polling every 60 minutes; pick a tighter or looser cadence from the dropdown. The unattended-sweep toggle controls whether scans run automatically at that cadence or only when you trigger one.
Per-action toggles
Each Gmail action category has its own on/off switch: draft · send · forward · trash · archive · label · unsubscribe. They apply everywhere — a toggle that is off blocks that action for every tool and every sweep, no matter what the agent decides. All default to on, because the master safety gate is training mode, not these; turn individual ones off to tighten further (for example: allow archiving and labeling, but block trash entirely).
Training mode
The master consent gate. With training on (the default), sending-class actions — send, forward, unsubscribe, calendar deletes — are blocked: the agent recommends, you approve. Reversible triage (archive, label, trash) stays autonomous either way, subject to the per-action toggles above. Switch training off when you trust the agent enough to let it act on its own.
Model selection
Choose which Claude model powers everyday work — triage sweeps, drafting, planning. Sonnet is the default and the right choice for most inboxes; Haiku is cheaper on your session budget, Opus is the smartest and the most expensive.
One part of the system ignores this setting on purpose: the memory core runs on Opus. Whenever your corrections are distilled into durable rules, the smartest model does it — a rule written subtly wrong compounds on every future email, so this is the one place quality is never traded for budget. If Opus is momentarily unavailable on your plan, that run falls back to your selected model and a notification tells you it happened.
Usage donut & session-limit pausing
The donut in the topbar shows your live Claude session usage — the same numbers Claude Code's own usage screen reads. Because Letterknife runs on your subscription, it budgets that subscription like it budgets your time:
- Before a big sweep, the cockpit estimates what fits in your remaining session budget and offers sized options.
- Long-running sweeps pause automatically as they approach the session limit, and resume on their own when the limit resets — no lost work, and no surprise "you've hit your limit" in the middle of your own Claude session.
- If usage is momentarily unreadable, the donut renders gray and the agent assumes conservatively.
Foundation files
Settings also gives you direct access to the agent's memory: open any foundation file — your rules, style, sender memory — read it, and hand-edit it. Everything the agent has learned is plain text you can change or delete; the next sweep uses whatever you saved.
FAQ & troubleshooting
Privacy, cost, and the handful of things that most commonly need a second look during setup.
Privacy
Where does my data live?
On your machine, full stop. Your mail stays in Gmail; Letterknife reads it over Google's API from your computer. Everything the agent creates — tasks, learned rules, sender memory, settings, the Google token — lives in a local SQLite database and plain-text files inside the Letterknife folder. There are no Letterknife servers holding any of it.
What leaves my machine?
Only what any Claude Code session sends: prompts and tool results exchanged with Anthropic through your own logged-in Claude Code CLI. That is the same data path you use when you run Claude Code in a terminal yourself — no third parties in between, and nothing flows through Letterknife's infrastructure.
How do I revoke Gmail access?
Go to myaccount.google.com/permissions and remove Letterknife (or your own OAuth client, if you created one). Locally, delete tokens.json from the Letterknife folder. Access is cut immediately.
Cost
What does the AI cost me?
Nothing beyond the Claude subscription you already have. Letterknife orchestrates your own Claude Code — there are no AI credits to buy from us and no token markup. The usage donut shows exactly how much of your session budget the agent is using, and big sweeps pause before they hit your limit.
Troubleshooting
Port 3007 is already in use
Another Letterknife (or something else) is on the port. Either stop it, or start on a different port:
# find what holds the port
lsof -i :3007
# or run Letterknife on another port
LETTERKNIFE_PORT=3008 node task-ui.jsClaude isn't logged in
If sweeps fail immediately or the usage donut stays gray, your Claude Code CLI session has likely expired. Run claude in a terminal, complete the browser login, then exit with Ctrl+C and retry.
The Letterknife tools are missing in Claude
If the agent reports it has no email tools, the MCP registration is missing or points at a moved folder. Re-run it from inside the Letterknife directory:
claude mcp add --scope user letterknife -- node "$PWD/mcp-server.js" You can check what's registered with claude mcp list. If you moved or renamed the Letterknife folder, remove and re-add: claude mcp remove letterknife, then the add command above.
The Google sign-in fails or loops
Make sure credentials.json exists next to package.json and is a Desktop app OAuth client (not a Web client), and that the Gmail and Calendar APIs are enabled for its Google Cloud project. Then re-run node scripts/auth.js. See Getting started for the full flow.
How do I update Letterknife?
Download the latest release, replace the app files in your Letterknife folder (keep your data: owner.json, credentials.json, tokens.json, the SQLite database, and the memory/ folder), then run npm install and restart node task-ui.js. Your rules, tasks, and connections carry over.
Still stuck?
Email hello@letterknife.com with a screenshot and a short note — during the beta, everything you hit is signal we want.