granite-mem 0.1.7 → 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 -207
- package/dist/index.js +4997 -1444
- package/dist/public/app.js +17 -588
- package/dist/public/graph-engine.js +102 -0
- package/dist/public/index.html +117 -126
- package/dist/public/markdown-renderer.js +1 -189
- package/dist/public/style.css +1 -923
- package/dist/templates/founder-os.yml +204 -0
- package/package.json +9 -3
- package/templates/founder-os.yml +204 -0
- package/dist/public/canvas-renderer.js +0 -524
- package/dist/public/graph.js +0 -380
package/README.md
CHANGED
|
@@ -1,269 +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
|
-
- link people, meetings, projects, and decisions
|
|
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
|
-
- `permanent` for durable ideas
|
|
44
|
-
- `reference` for external sources
|
|
45
|
-
- `person` for people and relationships
|
|
46
|
-
- `meeting` for notes with attendees, decisions, and actions
|
|
47
|
-
- `project` for active work
|
|
48
|
-
- `decision` for durable decision records
|
|
49
|
+
### Claude Code / Claude Desktop
|
|
49
50
|
|
|
50
|
-
This is enough structure to make your notes connect naturally, without forcing you into a heavyweight system.
|
|
51
|
-
|
|
52
|
-
### 2. Custom types without losing the plot
|
|
53
|
-
|
|
54
|
-
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.
|
|
55
|
-
|
|
56
|
-
### 3. Agent-native, not just agent-compatible
|
|
57
|
-
|
|
58
|
-
Granite is designed to be easy for agents to read and act on:
|
|
59
|
-
|
|
60
|
-
- notes are plain files
|
|
61
|
-
- metadata is explicit
|
|
62
|
-
- commands support `--json`
|
|
63
|
-
- Granite ships with an MCP server
|
|
64
|
-
- vault structure is predictable
|
|
65
|
-
- search, backlinks, and recommendations are available from the CLI
|
|
66
|
-
|
|
67
|
-
It works well as a personal system, and it also works as a memory layer for coding agents, assistants, or local automation.
|
|
68
|
-
|
|
69
|
-
## Quickstart
|
|
70
|
-
|
|
71
|
-
Clone the repo and install dependencies:
|
|
72
|
-
|
|
73
|
-
```bash
|
|
74
|
-
git clone https://github.com/The-Vibe-Company/Granite
|
|
75
|
-
cd Granite
|
|
76
|
-
npm install
|
|
77
|
-
npm run build
|
|
78
|
-
npm link
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
Create the default vault in `~/.granite` and start capturing:
|
|
82
|
-
|
|
83
|
-
```bash
|
|
84
|
-
granite init
|
|
85
|
-
granite add "Talked to Alice about local-first sync tradeoffs"
|
|
86
|
-
granite new "Local-first sync tradeoffs" --type permanent
|
|
87
|
-
granite list
|
|
88
|
-
granite search "sync"
|
|
89
51
|
```
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
granite mcp # MCP server for agent clients
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
`granite new` does more than create a file. It can immediately suggest related links, tags, and the next note to create, which is the core of Granite's value loop.
|
|
99
|
-
|
|
100
|
-
## Example Workflow
|
|
101
|
-
|
|
102
|
-
Capture something quickly:
|
|
103
|
-
|
|
104
|
-
```bash
|
|
105
|
-
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.
|
|
106
57
|
```
|
|
107
58
|
|
|
108
|
-
|
|
59
|
+
### Cursor
|
|
109
60
|
|
|
110
|
-
```bash
|
|
111
|
-
granite new "Strong defaults beat infinite flexibility" --type permanent
|
|
112
61
|
```
|
|
62
|
+
Run these commands, then add Granite to .cursor/mcp.json:
|
|
63
|
+
npm install -g granite-mem
|
|
64
|
+
granite init --template founder-os
|
|
113
65
|
|
|
114
|
-
|
|
66
|
+
Append to .cursor/mcp.json:
|
|
67
|
+
{ "mcpServers": { "granite": { "command": "granite", "args": ["mcp", "--vault", "~/.granite"] } } }
|
|
115
68
|
|
|
116
|
-
|
|
117
|
-
granite suggest-links strong-defaults-beat-infinite-flexibility
|
|
118
|
-
granite recommend strong-defaults-beat-infinite-flexibility
|
|
119
|
-
granite backlinks strong-defaults-beat-infinite-flexibility
|
|
69
|
+
Reload Cursor. Then call granite_wakeup.
|
|
120
70
|
```
|
|
121
71
|
|
|
122
|
-
|
|
72
|
+
### ChatGPT / any HTTP-MCP client
|
|
123
73
|
|
|
124
|
-
```bash
|
|
125
|
-
granite serve
|
|
126
74
|
```
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-

|
|
131
|
-
|
|
132
|
-
## Custom Note Types
|
|
133
|
-
|
|
134
|
-
Granite is intentionally small, but not rigid. Add a type in `granite.yml` when your workflow genuinely needs it:
|
|
135
|
-
|
|
136
|
-
```yaml
|
|
137
|
-
note_types:
|
|
138
|
-
idea:
|
|
139
|
-
folder: notes/ideas
|
|
140
|
-
description: Early product ideas worth pressure-testing
|
|
141
|
-
template: |
|
|
142
|
-
## Problem
|
|
143
|
-
|
|
144
|
-
## Insight
|
|
145
|
-
|
|
146
|
-
## Why now
|
|
147
|
-
|
|
148
|
-
## Next step
|
|
149
|
-
line_limit: 120
|
|
150
|
-
warn_only: true
|
|
151
|
-
slug_format: title
|
|
152
|
-
instructions: Capture the idea clearly, then link it to a project, person, or permanent note.
|
|
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.
|
|
153
78
|
```
|
|
154
79
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
## Local-First Architecture
|
|
80
|
+
Every one of these leaves you with the same outcome: your agent owns the loop.
|
|
158
81
|
|
|
159
|
-
|
|
82
|
+
## What your agent can do with it
|
|
160
83
|
|
|
161
|
-
|
|
162
|
-
- metadata lives in YAML frontmatter
|
|
163
|
-
- the default vault lives in `~/.granite`
|
|
164
|
-
- vault configuration lives in `~/.granite/granite.yml`
|
|
165
|
-
- full-text search and link resolution are backed by a local SQLite index in `~/.granite/index.db`
|
|
166
|
-
- the index can be rebuilt from the files at any time
|
|
84
|
+
Once connected, these are real prompts that work **out of the box**:
|
|
167
85
|
|
|
168
|
-
|
|
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`.
|
|
169
88
|
|
|
170
|
-
|
|
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.
|
|
171
91
|
|
|
172
|
-
|
|
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.
|
|
173
94
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
granite list --json
|
|
177
|
-
granite show sync-constraints --json
|
|
178
|
-
granite search "constraints" --json
|
|
179
|
-
granite backlinks sync-constraints --json
|
|
180
|
-
granite recommend sync-constraints --json
|
|
181
|
-
```
|
|
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.
|
|
182
97
|
|
|
183
|
-
|
|
98
|
+
Every one of those is a single MCP round-trip, deterministic, auditable in `git log`.
|
|
184
99
|
|
|
185
|
-
##
|
|
100
|
+
## Types as active contracts
|
|
186
101
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
Start it over stdio for local MCP clients:
|
|
190
|
-
|
|
191
|
-
```bash
|
|
192
|
-
granite mcp --vault /path/to/vault
|
|
193
|
-
```
|
|
102
|
+
This is what makes the agent feel native rather than bolted-on.
|
|
194
103
|
|
|
195
|
-
|
|
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
|
|
196
131
|
|
|
197
132
|
```bash
|
|
198
|
-
granite
|
|
133
|
+
granite init # minimal: note / source / synthesis / output
|
|
134
|
+
granite init --template founder-os # + person / organization / meeting / learning
|
|
199
135
|
```
|
|
200
136
|
|
|
201
|
-
|
|
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.
|
|
202
138
|
|
|
203
|
-
|
|
204
|
-
- resources for `granite.yml`, vault overview, note types, and individual notes via `granite://notes/{slug}`
|
|
205
|
-
- prompts for refining notes and reviewing links/next steps
|
|
139
|
+
## The hard boundary
|
|
206
140
|
|
|
207
|
-
|
|
141
|
+
Granite will **never**:
|
|
208
142
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
}
|
|
214
|
-
```
|
|
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
|
|
215
147
|
|
|
216
|
-
|
|
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).
|
|
217
149
|
|
|
218
|
-
|
|
219
|
-
granite init
|
|
220
|
-
granite new <title> [--type <type>] [--json]
|
|
221
|
-
granite add [text] [--json]
|
|
222
|
-
granite list [--type <type>] [--json]
|
|
223
|
-
granite edit <slug>
|
|
224
|
-
granite open <slug>
|
|
225
|
-
granite show <slug> [--json] [--body]
|
|
226
|
-
granite search <query> [--json]
|
|
227
|
-
granite backlinks <slug> [--json]
|
|
228
|
-
granite suggest-links <slug> [--json]
|
|
229
|
-
granite recommend <slug> [--json]
|
|
230
|
-
granite types
|
|
231
|
-
granite doctor
|
|
232
|
-
granite serve [-p <port>]
|
|
233
|
-
granite mcp [--vault <path>] [--transport <stdio|http>]
|
|
234
|
-
```
|
|
150
|
+
## Protocol fields
|
|
235
151
|
|
|
236
|
-
|
|
152
|
+
Every note carries five shared fields so humans and agents share ground truth:
|
|
237
153
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
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 |
|
|
245
161
|
|
|
246
|
-
|
|
162
|
+
Your agent reads these before writing and sets them as it works. You inherit a fully auditable trail.
|
|
247
163
|
|
|
248
|
-
|
|
249
|
-
npx vitest run test/core/note.test.ts
|
|
250
|
-
```
|
|
164
|
+
## Local-first, by design
|
|
251
165
|
|
|
252
|
-
|
|
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
|
|
253
170
|
|
|
254
|
-
|
|
255
|
-
npx tsx src/index.ts <command>
|
|
256
|
-
```
|
|
171
|
+
For the full CLI, run `granite --help`. For development, see [CLAUDE.md](CLAUDE.md).
|
|
257
172
|
|
|
258
173
|
## Philosophy
|
|
259
174
|
|
|
260
|
-
Granite is built on a few beliefs:
|
|
261
|
-
|
|
262
175
|
- local-first beats cloud dependence for personal memory
|
|
263
|
-
- plain
|
|
264
|
-
-
|
|
265
|
-
- relationships between notes matter more than visual chrome
|
|
266
|
-
- 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
|
|
267
178
|
- tools for humans should also be legible to agents
|
|
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
|
+
---
|
|
268
183
|
|
|
269
|
-
|
|
184
|
+
<p align="center">
|
|
185
|
+
<sub>Ship your agent a home. Then give it the keys.</sub>
|
|
186
|
+
</p>
|