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

  1. 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.
  2. 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
  3. Node.js 20+ — check with node -v, install from nodejs.org if missing.
  4. 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 install

2. 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.json next to package.json. Also enable the Gmail API and Calendar API for that project.

Then run the auth flow:

node scripts/auth.js

Open 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).

If you created your own OAuth client, Google may show a "Google hasn't verified this app" warning — that's your own personal client it hasn't reviewed, not someone else's app. Click Advanced → Continue to proceed. You can revoke access at any time at myaccount.google.com/permissions.

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.

Nothing sends without you. The assistant only creates drafts; sending needs your explicit OK. See Settings for the per-action toggles.

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.js starts a small server bound to 127.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.js gives 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.

📥Email

Reading, triaging, and (with consent) replying — the core of the toolbox.

scan_inbox

Lists inbox messages — sender, subject, snippet, date, labels — scoped by a Gmail search query (e.g. "is:unread", "from:acme.com", "has:attachment").

read_email

Full headers, plaintext body, and attachment list for one message by id.

get_thread

Loads every message in a conversation, oldest to newest — the way the agent sees full context before drafting a reply or deciding anything.

read_attachment

Fetches 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_reply

Creates 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_reply

Sends 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_email

Forwards 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_emails

Archives messages — removes them from the inbox but keeps them searchable in Gmail.

Reversible. Gated by the archive settings toggle.

label_emails

Applies a label to messages, creating the label if it does not exist yet.

Gated by the label settings toggle.

trash_emails

Moves messages to Trash. Not a permanent delete — Gmail keeps trashed mail recoverable for 30 days.

Gated by the trash settings toggle.

flag_spam

Records 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_spam

The undo for flag_spam — removes a spam verdict and puts the sender back on the normal judged path.

unsubscribe

Deterministically 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_sender

Bulk-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_replies

Detects 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_digest

Deep-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_events

Lists events in a time window (default: the next 7 days) with attendees and organizer — what the daily plan builds on.

create_calendar_event

Creates an event — all-day or timed, with optional attendees and location.

Attendees are not emailed unless the agent explicitly sets notify.

update_calendar_event

Edits an existing event — partial update, only the fields passed change.

Attendees are not emailed unless notify is set.

delete_calendar_event

Deletes an event by id — the general-purpose delete.

Consent-gated. Attendees are not notified unless notify is set.

remove_calendar_event

The 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_task

Adds 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_tasks

Lists tracked tasks, filterable by status, contact, participant, or person name — how the agent finds an existing task before creating a new one.

update_task

Updates 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_foundation

Loads your goals, triage rules, category map, and communication style — the context bundle for sessions that start cold.

record_memory_update

Captures 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_identities

Refreshes 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_recent

Reads 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_directory

Builds the Slack-to-email identity map, matching each workspace member to the email contact who is the same person.

send_slack

Sends 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_browser

Reserves the shared Chrome browser before any browser automation — one agent at a time, so parallel sessions never fight over your profile.

release_browser

Releases 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.js

Claude 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.