@graph-tl/graph 0.1.0
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/LICENSE +21 -0
- package/README.md +216 -0
- package/dist/activate-DSDTR2EJ.js +45 -0
- package/dist/activate-DSDTR2EJ.js.map +1 -0
- package/dist/chunk-RVM33A4A.js +497 -0
- package/dist/chunk-RVM33A4A.js.map +1 -0
- package/dist/chunk-WKOEKYTF.js +71 -0
- package/dist/chunk-WKOEKYTF.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/init-JYP72OZQ.js +39 -0
- package/dist/init-JYP72OZQ.js.map +1 -0
- package/dist/nodes-75II37NJ.js +24 -0
- package/dist/nodes-75II37NJ.js.map +1 -0
- package/dist/server-7IB2VIMK.js +1476 -0
- package/dist/server-7IB2VIMK.js.map +1 -0
- package/package.json +43 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Graph Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
# Graph
|
|
2
|
+
|
|
3
|
+
A task tracker built for AI agents, not humans.
|
|
4
|
+
|
|
5
|
+
Graph is an MCP server that lets agents plan, execute, and hand off work across sessions. It stores tasks as a dependency graph in SQLite — agents decompose work into subtrees, claim tasks, record what they did, and pass context to the next agent automatically.
|
|
6
|
+
|
|
7
|
+
Humans create projects and review results. Agents do everything in between.
|
|
8
|
+
|
|
9
|
+
## Why
|
|
10
|
+
|
|
11
|
+
Issue trackers (Jira, Linear) are built for humans: columns, boards, sprints, UI. When agents talk to them via MCP, they waste tokens on metadata and need 6+ round trips for simple workflows.
|
|
12
|
+
|
|
13
|
+
Graph gives agents what they actually need:
|
|
14
|
+
- **Persistent across sessions** — an agent picks up exactly where the last one left off
|
|
15
|
+
- **Arbitrary nesting** — decompose work as deep as needed
|
|
16
|
+
- **Dependencies with cycle detection** — the engine knows what's blocked and what's ready
|
|
17
|
+
- **Server-side ranking** — one call to get the highest-priority actionable task
|
|
18
|
+
- **Evidence trail** — agents record decisions, commits, and test results as they work, so the next agent inherits that knowledge
|
|
19
|
+
- **~450 tokens** for a full claim-work-resolve cycle (vs ~5000+ with Linear MCP)
|
|
20
|
+
|
|
21
|
+
## Use Cases
|
|
22
|
+
|
|
23
|
+
**Multi-session projects.** You tell Claude Code to build a feature. It plans the work into a graph, finishes 3 of 5 tasks, and hits the context limit. You start a new session — the agent calls `graph_onboard`, sees what was done, what's left, and picks up the next task with full context. No copy-pasting, no re-explaining.
|
|
24
|
+
|
|
25
|
+
**Agent handoff.** Agent 1 builds the backend. Agent 2 starts a fresh session to work on the frontend. It calls `graph_next` and gets the highest-priority unblocked task, along with evidence from the tasks it depends on — what was implemented, what decisions were made, what files were touched.
|
|
26
|
+
|
|
27
|
+
**Complex decomposition.** You say "build me a CLI tool with auth, a database layer, and tests." The agent breaks this into a task tree with dependencies — tests depend on implementation, implementation depends on design. The engine tracks what's blocked and what's ready so the agent always works on the right thing.
|
|
28
|
+
|
|
29
|
+
**Replanning mid-flight.** Halfway through a project, requirements change. The agent uses `graph_restructure` to drop irrelevant tasks, add new ones, and reparent subtrees. Dependencies recalculate automatically.
|
|
30
|
+
|
|
31
|
+
## How It Works
|
|
32
|
+
|
|
33
|
+
An agent's workflow with Graph looks like this:
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
1. graph_onboard → "What's the state of this project?"
|
|
37
|
+
2. graph_next → "What should I work on?" (claim it)
|
|
38
|
+
3. ... do the work ...
|
|
39
|
+
4. graph_update → "Done. Here's what I did." (resolve with evidence)
|
|
40
|
+
5. → engine returns newly unblocked tasks
|
|
41
|
+
6. graph_next → "What's next?"
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
When a new agent joins, `graph_onboard` returns everything it needs in one call: project status, task tree, recent evidence from completed work, all file references, and what's actionable now.
|
|
45
|
+
|
|
46
|
+
### Example: Planning a project
|
|
47
|
+
|
|
48
|
+
You tell the agent: "Build a REST API with authentication and tests."
|
|
49
|
+
|
|
50
|
+
The agent calls `graph_plan` to create this structure:
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
Build REST API
|
|
54
|
+
├── Design
|
|
55
|
+
│ └── Write API spec
|
|
56
|
+
├── Implementation
|
|
57
|
+
│ ├── Auth module (depends on: Write API spec)
|
|
58
|
+
│ ├── Routes (depends on: Write API spec)
|
|
59
|
+
│ └── Database layer
|
|
60
|
+
└── Testing
|
|
61
|
+
├── Unit tests (depends on: Auth, Routes, Database)
|
|
62
|
+
└── Integration tests (depends on: Unit tests)
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
`graph_next` immediately knows: "Write API spec" and "Database layer" are actionable. Everything else is blocked. When "Write API spec" is resolved, "Auth module" and "Routes" unblock automatically.
|
|
66
|
+
|
|
67
|
+
### Example: Agent handoff between sessions
|
|
68
|
+
|
|
69
|
+
Session 1 ends after completing 3 tasks. Session 2 starts:
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
→ graph_onboard("my-project")
|
|
73
|
+
|
|
74
|
+
← {
|
|
75
|
+
summary: { total: 8, resolved: 3, unresolved: 5, actionable: 2 },
|
|
76
|
+
recent_evidence: [
|
|
77
|
+
{ task: "Auth module", type: "note", ref: "Used JWT with RS256, keys in /config" },
|
|
78
|
+
{ task: "Auth module", type: "git", ref: "a]1b2c3d — implement auth middleware" },
|
|
79
|
+
...
|
|
80
|
+
],
|
|
81
|
+
context_links: ["src/auth.ts", "src/db.ts", "config/keys.json"],
|
|
82
|
+
actionable: [
|
|
83
|
+
{ summary: "Routes", priority: 8 },
|
|
84
|
+
{ summary: "Database layer", priority: 7 },
|
|
85
|
+
]
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
The new agent knows what was built, how, and what to do next — without reading the entire codebase or prior conversation.
|
|
90
|
+
|
|
91
|
+
### Code annotations: from static comments to traceable history
|
|
92
|
+
|
|
93
|
+
Code comments tell you *what* code does. Graph annotations tell you *why it exists, who wrote it, and what was considered*.
|
|
94
|
+
|
|
95
|
+
When agents work through Graph, they annotate key changes with `// [sl:nodeId]`:
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
// [sl:OZ0or-q5TserCEfWUeMVv] Require evidence when resolving
|
|
99
|
+
if (input.resolved === true && !node.resolved) {
|
|
100
|
+
const hasExistingEvidence = node.evidence.length > 0;
|
|
101
|
+
const hasNewEvidence = input.add_evidence && input.add_evidence.length > 0;
|
|
102
|
+
if (!hasExistingEvidence && !hasNewEvidence) {
|
|
103
|
+
throw new EngineError("evidence_required", ...);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
That node ID links to a task in the graph. A future agent (or human) can call `graph_context` or `graph_history` on that ID and get:
|
|
109
|
+
|
|
110
|
+
- **What the task was** — "Enforce evidence on resolve"
|
|
111
|
+
- **Why it was done** — the evidence trail: design decisions, alternatives considered
|
|
112
|
+
- **What else changed** — context links to every file modified for that task
|
|
113
|
+
- **Who did it and when** — the full audit log
|
|
114
|
+
|
|
115
|
+
Comments are a snapshot. Graph turns your codebase into a traceable history of decisions.
|
|
116
|
+
|
|
117
|
+
## Install
|
|
118
|
+
|
|
119
|
+
Add to your Claude Code MCP config (`.mcp.json` in your project root):
|
|
120
|
+
|
|
121
|
+
```json
|
|
122
|
+
{
|
|
123
|
+
"mcpServers": {
|
|
124
|
+
"graph": {
|
|
125
|
+
"command": "npx",
|
|
126
|
+
"args": ["-y", "@graph-tl/graph"],
|
|
127
|
+
"env": {
|
|
128
|
+
"GRAPH_AGENT": "claude-code"
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
That's it. No cloning, no building. npx handles everything.
|
|
136
|
+
|
|
137
|
+
### From source
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
git clone https://github.com/Graph-tl/graph.git
|
|
141
|
+
cd graph
|
|
142
|
+
npm install
|
|
143
|
+
npm run build
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Then point your `.mcp.json` at the local build:
|
|
147
|
+
|
|
148
|
+
```json
|
|
149
|
+
{
|
|
150
|
+
"mcpServers": {
|
|
151
|
+
"graph": {
|
|
152
|
+
"command": "node",
|
|
153
|
+
"args": ["./graph/dist/index.js"],
|
|
154
|
+
"env": {
|
|
155
|
+
"GRAPH_AGENT": "claude-code"
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Environment variables:
|
|
163
|
+
- `GRAPH_AGENT` — agent identity, attached to all writes (default: `default-agent`)
|
|
164
|
+
- `GRAPH_DB` — SQLite database path (default: `./graph.db`)
|
|
165
|
+
- `GRAPH_CLAIM_TTL` — soft claim expiry in minutes (default: `60`)
|
|
166
|
+
|
|
167
|
+
## Tools
|
|
168
|
+
|
|
169
|
+
| Tool | Purpose |
|
|
170
|
+
|---|---|
|
|
171
|
+
| **graph_onboard** | Single-call orientation for a new agent joining a project. Returns project summary, task tree, recent evidence, context links, and actionable tasks. |
|
|
172
|
+
| **graph_open** | Open or create a project. No args = list all projects. |
|
|
173
|
+
| **graph_plan** | Batch create tasks with parent-child and dependency relationships. Atomic. |
|
|
174
|
+
| **graph_next** | Get the next actionable task, ranked by priority/depth/recency. Optional scope to a subtree. Optional soft claim. |
|
|
175
|
+
| **graph_context** | Deep-read a task: ancestors, children tree, dependency graph. |
|
|
176
|
+
| **graph_update** | Resolve tasks, add evidence/context links. Reports newly unblocked tasks. |
|
|
177
|
+
| **graph_connect** | Add or remove dependency edges. Cycle detection on `depends_on`. |
|
|
178
|
+
| **graph_query** | Search and filter tasks by state, properties, text, ancestry, actionability. |
|
|
179
|
+
| **graph_restructure** | Move, merge, or drop tasks. For replanning. |
|
|
180
|
+
| **graph_history** | Audit trail for a task — who changed what, when. |
|
|
181
|
+
|
|
182
|
+
See [TOOLS.md](TOOLS.md) for full schemas and response shapes.
|
|
183
|
+
|
|
184
|
+
## Token Efficiency
|
|
185
|
+
|
|
186
|
+
Every response is compact JSON — no UI chrome, no avatar URLs, no pagination boilerplate. Measured against real Claude Code sessions:
|
|
187
|
+
|
|
188
|
+
| Operation | Tokens | Round trips |
|
|
189
|
+
|---|---|---|
|
|
190
|
+
| Onboard a new agent to a 30-task project | ~500 | 1 |
|
|
191
|
+
| Plan 4 tasks with dependencies | ~220 | 1 |
|
|
192
|
+
| Get next actionable task (with context) | ~300 | 1 |
|
|
193
|
+
| Resolve a task + see what unblocked | ~120 | 1 |
|
|
194
|
+
| **Full claim-work-resolve cycle** | **~450** | **3** |
|
|
195
|
+
|
|
196
|
+
The same workflow through a traditional tracker's MCP integration typically costs ~4500 tokens across 6 round trips. **~90% token reduction, ~50% fewer round trips.**
|
|
197
|
+
|
|
198
|
+
## Data & Security
|
|
199
|
+
|
|
200
|
+
Graph is fully local. Your data never leaves your machine.
|
|
201
|
+
|
|
202
|
+
- **Single SQLite file** — everything is stored in one `.db` file at the path you configure via `GRAPH_DB`. Default: `./graph.db` in the working directory.
|
|
203
|
+
- **No network calls** — Graph is a stdio MCP server. It reads and writes to disk. There is no telemetry, no cloud sync, no external API calls.
|
|
204
|
+
- **No secrets in the graph** — Graph stores task summaries, evidence notes, and file path references. It does not read file contents, access credentials, or store source code.
|
|
205
|
+
- **You control the data** — the SQLite file is yours. Back it up, delete it, move it between machines. There is no account, no server, no lock-in.
|
|
206
|
+
- **Gitignore it** — add `*.db` to your `.gitignore`. The graph contains project-specific planning data that doesn't belong in version control.
|
|
207
|
+
|
|
208
|
+
## Design
|
|
209
|
+
|
|
210
|
+
- **`resolved` boolean** is the only field the engine interprets. Drives dependency computation. `state` is freeform for agent semantics.
|
|
211
|
+
- **Evidence model** — hints, notes, commits, test results are all evidence entries with a `type` field. One mechanism.
|
|
212
|
+
- **Linked context** — nodes store pointers to files/commits/docs, not content blobs.
|
|
213
|
+
|
|
214
|
+
## License
|
|
215
|
+
|
|
216
|
+
MIT
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
verifyLicenseKey
|
|
4
|
+
} from "./chunk-WKOEKYTF.js";
|
|
5
|
+
|
|
6
|
+
// src/activate.ts
|
|
7
|
+
import { mkdirSync, writeFileSync } from "fs";
|
|
8
|
+
import { join } from "path";
|
|
9
|
+
import { homedir } from "os";
|
|
10
|
+
var KEY_PREFIX = "graph_";
|
|
11
|
+
function validateKeyFormat(key) {
|
|
12
|
+
const raw = key.startsWith(KEY_PREFIX) ? key.slice(KEY_PREFIX.length) : key;
|
|
13
|
+
const parts = raw.split(".");
|
|
14
|
+
return parts.length === 3 && parts.every((p) => p.length > 0);
|
|
15
|
+
}
|
|
16
|
+
function activate(key) {
|
|
17
|
+
if (!key) {
|
|
18
|
+
console.error("Usage: graph activate <license-key>");
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}
|
|
21
|
+
if (!validateKeyFormat(key)) {
|
|
22
|
+
console.error("Invalid key format. Expected: graph_<header>.<payload>.<signature>");
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
const info = verifyLicenseKey(key);
|
|
26
|
+
if (info) {
|
|
27
|
+
const expDate = new Date(info.exp * 1e3).toISOString().split("T")[0];
|
|
28
|
+
console.log(`Verified: ${info.tier} tier, expires ${expDate}`);
|
|
29
|
+
} else if (process.env.GRAPH_LICENSE_PUBLIC_KEY) {
|
|
30
|
+
console.error("Key signature verification failed. The key may be invalid or expired.");
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
const dir = join(homedir(), ".graph");
|
|
34
|
+
mkdirSync(dir, { recursive: true });
|
|
35
|
+
const path = join(dir, "license");
|
|
36
|
+
writeFileSync(path, key, "utf8");
|
|
37
|
+
console.log(`License key saved to ${path}`);
|
|
38
|
+
if (!info) {
|
|
39
|
+
console.log("Key stored (signature not verified \u2014 public key not configured).");
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
export {
|
|
43
|
+
activate
|
|
44
|
+
};
|
|
45
|
+
//# sourceMappingURL=activate-DSDTR2EJ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/activate.ts"],"sourcesContent":["import { mkdirSync, writeFileSync } from \"fs\";\nimport { join } from \"path\";\nimport { homedir } from \"os\";\nimport { verifyLicenseKey } from \"./license.js\";\n\n// [sl:WvU_sWubakQWRCkP993pp] CLI activation — store license key locally\n\nconst KEY_PREFIX = \"graph_\";\n\nfunction validateKeyFormat(key: string): boolean {\n const raw = key.startsWith(KEY_PREFIX) ? key.slice(KEY_PREFIX.length) : key;\n const parts = raw.split(\".\");\n return parts.length === 3 && parts.every((p) => p.length > 0);\n}\n\nexport function activate(key: string): void {\n if (!key) {\n console.error(\"Usage: graph activate <license-key>\");\n process.exit(1);\n }\n\n // Basic format check\n if (!validateKeyFormat(key)) {\n console.error(\"Invalid key format. Expected: graph_<header>.<payload>.<signature>\");\n process.exit(1);\n }\n\n // Try to verify if public key is available\n const info = verifyLicenseKey(key);\n if (info) {\n const expDate = new Date(info.exp * 1000).toISOString().split(\"T\")[0];\n console.log(`Verified: ${info.tier} tier, expires ${expDate}`);\n } else if (process.env.GRAPH_LICENSE_PUBLIC_KEY) {\n console.error(\"Key signature verification failed. The key may be invalid or expired.\");\n process.exit(1);\n }\n\n // Store to ~/.graph/license\n const dir = join(homedir(), \".graph\");\n mkdirSync(dir, { recursive: true });\n const path = join(dir, \"license\");\n writeFileSync(path, key, \"utf8\");\n\n console.log(`License key saved to ${path}`);\n if (!info) {\n console.log(\"Key stored (signature not verified — public key not configured).\");\n }\n}\n"],"mappings":";;;;;;AAAA,SAAS,WAAW,qBAAqB;AACzC,SAAS,YAAY;AACrB,SAAS,eAAe;AAKxB,IAAM,aAAa;AAEnB,SAAS,kBAAkB,KAAsB;AAC/C,QAAM,MAAM,IAAI,WAAW,UAAU,IAAI,IAAI,MAAM,WAAW,MAAM,IAAI;AACxE,QAAM,QAAQ,IAAI,MAAM,GAAG;AAC3B,SAAO,MAAM,WAAW,KAAK,MAAM,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC;AAC9D;AAEO,SAAS,SAAS,KAAmB;AAC1C,MAAI,CAAC,KAAK;AACR,YAAQ,MAAM,qCAAqC;AACnD,YAAQ,KAAK,CAAC;AAAA,EAChB;AAGA,MAAI,CAAC,kBAAkB,GAAG,GAAG;AAC3B,YAAQ,MAAM,oEAAoE;AAClF,YAAQ,KAAK,CAAC;AAAA,EAChB;AAGA,QAAM,OAAO,iBAAiB,GAAG;AACjC,MAAI,MAAM;AACR,UAAM,UAAU,IAAI,KAAK,KAAK,MAAM,GAAI,EAAE,YAAY,EAAE,MAAM,GAAG,EAAE,CAAC;AACpE,YAAQ,IAAI,aAAa,KAAK,IAAI,kBAAkB,OAAO,EAAE;AAAA,EAC/D,WAAW,QAAQ,IAAI,0BAA0B;AAC/C,YAAQ,MAAM,uEAAuE;AACrF,YAAQ,KAAK,CAAC;AAAA,EAChB;AAGA,QAAM,MAAM,KAAK,QAAQ,GAAG,QAAQ;AACpC,YAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AAClC,QAAM,OAAO,KAAK,KAAK,SAAS;AAChC,gBAAc,MAAM,KAAK,MAAM;AAE/B,UAAQ,IAAI,wBAAwB,IAAI,EAAE;AAC1C,MAAI,CAAC,MAAM;AACT,YAAQ,IAAI,uEAAkE;AAAA,EAChF;AACF;","names":[]}
|