granite-mem 0.1.8 → 0.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +124 -227
- package/dist/index.js +4113 -652
- package/dist/public/app.js +17 -540
- package/dist/public/graph-engine.js +102 -0
- package/dist/public/index.html +113 -135
- package/dist/public/markdown-renderer.js +1 -187
- package/dist/public/style.css +1 -960
- package/dist/templates/founder-os.yml +204 -0
- package/package.json +8 -3
- package/templates/founder-os.yml +204 -0
- package/dist/public/canvas-renderer.js +0 -524
- package/dist/public/graph.js +0 -377
package/README.md
CHANGED
|
@@ -1,289 +1,186 @@
|
|
|
1
1
|
# Granite
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> **The personal OS your agent runs on.**
|
|
4
|
+
> Markdown files. One SQLite index. A contract your agent already knows how to operate.
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
<p align="center">
|
|
7
|
+
<img src="docs/screenshots/granite-note.png" alt="Granite note view" width="720">
|
|
8
|
+
</p>
|
|
6
9
|
|
|
7
|
-
|
|
10
|
+
<p align="center">
|
|
11
|
+
<b>Install in one prompt.</b> Your agent does the rest.
|
|
12
|
+
</p>
|
|
8
13
|
|
|
9
|
-
|
|
10
|
-
- structure ideas without over-designing your workflow
|
|
11
|
-
- keep sources, durable notes, syntheses, and outputs connected
|
|
12
|
-
- surface what to connect or write next
|
|
13
|
-
- stay fully local, scriptable, and agent-friendly
|
|
14
|
+
---
|
|
14
15
|
|
|
15
|
-
|
|
16
|
+
## The wow moment
|
|
16
17
|
|
|
17
|
-
|
|
18
|
+
Paste this into **Claude Code**, **Cursor**, or any MCP-capable agent:
|
|
18
19
|
|
|
19
|
-
|
|
20
|
+
````
|
|
21
|
+
Install Granite as my personal OS.
|
|
20
22
|
|
|
21
|
-
|
|
23
|
+
1. `npm install -g granite-mem`
|
|
24
|
+
2. `granite init --template founder-os` (vault at ~/.granite)
|
|
25
|
+
3. `claude mcp add granite -- granite mcp --vault ~/.granite`
|
|
26
|
+
4. Restart yourself so the MCP server loads.
|
|
27
|
+
5. Call `granite_wakeup`, then propose three notes you would write
|
|
28
|
+
first based on what you know about me so far. Capture them as
|
|
29
|
+
drafts with --source agent.
|
|
30
|
+
````
|
|
22
31
|
|
|
23
|
-
|
|
32
|
+
Sixty seconds later you have a live vault, a connected agent that **knows how to use it**, and three starter notes in `~/.granite/notes/`. No system prompt. No config. No cloud.
|
|
24
33
|
|
|
25
|
-
That
|
|
34
|
+
That's the thesis of this project.
|
|
26
35
|
|
|
27
|
-
|
|
28
|
-
- the index is derived state, not the source of truth
|
|
29
|
-
- the default note types create just enough structure to stay useful
|
|
30
|
-
- custom note types are easy to add in `granite.yml`
|
|
31
|
-
- the CLI is predictable for both humans and agents
|
|
32
|
-
- the local web UI makes the vault browseable without adding cloud lock-in
|
|
36
|
+
## What is Granite?
|
|
33
37
|
|
|
34
|
-
Granite is
|
|
38
|
+
Granite is a **local-first operating substrate** for the human + agent duo:
|
|
35
39
|
|
|
36
|
-
|
|
40
|
+
- **Files you own.** Plain markdown with YAML frontmatter in `~/.granite`. No database, no lock-in, `git` works.
|
|
41
|
+
- **Typed contracts, not folders.** Note types declare fields, hooks, indexed queries, and lifecycles. Create a `meeting` and the org stub, date default, and backlinks all fall into place automatically — deterministically, no LLM involved.
|
|
42
|
+
- **Agent-native MCP.** The server *teaches* methodology: tools organized along `orient → research → inspect → plan → mutate`. Drop any MCP-capable LLM onto the vault and it can operate it without a system prompt.
|
|
43
|
+
- **Hard boundary.** **No LLM, no embeddings, no scheduler inside Granite.** All intelligence lives in your agent. Granite is the disk, the schema, and the rules — never the brain.
|
|
37
44
|
|
|
38
|
-
|
|
45
|
+
One loop: **capture → compile → query → output → lint**.
|
|
39
46
|
|
|
40
|
-
|
|
47
|
+
## Install prompts (copy-paste)
|
|
41
48
|
|
|
42
|
-
|
|
43
|
-
- `source` for imported or observed source material
|
|
44
|
-
- `synthesis` for durable compiled knowledge
|
|
45
|
-
- `output` for audience-specific deliverables
|
|
49
|
+
### Claude Code / Claude Desktop
|
|
46
50
|
|
|
47
|
-
`note -> synthesis -> output`
|
|
48
|
-
|
|
49
|
-
This is enough structure to make your notes connect naturally, without forcing you into a heavyweight system.
|
|
50
|
-
|
|
51
|
-
### 2. Custom types without losing the plot
|
|
52
|
-
|
|
53
|
-
You can add your own note types in `granite.yml`, but Granite still works out of the box. The product stays simple because the core model is small and every type shares the same mechanics: folder, template, line limit, guidance, and slug strategy.
|
|
54
|
-
|
|
55
|
-
### 3. Agent-native, not just agent-compatible
|
|
56
|
-
|
|
57
|
-
Granite is designed to be easy for agents to read and act on:
|
|
58
|
-
|
|
59
|
-
- notes are plain files
|
|
60
|
-
- metadata is explicit
|
|
61
|
-
- commands support `--json`
|
|
62
|
-
- Granite ships with an MCP server
|
|
63
|
-
- vault structure is predictable
|
|
64
|
-
- search, backlinks, and recommendations are available from the CLI
|
|
65
|
-
|
|
66
|
-
It works well as a personal system, and it also works as a memory layer for coding agents, assistants, or local automation.
|
|
67
|
-
|
|
68
|
-
## Quickstart
|
|
69
|
-
|
|
70
|
-
Clone the repo and install dependencies:
|
|
71
|
-
|
|
72
|
-
```bash
|
|
73
|
-
git clone https://github.com/The-Vibe-Company/Granite
|
|
74
|
-
cd Granite
|
|
75
|
-
npm install
|
|
76
|
-
npm run build
|
|
77
|
-
npm link
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
Create the default vault in `~/.granite` and start capturing:
|
|
81
|
-
|
|
82
|
-
```bash
|
|
83
|
-
granite init
|
|
84
|
-
granite add "Talked to Alice about local-first sync tradeoffs"
|
|
85
|
-
granite new "Local-first sync tradeoffs" --type note
|
|
86
|
-
granite list
|
|
87
|
-
granite search "sync"
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
Start one long-running interface when you need it:
|
|
91
|
-
|
|
92
|
-
```bash
|
|
93
|
-
granite serve # local web UI
|
|
94
|
-
granite mcp # MCP server for agent clients
|
|
95
51
|
```
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
Capture something quickly:
|
|
102
|
-
|
|
103
|
-
```bash
|
|
104
|
-
granite add "Users want fewer note types, but stronger defaults."
|
|
52
|
+
Install Granite for me:
|
|
53
|
+
npm install -g granite-mem
|
|
54
|
+
granite init --template founder-os
|
|
55
|
+
claude mcp add granite -- granite mcp --vault ~/.granite
|
|
56
|
+
After restart, call granite_wakeup and tell me what the vault looks like.
|
|
105
57
|
```
|
|
106
58
|
|
|
107
|
-
|
|
59
|
+
### Cursor
|
|
108
60
|
|
|
109
|
-
```bash
|
|
110
|
-
granite new "Strong defaults beat infinite flexibility" --type note
|
|
111
61
|
```
|
|
62
|
+
Run these commands, then add Granite to .cursor/mcp.json:
|
|
63
|
+
npm install -g granite-mem
|
|
64
|
+
granite init --template founder-os
|
|
112
65
|
|
|
113
|
-
|
|
66
|
+
Append to .cursor/mcp.json:
|
|
67
|
+
{ "mcpServers": { "granite": { "command": "granite", "args": ["mcp", "--vault", "~/.granite"] } } }
|
|
114
68
|
|
|
115
|
-
|
|
116
|
-
granite suggest-links strong-defaults-beat-infinite-flexibility
|
|
117
|
-
granite recommend strong-defaults-beat-infinite-flexibility
|
|
118
|
-
granite backlinks strong-defaults-beat-infinite-flexibility
|
|
69
|
+
Reload Cursor. Then call granite_wakeup.
|
|
119
70
|
```
|
|
120
71
|
|
|
121
|
-
|
|
72
|
+
### ChatGPT / any HTTP-MCP client
|
|
122
73
|
|
|
123
|
-
```bash
|
|
124
|
-
granite serve
|
|
125
74
|
```
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-

|
|
130
|
-
|
|
131
|
-
## Custom Note Types
|
|
132
|
-
|
|
133
|
-
Granite is intentionally small, but not rigid. Add a type in `granite.yml` when your workflow genuinely needs it:
|
|
134
|
-
|
|
135
|
-
```yaml
|
|
136
|
-
note_types:
|
|
137
|
-
idea:
|
|
138
|
-
folder: notes/ideas
|
|
139
|
-
description: Early product ideas worth pressure-testing
|
|
140
|
-
template: |
|
|
141
|
-
## Problem
|
|
142
|
-
|
|
143
|
-
## Insight
|
|
144
|
-
|
|
145
|
-
## Why now
|
|
146
|
-
|
|
147
|
-
## Next step
|
|
148
|
-
line_limit: 120
|
|
149
|
-
warn_only: true
|
|
150
|
-
slug_format: title
|
|
151
|
-
instructions: Capture the idea clearly, then link it to a source, note, or synthesis.
|
|
75
|
+
Start the Granite MCP over HTTP:
|
|
76
|
+
granite mcp --transport http --host 127.0.0.1 --port 3321
|
|
77
|
+
Then register http://127.0.0.1:3321 as an MCP server in your client.
|
|
152
78
|
```
|
|
153
79
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
## Protocol Fields
|
|
157
|
-
|
|
158
|
-
Granite keeps the core schema small, but now includes a few shared fields that help both humans and agents work safely in the same vault:
|
|
159
|
-
|
|
160
|
-
- `status`: `inbox | active | archived`
|
|
161
|
-
- `source`: `human | agent | extraction`
|
|
162
|
-
- `review_state`: `draft | reviewed | locked`
|
|
163
|
-
- `durability`: `canonical | working | ephemeral`
|
|
164
|
-
- `derived_from`: list of note IDs or slugs used as provenance
|
|
80
|
+
Every one of these leaves you with the same outcome: your agent owns the loop.
|
|
165
81
|
|
|
166
|
-
|
|
82
|
+
## What your agent can do with it
|
|
167
83
|
|
|
168
|
-
|
|
169
|
-
- `durability` distinguishes durable knowledge from working material or situational outputs
|
|
170
|
-
- `derived_from` is the minimal provenance hook for syntheses and outputs
|
|
84
|
+
Once connected, these are real prompts that work **out of the box**:
|
|
171
85
|
|
|
172
|
-
|
|
86
|
+
> **"Process my inbox."**
|
|
87
|
+
> The agent calls `granite_wakeup`, lists inbox notes, classifies each, rewrites them as durable `note`s, links them to existing people/orgs, and promotes `review_state: draft → reviewed`.
|
|
173
88
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
Granite keeps the source of truth boring and durable:
|
|
177
|
-
|
|
178
|
-
- notes are Markdown files
|
|
179
|
-
- metadata lives in YAML frontmatter
|
|
180
|
-
- the default vault lives in `~/.granite`
|
|
181
|
-
- vault configuration lives in `~/.granite/granite.yml`
|
|
182
|
-
- full-text search and link resolution are backed by a local SQLite index in `~/.granite/index.db`
|
|
183
|
-
- the index can be rebuilt from the files at any time
|
|
184
|
-
|
|
185
|
-
This keeps the system transparent, portable, and inspectable.
|
|
186
|
-
|
|
187
|
-
## Agent-Friendly CLI
|
|
188
|
-
|
|
189
|
-
Many commands support JSON output:
|
|
190
|
-
|
|
191
|
-
```bash
|
|
192
|
-
granite new "Sync constraints" --type note --review-state reviewed --durability canonical --json
|
|
193
|
-
granite list --json
|
|
194
|
-
granite show sync-constraints --json
|
|
195
|
-
granite search "constraints" --json
|
|
196
|
-
granite backlinks sync-constraints --json
|
|
197
|
-
granite recommend sync-constraints --json
|
|
198
|
-
```
|
|
89
|
+
> **"Summarize everything I know about [[acme-corp]] before the meeting at 3pm."**
|
|
90
|
+
> `granite_compile_context` returns a typed brief: identity, recent meetings, people, open threads, links into related syntheses. One tool call. No fuzzy matching.
|
|
199
91
|
|
|
200
|
-
|
|
92
|
+
> **"I just talked to Alice from Acme about local-first sync."**
|
|
93
|
+
> `granite_capture_knowledge` creates a `meeting`, fills `date: today` via a hook, resolves `organization: Acme` to a slug (creates a stub if missing), links `attendees: [[alice]]`, and suggests three follow-up notes.
|
|
201
94
|
|
|
202
|
-
|
|
95
|
+
> **"Garden the vault."**
|
|
96
|
+
> `granite_plan_garden` returns the highest-leverage clusters to revisit. The agent opens the top three, revises them, and flags lifecycle transitions (`stale_days`) for your review.
|
|
203
97
|
|
|
204
|
-
|
|
98
|
+
Every one of those is a single MCP round-trip, deterministic, auditable in `git log`.
|
|
205
99
|
|
|
206
|
-
|
|
100
|
+
## Types as active contracts
|
|
207
101
|
|
|
208
|
-
|
|
209
|
-
granite mcp --vault /path/to/vault
|
|
210
|
-
```
|
|
102
|
+
This is what makes the agent feel native rather than bolted-on.
|
|
211
103
|
|
|
212
|
-
|
|
104
|
+
```yaml
|
|
105
|
+
# granite.yml — every note type is an executable contract
|
|
106
|
+
note_types:
|
|
107
|
+
meeting:
|
|
108
|
+
folder: notes/meetings
|
|
109
|
+
fields:
|
|
110
|
+
date: { type: date, required: true }
|
|
111
|
+
organization: { type: wikilink, target_types: [organization] }
|
|
112
|
+
attendees: { type: wikilink, target_types: [person] }
|
|
113
|
+
on_create:
|
|
114
|
+
- { action: set_default, field: date, value: "${today}" }
|
|
115
|
+
- { action: resolve_wikilinks, fields: [organization, attendees], auto_stub: true }
|
|
116
|
+
indexed_fields: [date, organization]
|
|
117
|
+
lifecycle:
|
|
118
|
+
states: [active, archived]
|
|
119
|
+
transitions:
|
|
120
|
+
- { from: active, to: archived, trigger: stale_days, days: 180 }
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
- `set_default` — fills `${today}` automatically
|
|
124
|
+
- `resolve_wikilinks + auto_stub` — turns `organization: Acme Corp` into the slug `acme-corp`, creating the org note if missing (with a globally-unique slug so nothing gets silently overwritten)
|
|
125
|
+
- `indexed_fields` — makes `granite_query { type: meeting, where: { date: { gte: "2026-01-01" } } }` O(1) and deterministic
|
|
126
|
+
- `lifecycle` — `granite doctor` surfaces stale notes so gardening never drifts
|
|
127
|
+
|
|
128
|
+
Add a type when your life has a new shape. The core stays small.
|
|
129
|
+
|
|
130
|
+
## Templates
|
|
213
131
|
|
|
214
132
|
```bash
|
|
215
|
-
granite
|
|
133
|
+
granite init # minimal: note / source / synthesis / output
|
|
134
|
+
granite init --template founder-os # + person / organization / meeting / learning
|
|
216
135
|
```
|
|
217
136
|
|
|
218
|
-
|
|
137
|
+
`founder-os` is the full personal-OS starter: people you talk to, orgs you work with, meetings you had, things you learned. Nine types, already wired with hooks, indexed fields, and lifecycles. Open `templates/founder-os.yml` — it's 150 lines of pure YAML.
|
|
219
138
|
|
|
220
|
-
|
|
221
|
-
- resources for `granite.yml`, vault overview, note types, and individual notes via `granite://notes/{slug}`
|
|
222
|
-
- prompts for refining notes and reviewing links/next steps
|
|
139
|
+
## The hard boundary
|
|
223
140
|
|
|
224
|
-
|
|
141
|
+
Granite will **never**:
|
|
225
142
|
|
|
226
|
-
|
|
143
|
+
- embed an LLM, run prompts, or hold an API key
|
|
144
|
+
- compute embeddings or ship a vector store
|
|
145
|
+
- run background agents or a scheduler
|
|
146
|
+
- add overlapping CLI/MCP endpoints that blur the loop
|
|
227
147
|
|
|
228
|
-
|
|
229
|
-
{
|
|
230
|
-
"command": "granite",
|
|
231
|
-
"args": ["mcp", "--vault", "/path/to/vault"]
|
|
232
|
-
}
|
|
233
|
-
```
|
|
234
|
-
|
|
235
|
-
## Commands
|
|
148
|
+
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).
|
|
236
149
|
|
|
237
|
-
|
|
238
|
-
granite init
|
|
239
|
-
granite new <title> [--type <type>] [--source <source>] [--status <status>] [--review-state <state>] [--durability <durability>] [--derived-from <refs>] [--json]
|
|
240
|
-
granite add [text] [--json]
|
|
241
|
-
granite list [--type <type>] [--json]
|
|
242
|
-
granite edit <slug> [--body <text>] [--append <text>] [--title <title>] [--tag <tags>] [--alias <aliases>] [--status <status>] [--source <source>] [--review-state <state>] [--durability <durability>] [--derived-from <refs>]
|
|
243
|
-
granite open <slug>
|
|
244
|
-
granite show <slug> [--json] [--body]
|
|
245
|
-
granite search <query> [--json]
|
|
246
|
-
granite backlinks <slug> [--json]
|
|
247
|
-
granite suggest-links <slug> [--json]
|
|
248
|
-
granite recommend <slug> [--json]
|
|
249
|
-
granite types
|
|
250
|
-
granite doctor
|
|
251
|
-
granite serve [-p <port>]
|
|
252
|
-
granite mcp [--vault <path>] [--transport <stdio|http>]
|
|
253
|
-
```
|
|
150
|
+
## Protocol fields
|
|
254
151
|
|
|
255
|
-
|
|
152
|
+
Every note carries five shared fields so humans and agents share ground truth:
|
|
256
153
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
154
|
+
| Field | Values | Purpose |
|
|
155
|
+
|----------------|---------------------------------------|--------------------------------------|
|
|
156
|
+
| `status` | `inbox` · `active` · `archived` | operational state |
|
|
157
|
+
| `source` | `human` · `agent` · `extraction` | who wrote it |
|
|
158
|
+
| `review_state` | `draft` · `reviewed` · `locked` | editorial state |
|
|
159
|
+
| `durability` | `canonical` · `working` · `ephemeral` | keep / may drift / throwaway |
|
|
160
|
+
| `derived_from` | `[slug, …]` | provenance for syntheses and outputs |
|
|
264
161
|
|
|
265
|
-
|
|
162
|
+
Your agent reads these before writing and sets them as it works. You inherit a fully auditable trail.
|
|
266
163
|
|
|
267
|
-
|
|
268
|
-
npx vitest run test/core/note.test.ts
|
|
269
|
-
```
|
|
164
|
+
## Local-first, by design
|
|
270
165
|
|
|
271
|
-
|
|
166
|
+
- Markdown files are the source of truth; the SQLite index in `~/.granite/index.db` is derived state and can be rebuilt at any time
|
|
167
|
+
- no cloud, no telemetry, no account
|
|
168
|
+
- `git init` your vault and you have versioning for free
|
|
169
|
+
- `granite serve` gives you a local web UI — browse, search, explore the graph
|
|
272
170
|
|
|
273
|
-
|
|
274
|
-
npx tsx src/index.ts <command>
|
|
275
|
-
```
|
|
171
|
+
For the full CLI, run `granite --help`. For development, see [CLAUDE.md](CLAUDE.md).
|
|
276
172
|
|
|
277
173
|
## Philosophy
|
|
278
174
|
|
|
279
|
-
Granite is built on a few beliefs:
|
|
280
|
-
|
|
281
175
|
- local-first beats cloud dependence for personal memory
|
|
282
|
-
- plain
|
|
283
|
-
-
|
|
284
|
-
- relationships between notes matter more than visual chrome
|
|
285
|
-
- a good PKM should help you decide what to connect or write next
|
|
176
|
+
- plain markdown beats proprietary formats
|
|
177
|
+
- **types as active contracts** beat types as folders
|
|
286
178
|
- tools for humans should also be legible to agents
|
|
287
|
-
- protocol belongs in the core
|
|
179
|
+
- protocol belongs in the core; **agent policy belongs outside it**
|
|
180
|
+
- a personal OS is a thing you own — not a thing you rent
|
|
181
|
+
|
|
182
|
+
---
|
|
288
183
|
|
|
289
|
-
|
|
184
|
+
<p align="center">
|
|
185
|
+
<sub>Ship your agent a home. Then give it the keys.</sub>
|
|
186
|
+
</p>
|