
the-vibe-company/granite
Productivity workflowLocal-first knowledge compiler for humans and agents. Inspired by Karpathy's vision. Plain markdown, CLI + MCP server.
Обзор
Give your agent a memory it can't hallucinate: plain markdown + SQLite full-text search + a typed contract it already knows how to operate. No LLM inside. Your agent brings the intelligence; Granite holds the ground truth. Paste this into , , or any MCP-capable agent: Sixty seconds later: a live vault, an agent that knows how to operate it, and its first three notes on disk in ~/.granite/notes/. No system prompt. No config. No cloud. That's the thesis of this project. No agent handy? Granite is a complete tool on its own: Add --template founder-os to init when you want a full personal OS from the start: person, organization, meeting, and learning on top of the four defaults — eight types already wired with hooks, indexed fields, and lifecycles, in 150 lines of pure YAML. Everything Granite writes is a plain .md file with YAML frontmatter. Close the laptop, git init the vault, open the folder in any editor — it's just files.
README
Granite
The personal OS your agent runs on. Give your agent a memory it can’t hallucinate: plain markdown + SQLite full-text search + a typed contract it already knows how to operate. No LLM inside. Your agent brings the intelligence; Granite holds the ground truth.
npm install -g granite-mem
Jump to: The 60-second setup · Install it yourself · How it works · Why not Obsidian, Notion, or a vector store? · See it · Types are contracts · The MCP server · What Granite will never do · Beyond one machine · The full CLI · FAQ · Philosophy
The 60-second setup
Paste this into Claude Code, Cursor, or any MCP-capable agent:
Install Granite as my personal OS.
1. `npm install -g granite-mem`
2. `granite init --template founder-os` (vault at ~/.granite)
3. `claude mcp add granite -- granite mcp --vault ~/.granite`
4. Restart yourself so the MCP server loads.
5. Call `granite_wakeup`, then propose three notes you would write
first based on what you know about me so far. Capture them as
drafts with --source agent.
Sixty seconds later: a live vault, an agent that knows how to operate it, and its first three notes on disk in ~/.granite/notes/. No system prompt. No config. No cloud.
That’s the thesis of this project. No agent handy? Granite is a complete tool on its own:
Or install it yourself
npm install -g granite-mem
granite init # note / source / synthesis / output
granite new "Ideas worth stealing"
granite search "steal"
granite serve # web UI + constellation graph
Add --template founder-os to init when you want a full personal OS from the start: person, organization, meeting, and learning on top of the four defaults — eight types already wired with hooks, indexed fields, and lifecycles, in 150 lines of pure YAML.
Everything Granite writes is a plain .md file with YAML frontmatter. Close the laptop, git init the vault, open the folder in any editor — it’s just files.
How it works
Granite is a deterministic substrate for knowledge: markdown files as the source of truth, a SQLite index as derived state, and one fixed loop imposed on top. The intelligence is not in Granite — it’s in whatever agent (or human) operates it.
┌──────────────────────────────────────────┐
│ your agent · the brains │
└────────────────────┬─────────────────────┘
│ MCP · CLI · web UI
┌────────────────────▼─────────────────────┐
│ GRANITE │
│ │
│ capture ─▶ compile ─▶ query ─▶ output │
│ ▲ │ │
│ └──────────── lint ◀──────────┘ │
│ │
│ .md files SQLite FTS5 wikilinks │
│ (truth) (derived) (graph) │
└──────────────────────────────────────────┘
- Markdown is truth. Every note is
/.mdwith YAML frontmatter. Nothing you can’t read incat. - The index is disposable. Full-text search, backlinks, and typed queries live in
.granite/index.db— rebuilt from the files at any time. - Wikilinks are the graph.
[[a-note]]in any body resolves slug → title → alias, and the backlink graph falls out for free.
Karpathy asked for “an incredible new product instead of a hacky collection of scripts” for LLM knowledge bases.
This is our answer.
Why not Obsidian, Notion, or a vector store?
Granite doesn’t compete with your note app. It competes with the pile of scripts you were about to write.
| Granite | Obsidian | Notion | Vector memory | Plain files | |
|---|---|---|---|---|---|
| Plain markdown on disk | ✅ | ✅ | ❌ | ❌ | ✅ |
| Typed schemas with hooks & lifecycles | ✅ | plugins | databases | ❌ | ❌ |
| Agent-native MCP workflow | ✅ | community | limited | ✅ | ❌ |
| Deterministic retrieval (no embeddings) | ✅ | ✅ | ❌ | ❌ | grep |
| Structured queries over indexed fields | ✅ | plugins | ✅ | ❌ | ❌ |
| Provenance on every note | ✅ | ❌ | ❌ | partial | ❌ |
| Offline, no account, no telemetry | ✅ | ✅ | ❌ | ❌ | ✅ |
| Git-friendly | ✅ | ✅ | ❌ | ❌ | ✅ |
Obsidian is a great editor for humans. Vector memory is a great cache for agents. Granite is the shared substrate both can operate.
See it
Types are contracts, not folders
This is what makes an agent feel native rather than bolted-on. Every note type in granite.yml is an executable contract:
note_types:
meeting:
folder: notes/meetings
fields:
date: { type: date, required: true }
organization: { type: wikilink, target_types: [organization] }
attendees: { type: wikilink, target_types: [person] }
on_create:
- { action: set_default, field: date, value: "${today}" }
- { action: resolve_wikilinks, fields: [organization, attendees], auto_stub: true }
indexed_fields: [date, organization]
set_default— fills${today}automaticallyresolve_wikilinks + auto_stub— turnsorganization: Acme Corpinto the slugacme-corp, creating the org note if missing (with a globally-unique slug so nothing gets silently overwritten)indexed_fields— makesgranite_query { type: meeting, where: { date: { gte: "2026-01-01" } } }fast and deterministiclifecycle— declare states and stale-days transitions, andgranite doctorsurfaces drift before it rots
On top of its type, every note carries five protocol fields, so humans and agents share ground truth:
| Field | Values | Purpose |
|---|---|---|
status |
inbox · active · archived |
operational state |
source |
human · agent · extraction |
who wrote it |
review_state |
draft · reviewed · locked |
editorial state |
durability |
canonical · working · ephemeral |
keep / may drift / throwaway |
derived_from |
[slug, …] |
provenance for syntheses and outputs |
Your agent reads these before writing and sets them as it works. You inherit a fully auditable trail. Add a type when your life grows a new shape — the core stays small. For the formal protocol, see docs/GRANITE_OBJECT_STANDARD.md.
Wired for agents: the MCP server
“A thin MCP server exposes capabilities. A strong MCP server shapes behavior.”
One line connects any MCP-capable agent to your vault:
claude mcp add granite -- granite mcp --vault ~/.granite
The surface is intention-first — fourteen tools organized around the workflow, not around files:
| Intent | Tools |
|---|---|
| Orient | granite_wakeup · granite_research_topic · granite_resolve |
| Read | granite_query · granite_compile_context · granite_understand_note · granite_extract_document |
| Write | granite_capture_knowledge · granite_import_document · granite_revise_note · granite_dispose_note |
| Garden | granite_plan_garden · granite_adjudicate_garden_opportunity · granite_list_garden_adjudications |
Plus three prompts for the higher-level workflows (granite_refine_note, granite_process_inbox, granite_compile_topic), and resources for raw note and type-contract access. Start the server with --role read when an agent should inspect without mutating. An HTTP transport with bearer-token auth is available for remote setups — see docs/DEPLOY.md.
The point is not to give an agent a file browser. The point is to give it a workflow it can follow.
What Granite will never do
Granite will never:
- embed an LLM, run prompts, or hold an API key
- compute embeddings or ship a vector store
- run background agents or a scheduler
- phone home — no telemetry, no account, no cloud dependency
- add overlapping CLI/MCP endpoints that blur the loop
This is why your agent can be trusted with write access. The vault is a deterministic substrate. The intelligence is yours (or Claude’s, or GPT’s, or whoever you pay this quarter).
Beyond one machine
Cloud, if you want it. One command deploys a personal serverless Granite on Fly.io Sprites: wakes on request in 100–500 ms, sleeps when idle, costs cents per month at rest. You own the sprite — there is no Granite cloud, no central admin, no relay.
granite deploy login --token # or export SPRITES_TOKEN=…
granite deploy # prints an MCP URL + bearer token
claude mcp add --transport http granite https://.sprites.app/mcp \
--header "Authorization: Bearer "
Multiple named instances, bulk upgrades, token rotation, and self-hosting the HTTP MCP server (a generic Dockerfile is included) are covered in docs/DEPLOY.md.
Sync, without a relay. Direct machine-to-machine over LAN, Tailscale, or a private DNS name — with per-device read/write tokens:
granite sync access grant ipad --role read # on the serving machine
granite sync serve --host 0.0.0.0 --port 8765
granite sync remote add macbook http://100.x.y.z:8765 --token
granite sync watch macbook --direction pull --interval 30
Conflict policies, push/pull details, and access management live in docs/SYNC.md.
The full CLI
FAQ
Philosophy
- local-first beats cloud dependence for personal memory
- plain markdown beats proprietary formats
- types as active contracts beat types as folders
- tools for humans should also be legible to agents
- protocol belongs in the core; agent policy belongs outside it
- a personal OS is a thing you own — not a thing you rent
Status & contributing
Granite is pre-1.0 and moving fast — see CHANGELOG.md for release history. The product boundary stays fixed: Granite stores and indexes local knowledge; agents bring the intelligence.
Issues and focused PRs are welcome. For local development, read CLAUDE.md. The key product rule is simple: no embedded LLM, no vector store, no autonomous scheduler inside Granite.
Ship your agent a home. Then give it the keys.
Установка
This server does not publish a one-line install command.
Open the repository installation guide