contextsliver 0.1.1
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 +130 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +156 -0
- package/dist/cli.js.map +1 -0
- package/dist/graph/rank.d.ts +9 -0
- package/dist/graph/rank.d.ts.map +1 -0
- package/dist/graph/rank.js +10 -0
- package/dist/graph/rank.js.map +1 -0
- package/dist/graph/schema.d.ts +4 -0
- package/dist/graph/schema.d.ts.map +1 -0
- package/dist/graph/schema.js +74 -0
- package/dist/graph/schema.js.map +1 -0
- package/dist/graph/store.d.ts +56 -0
- package/dist/graph/store.d.ts.map +1 -0
- package/dist/graph/store.js +163 -0
- package/dist/graph/store.js.map +1 -0
- package/dist/graph/traverse.d.ts +20 -0
- package/dist/graph/traverse.d.ts.map +1 -0
- package/dist/graph/traverse.js +81 -0
- package/dist/graph/traverse.js.map +1 -0
- package/dist/graph/types.d.ts +48 -0
- package/dist/graph/types.d.ts.map +1 -0
- package/dist/graph/types.js +4 -0
- package/dist/graph/types.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/responses.d.ts +19 -0
- package/dist/mcp/responses.d.ts.map +1 -0
- package/dist/mcp/responses.js +25 -0
- package/dist/mcp/responses.js.map +1 -0
- package/dist/mcp/server.d.ts +16 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +88 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/tools/cs_blast_radius.d.ts +3 -0
- package/dist/mcp/tools/cs_blast_radius.d.ts.map +1 -0
- package/dist/mcp/tools/cs_blast_radius.js +96 -0
- package/dist/mcp/tools/cs_blast_radius.js.map +1 -0
- package/dist/mcp/tools/cs_get_context.d.ts +3 -0
- package/dist/mcp/tools/cs_get_context.d.ts.map +1 -0
- package/dist/mcp/tools/cs_get_context.js +80 -0
- package/dist/mcp/tools/cs_get_context.js.map +1 -0
- package/dist/mcp/tools/cs_index_repo.d.ts +3 -0
- package/dist/mcp/tools/cs_index_repo.d.ts.map +1 -0
- package/dist/mcp/tools/cs_index_repo.js +45 -0
- package/dist/mcp/tools/cs_index_repo.js.map +1 -0
- package/dist/mcp/tools/cs_index_status.d.ts +3 -0
- package/dist/mcp/tools/cs_index_status.d.ts.map +1 -0
- package/dist/mcp/tools/cs_index_status.js +31 -0
- package/dist/mcp/tools/cs_index_status.js.map +1 -0
- package/dist/mcp/tools/cs_search_symbols.d.ts +3 -0
- package/dist/mcp/tools/cs_search_symbols.d.ts.map +1 -0
- package/dist/mcp/tools/cs_search_symbols.js +51 -0
- package/dist/mcp/tools/cs_search_symbols.js.map +1 -0
- package/dist/mcp/tools/index.d.ts +4 -0
- package/dist/mcp/tools/index.d.ts.map +1 -0
- package/dist/mcp/tools/index.js +14 -0
- package/dist/mcp/tools/index.js.map +1 -0
- package/dist/mcp/types.d.ts +22 -0
- package/dist/mcp/types.d.ts.map +1 -0
- package/dist/mcp/types.js +2 -0
- package/dist/mcp/types.js.map +1 -0
- package/dist/parser/extractor.d.ts +16 -0
- package/dist/parser/extractor.d.ts.map +1 -0
- package/dist/parser/extractor.js +304 -0
- package/dist/parser/extractor.js.map +1 -0
- package/dist/parser/index.d.ts +30 -0
- package/dist/parser/index.d.ts.map +1 -0
- package/dist/parser/index.js +270 -0
- package/dist/parser/index.js.map +1 -0
- package/dist/parser/languages/python.d.ts +3 -0
- package/dist/parser/languages/python.d.ts.map +1 -0
- package/dist/parser/languages/python.js +14 -0
- package/dist/parser/languages/python.js.map +1 -0
- package/dist/parser/languages/query-loader.d.ts +10 -0
- package/dist/parser/languages/query-loader.d.ts.map +1 -0
- package/dist/parser/languages/query-loader.js +33 -0
- package/dist/parser/languages/query-loader.js.map +1 -0
- package/dist/parser/languages/registry.d.ts +25 -0
- package/dist/parser/languages/registry.d.ts.map +1 -0
- package/dist/parser/languages/registry.js +33 -0
- package/dist/parser/languages/registry.js.map +1 -0
- package/dist/parser/languages/typescript.d.ts +11 -0
- package/dist/parser/languages/typescript.d.ts.map +1 -0
- package/dist/parser/languages/typescript.js +26 -0
- package/dist/parser/languages/typescript.js.map +1 -0
- package/dist/parser/types.d.ts +36 -0
- package/dist/parser/types.d.ts.map +1 -0
- package/dist/parser/types.js +2 -0
- package/dist/parser/types.js.map +1 -0
- package/dist/session/manager.d.ts +28 -0
- package/dist/session/manager.d.ts.map +1 -0
- package/dist/session/manager.js +82 -0
- package/dist/session/manager.js.map +1 -0
- package/dist/session/pruner.d.ts +28 -0
- package/dist/session/pruner.d.ts.map +1 -0
- package/dist/session/pruner.js +24 -0
- package/dist/session/pruner.js.map +1 -0
- package/dist/session/types.d.ts +21 -0
- package/dist/session/types.d.ts.map +1 -0
- package/dist/session/types.js +4 -0
- package/dist/session/types.js.map +1 -0
- package/dist/utils/logger.d.ts +13 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +36 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/paths.d.ts +24 -0
- package/dist/utils/paths.d.ts.map +1 -0
- package/dist/utils/paths.js +55 -0
- package/dist/utils/paths.js.map +1 -0
- package/dist/utils/tokens.d.ts +10 -0
- package/dist/utils/tokens.d.ts.map +1 -0
- package/dist/utils/tokens.js +28 -0
- package/dist/utils/tokens.js.map +1 -0
- package/dist/watcher/hasher.d.ts +11 -0
- package/dist/watcher/hasher.d.ts.map +1 -0
- package/dist/watcher/hasher.js +29 -0
- package/dist/watcher/hasher.js.map +1 -0
- package/dist/watcher/index.d.ts +9 -0
- package/dist/watcher/index.d.ts.map +1 -0
- package/dist/watcher/index.js +100 -0
- package/dist/watcher/index.js.map +1 -0
- package/grammars/python/tags.scm +16 -0
- package/grammars/typescript/tags.scm +39 -0
- package/hooks/pre-tool-use.js +46 -0
- package/package.json +89 -0
- package/templates/CLAUDE.md +50 -0
- package/templates/mcp-config-claude-code.json +9 -0
- package/templates/mcp-config-cline.json +15 -0
- package/templates/mcp-config-cursor.json +9 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 DevMuneeb
|
|
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,130 @@
|
|
|
1
|
+
# ContextSliver
|
|
2
|
+
|
|
3
|
+
> On-demand context management for AI coding agents. Stop reading whole files — ask for the connected subgraph instead.
|
|
4
|
+
|
|
5
|
+
[](https://github.com/DevMuneeb/contextsliver/actions/workflows/ci.yml)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
[](https://www.npmjs.com/package/contextsliver)
|
|
8
|
+
|
|
9
|
+
## The problem
|
|
10
|
+
|
|
11
|
+
When you ask an AI coding agent (Claude Code, Cursor, Cline) to *"fix the bug in AuthService,"* it
|
|
12
|
+
repeatedly reads entire files to find the 5% that's relevant — burning 40,000–80,000 tokens on a
|
|
13
|
+
question that needed ~3,000.
|
|
14
|
+
|
|
15
|
+
```text
|
|
16
|
+
find . -name "*.ts" → 2,000 tokens (a file listing)
|
|
17
|
+
cat AuthService.ts → 3,000 tokens (whole file)
|
|
18
|
+
grep -r "AuthService" → 5,000 tokens (40 matches)
|
|
19
|
+
cat AuthMiddleware.ts → 2,500 tokens (whole file, again)
|
|
20
|
+
... × 10 more ...
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Existing tools don't fully fix it: Graphify dumps one enormous whole-repo map into context up front;
|
|
24
|
+
Repomix packs the entire repo into one file; Aider's repo-map sends a whole-repo summary with every
|
|
25
|
+
message. **None of them track what the agent has already seen this session.**
|
|
26
|
+
|
|
27
|
+
## What ContextSliver does
|
|
28
|
+
|
|
29
|
+
ContextSliver runs as a background **MCP server** on your machine. It indexes your codebase into a
|
|
30
|
+
local SQLite graph of every function, class, and import. When the agent needs context, it calls an
|
|
31
|
+
MCP tool instead of reading files:
|
|
32
|
+
|
|
33
|
+
```text
|
|
34
|
+
Agent: "What connects to AuthService? Budget: 2,000 tokens."
|
|
35
|
+
|
|
36
|
+
ContextSliver:
|
|
37
|
+
symbol: AuthService (src/auth/AuthService.ts)
|
|
38
|
+
callers: [AuthMiddleware, LoginController] ← who uses it
|
|
39
|
+
dependencies: [UserRepository, TokenService] ← what it uses
|
|
40
|
+
already_in_context: [UserRepository] ← skipped, agent already has it
|
|
41
|
+
// ~380 tokens
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Three things make it different:
|
|
45
|
+
|
|
46
|
+
1. **On-demand pruning** — never sends the whole graph, only the connected subgraph for the task.
|
|
47
|
+
2. **Session ledger** — tracks what the agent has already seen and skips re-sending it.
|
|
48
|
+
3. **One-command setup** — `npx contextsliver init`. No database server, no API key.
|
|
49
|
+
|
|
50
|
+
## Quickstart
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
# In your project root:
|
|
54
|
+
npx contextsliver init # creates .sliver/, .mcp.json, CLAUDE.md, indexes the repo
|
|
55
|
+
npx contextsliver start # runs the MCP server + file watcher (stdio)
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Then restart Claude Code / Cursor / Cline — they'll pick up the five tools automatically. See the
|
|
59
|
+
[templates](./templates) for client-specific config.
|
|
60
|
+
|
|
61
|
+
## The five MCP tools
|
|
62
|
+
|
|
63
|
+
| Tool | What it does | Typical tokens |
|
|
64
|
+
|------|-------------|---------------|
|
|
65
|
+
| `cs_index_repo` | Trigger a full re-index | ~50 |
|
|
66
|
+
| `cs_get_context` | Symbol definition + immediate connections | ~300–800 |
|
|
67
|
+
| `cs_blast_radius` | All callers + dependents up to N hops | ~500–2,000 |
|
|
68
|
+
| `cs_search_symbols` | Full-text search across indexed symbols | ~200–600 |
|
|
69
|
+
| `cs_index_status` | Index health, file count, last-updated | ~100 |
|
|
70
|
+
|
|
71
|
+
Pass the `session_id` from your first `cs_get_context` call to every subsequent call to enable
|
|
72
|
+
deduplication.
|
|
73
|
+
|
|
74
|
+
## Supported languages
|
|
75
|
+
|
|
76
|
+
- **TypeScript / JavaScript / TSX** (v0.1)
|
|
77
|
+
- **Python** (v0.1)
|
|
78
|
+
- Go, Rust, Java — planned (see [roadmap](#roadmap))
|
|
79
|
+
|
|
80
|
+
Adding a language = add a grammar package + a `grammars/<lang>/tags.scm` query + a fixture. See
|
|
81
|
+
[CONTRIBUTING.md](./CONTRIBUTING.md).
|
|
82
|
+
|
|
83
|
+
## How it works
|
|
84
|
+
|
|
85
|
+
```text
|
|
86
|
+
Your codebase ──chokidar──▶ Parser (Tree-sitter) ──▶ SQLite graph (.sliver/index.db)
|
|
87
|
+
│
|
|
88
|
+
MCP server (stdio) ◀──────────────────┘
|
|
89
|
+
│ session ledger (.sliver/sessions.db)
|
|
90
|
+
▼
|
|
91
|
+
Claude Code / Cursor / Cline
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
- **Parser**: Tree-sitter extracts symbols + imports per file.
|
|
95
|
+
- **Graph engine**: stores symbol→symbol edges; bidirectional BFS (`blastRadius`) for blast radius
|
|
96
|
+
with cycle detection.
|
|
97
|
+
- **Session manager**: per-session ledger computes deltas so already-sent context is skipped.
|
|
98
|
+
- **MCP server**: exposes the five tools over stdio.
|
|
99
|
+
|
|
100
|
+
## Token counting
|
|
101
|
+
|
|
102
|
+
Counts use [`gpt-tokenizer`](https://www.npmjs.com/package/gpt-tokenizer) (`cl100k_base`) and are
|
|
103
|
+
labeled **~approximate** — close enough for budget guidance, not billing.
|
|
104
|
+
|
|
105
|
+
## Development
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
npm install
|
|
109
|
+
npm test # unit + integration tests
|
|
110
|
+
npm run test:bench # indexing benchmarks
|
|
111
|
+
npm run build # tsc → dist/
|
|
112
|
+
npm run lint # eslint
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Requires Node ≥ 20.
|
|
116
|
+
|
|
117
|
+
## Roadmap
|
|
118
|
+
|
|
119
|
+
- **v0.1** ✅ TS/JS + Python, SQLite graph, session ledger, 5 tools, CLI, watcher
|
|
120
|
+
- **v0.2** — incremental indexing polish, Cursor integration, CI benchmarks
|
|
121
|
+
- **v0.3** — Go + Rust, monorepo workspace resolution, language-plugin docs
|
|
122
|
+
- **v0.4** — PreToolUse hook, Java, published token-reduction benchmarks
|
|
123
|
+
- **v0.5** — Streamable HTTP transport, DuckDB backend for 50k-file repos, PageRank ranking
|
|
124
|
+
- **v1.0** — frozen API, optional native (napi-rs) engine, SCIP/LSP precision backend
|
|
125
|
+
|
|
126
|
+
See [`contextsliver-spec.md`](./contextsliver-spec.md) for the full specification.
|
|
127
|
+
|
|
128
|
+
## License
|
|
129
|
+
|
|
130
|
+
MIT © Muneeb Ur Rehman
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// ContextSliver CLI entry point. This is what `npx contextsliver <command>` runs.
|
|
3
|
+
//
|
|
4
|
+
// Commands:
|
|
5
|
+
// init Set up the project: create .sliver/, append .gitignore, write .mcp.json +
|
|
6
|
+
// CLAUDE.md, run the initial index.
|
|
7
|
+
// start Run the MCP server (stdio) + file watcher. The agent connects to this.
|
|
8
|
+
// reindex Force a full re-index.
|
|
9
|
+
//
|
|
10
|
+
// Logging uses console.error (stderr) directly for user-facing CLI messages, and the log()
|
|
11
|
+
// helper for server-internal diagnostics. Neither touches stdout except the MCP transport.
|
|
12
|
+
import { Command } from 'commander';
|
|
13
|
+
import { join, resolve } from 'node:path';
|
|
14
|
+
import { mkdirSync, existsSync, readFileSync, writeFileSync, appendFileSync, } from 'node:fs';
|
|
15
|
+
import { fileURLToPath } from 'node:url';
|
|
16
|
+
import { startMCPServer } from './mcp/server.js';
|
|
17
|
+
import { GraphStore } from './graph/store.js';
|
|
18
|
+
import { indexRepository } from './parser/index.js';
|
|
19
|
+
import { log } from './utils/logger.js';
|
|
20
|
+
const VERSION = '0.1.0';
|
|
21
|
+
const program = new Command();
|
|
22
|
+
program
|
|
23
|
+
.name('contextsliver')
|
|
24
|
+
.description('Universal context-management MCP server for AI coding agents')
|
|
25
|
+
.version(VERSION);
|
|
26
|
+
// ── init ──────────────────────────────────────────────────────────────────────
|
|
27
|
+
program
|
|
28
|
+
.command('init')
|
|
29
|
+
.description('Initialize ContextSliver for the current project')
|
|
30
|
+
.option('--root <path>', 'Project root directory', process.cwd())
|
|
31
|
+
.option('--no-index', 'Skip the initial index (index later with `reindex`)')
|
|
32
|
+
.action(async (opts) => {
|
|
33
|
+
const root = resolve(opts.root);
|
|
34
|
+
console.error(`Initializing ContextSliver in ${root}`);
|
|
35
|
+
// 1. .sliver/
|
|
36
|
+
mkdirSync(join(root, '.sliver'), { recursive: true });
|
|
37
|
+
// 2. .gitignore
|
|
38
|
+
addToGitignore(root);
|
|
39
|
+
// 3. .mcp.json
|
|
40
|
+
writeMcpConfig(root);
|
|
41
|
+
// 4. CLAUDE.md
|
|
42
|
+
writeClaudeMd(root);
|
|
43
|
+
// 5. Initial index
|
|
44
|
+
if (opts.index) {
|
|
45
|
+
console.error('Indexing project (this may take a few seconds for large repos)...');
|
|
46
|
+
const dbPath = join(root, '.sliver', 'index.db');
|
|
47
|
+
// Use better-sqlite3 directly to avoid spinning up the MCP server.
|
|
48
|
+
const Database = (await import('better-sqlite3')).default;
|
|
49
|
+
const db = new Database(dbPath);
|
|
50
|
+
const store = new GraphStore(db);
|
|
51
|
+
const result = indexRepository(store, root, { force: true });
|
|
52
|
+
console.error(`✓ Indexed ${result.filesIndexed} file(s), ${result.symbols} symbols, ${result.edges} edges`);
|
|
53
|
+
db.close();
|
|
54
|
+
}
|
|
55
|
+
console.error('\n✓ ContextSliver initialized.');
|
|
56
|
+
console.error(' Next: restart Claude Code / Cursor to pick up the MCP server, then run:');
|
|
57
|
+
console.error(' npx contextsliver start');
|
|
58
|
+
});
|
|
59
|
+
// ── start ────────────────────────────────────────────────────────────────────
|
|
60
|
+
program
|
|
61
|
+
.command('start')
|
|
62
|
+
.description('Start the ContextSliver MCP server and file watcher')
|
|
63
|
+
.option('--root <path>', 'Project root directory', process.cwd())
|
|
64
|
+
.option('--no-watch', 'Disable the file watcher')
|
|
65
|
+
.action(async (opts) => {
|
|
66
|
+
const root = resolve(opts.root);
|
|
67
|
+
log(`Starting ContextSliver MCP server in ${root}`);
|
|
68
|
+
await startMCPServer({ projectRoot: root, watch: opts.watch });
|
|
69
|
+
});
|
|
70
|
+
// ── reindex ──────────────────────────────────────────────────────────────────
|
|
71
|
+
program
|
|
72
|
+
.command('reindex')
|
|
73
|
+
.description('Force a full re-index of the project')
|
|
74
|
+
.option('--root <path>', 'Project root directory', process.cwd())
|
|
75
|
+
.option('--force', 'Re-parse every file even if its hash is unchanged', true)
|
|
76
|
+
.action(async (opts) => {
|
|
77
|
+
const root = resolve(opts.root);
|
|
78
|
+
mkdirSync(join(root, '.sliver'), { recursive: true });
|
|
79
|
+
const dbPath = join(root, '.sliver', 'index.db');
|
|
80
|
+
const Database = (await import('better-sqlite3')).default;
|
|
81
|
+
const db = new Database(dbPath);
|
|
82
|
+
const store = new GraphStore(db);
|
|
83
|
+
const result = indexRepository(store, root, { force: opts.force });
|
|
84
|
+
console.error(`✓ Re-indexed: ${result.filesIndexed} file(s) indexed, ${result.filesSkipped} skipped, ` +
|
|
85
|
+
`${result.symbols} symbols, ${result.edges} edges in ${result.durationMs}ms`);
|
|
86
|
+
db.close();
|
|
87
|
+
});
|
|
88
|
+
program.parse();
|
|
89
|
+
// ── init helpers ─────────────────────────────────────────────────────────────
|
|
90
|
+
function addToGitignore(root) {
|
|
91
|
+
const gitignorePath = join(root, '.gitignore');
|
|
92
|
+
const entry = '\n# ContextSliver index\n.sliver/\n';
|
|
93
|
+
if (existsSync(gitignorePath)) {
|
|
94
|
+
const content = readFileSync(gitignorePath, 'utf-8');
|
|
95
|
+
if (!content.includes('.sliver/')) {
|
|
96
|
+
appendFileSync(gitignorePath, entry);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
writeFileSync(gitignorePath, entry.trimStart());
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
function writeMcpConfig(root) {
|
|
104
|
+
const configPath = join(root, '.mcp.json');
|
|
105
|
+
if (existsSync(configPath)) {
|
|
106
|
+
log('Skipped .mcp.json (already exists)');
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
const config = {
|
|
110
|
+
mcpServers: {
|
|
111
|
+
contextsliver: {
|
|
112
|
+
command: 'npx',
|
|
113
|
+
args: ['contextsliver', 'start', '--root', root],
|
|
114
|
+
env: {},
|
|
115
|
+
},
|
|
116
|
+
},
|
|
117
|
+
};
|
|
118
|
+
writeFileSync(configPath, JSON.stringify(config, null, 2) + '\n');
|
|
119
|
+
log('Created .mcp.json');
|
|
120
|
+
}
|
|
121
|
+
function writeClaudeMd(root) {
|
|
122
|
+
const claudeMdPath = join(root, 'CLAUDE.md');
|
|
123
|
+
if (existsSync(claudeMdPath)) {
|
|
124
|
+
log('Skipped CLAUDE.md (already exists)');
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
const template = readTemplate('CLAUDE.md');
|
|
128
|
+
writeFileSync(claudeMdPath, template);
|
|
129
|
+
log('Created CLAUDE.md');
|
|
130
|
+
}
|
|
131
|
+
/** Read a file from templates/, resolving whether we're running from src/ or dist/. */
|
|
132
|
+
function readTemplate(name) {
|
|
133
|
+
const here = fileURLToPath(import.meta.url);
|
|
134
|
+
const dir = here.slice(0, here.lastIndexOf('/'));
|
|
135
|
+
// src/cli.ts → ../templates ; dist/cli.js → ../templates
|
|
136
|
+
const candidates = [
|
|
137
|
+
join(dir, '..', 'templates', name),
|
|
138
|
+
join(dir, '..', '..', 'templates', name),
|
|
139
|
+
join(process.cwd(), 'templates', name),
|
|
140
|
+
];
|
|
141
|
+
for (const candidate of candidates) {
|
|
142
|
+
if (existsSync(candidate))
|
|
143
|
+
return readFileSync(candidate, 'utf-8');
|
|
144
|
+
}
|
|
145
|
+
// Fallback: an inline minimal template so init never fails just because the file is missing.
|
|
146
|
+
return [
|
|
147
|
+
'# ContextSliver — Code Navigation Rules',
|
|
148
|
+
'',
|
|
149
|
+
'This project has ContextSliver installed. Before reading files or running grep/find,',
|
|
150
|
+
'use the cs_* MCP tools (cs_get_context, cs_blast_radius, cs_search_symbols) to get just',
|
|
151
|
+
'the connected subgraph. Pass the session_id from your first cs_get_context call to every',
|
|
152
|
+
'subsequent call to skip context you already have.',
|
|
153
|
+
'',
|
|
154
|
+
].join('\n');
|
|
155
|
+
}
|
|
156
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { SymbolRow } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Rank symbols by importance. v0.1 stub: returns the input unchanged.
|
|
4
|
+
*
|
|
5
|
+
* TODO (v0.5): implement PageRank-style scoring over the symbol graph. Until then the
|
|
6
|
+
* traversal order (BFS, nearest-first) is a reasonable default.
|
|
7
|
+
*/
|
|
8
|
+
export declare function rankSymbols(symbols: SymbolRow[]): SymbolRow[];
|
|
9
|
+
//# sourceMappingURL=rank.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rank.d.ts","sourceRoot":"","sources":["../../src/graph/rank.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,SAAS,EAAE,GAAG,SAAS,EAAE,CAE7D"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rank symbols by importance. v0.1 stub: returns the input unchanged.
|
|
3
|
+
*
|
|
4
|
+
* TODO (v0.5): implement PageRank-style scoring over the symbol graph. Until then the
|
|
5
|
+
* traversal order (BFS, nearest-first) is a reasonable default.
|
|
6
|
+
*/
|
|
7
|
+
export function rankSymbols(symbols) {
|
|
8
|
+
return symbols;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=rank.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rank.js","sourceRoot":"","sources":["../../src/graph/rank.ts"],"names":[],"mappings":"AAQA;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CAAC,OAAoB;IAC9C,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare const SCHEMA_SQL = "\n PRAGMA journal_mode = WAL;\n PRAGMA synchronous = NORMAL;\n PRAGMA foreign_keys = ON;\n\n -- One row per indexed file\n CREATE TABLE IF NOT EXISTS files (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n path TEXT NOT NULL UNIQUE, -- relative to project root, posix-style\n content_hash TEXT NOT NULL, -- SHA-256 of file content\n indexed_at INTEGER NOT NULL, -- unix timestamp (ms)\n language TEXT NOT NULL -- 'typescript' | 'python' | ...\n );\n\n -- One row per extracted symbol (function, class, interface, variable, type)\n CREATE TABLE IF NOT EXISTS symbols (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n file_id INTEGER NOT NULL REFERENCES files(id) ON DELETE CASCADE,\n name TEXT NOT NULL, -- e.g. 'AuthService'\n kind TEXT NOT NULL, -- 'function' | 'class' | 'interface' | 'variable' | 'type'\n line_start INTEGER NOT NULL,\n line_end INTEGER NOT NULL,\n signature TEXT, -- condensed definition (name + params), not full body\n package TEXT -- monorepo: owning package name (v0.3)\n );\n\n CREATE INDEX IF NOT EXISTS idx_symbols_name ON symbols(name);\n CREATE INDEX IF NOT EXISTS idx_symbols_file_id ON symbols(file_id);\n CREATE INDEX IF NOT EXISTS idx_symbols_package ON symbols(package);\n\n -- Directed edges: symbol A references symbol B\n CREATE TABLE IF NOT EXISTS edges (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n from_id INTEGER NOT NULL REFERENCES symbols(id) ON DELETE CASCADE,\n to_id INTEGER NOT NULL REFERENCES symbols(id) ON DELETE CASCADE,\n kind TEXT NOT NULL, -- 'calls' | 'imports' | 'extends' | 'implements' | 'uses'\n UNIQUE(from_id, to_id, kind)\n );\n\n CREATE INDEX IF NOT EXISTS idx_edges_from ON edges(from_id);\n CREATE INDEX IF NOT EXISTS idx_edges_to ON edges(to_id);\n\n -- Session ledger: what was already sent in each agent session\n CREATE TABLE IF NOT EXISTS sessions (\n id TEXT PRIMARY KEY, -- UUID\n created_at INTEGER NOT NULL,\n project_root TEXT NOT NULL\n );\n\n CREATE TABLE IF NOT EXISTS ledger_entries (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,\n symbol_id INTEGER NOT NULL REFERENCES symbols(id) ON DELETE CASCADE,\n content_hash TEXT NOT NULL, -- hash of what was sent at the time\n sent_at INTEGER NOT NULL,\n UNIQUE(session_id, symbol_id)\n );\n\n CREATE INDEX IF NOT EXISTS idx_ledger_session ON ledger_entries(session_id);\n";
|
|
2
|
+
/** Languages currently supported by the index. Matches parser/languages/registry.ts. */
|
|
3
|
+
export declare const SCHEMA_VERSION = 1;
|
|
4
|
+
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/graph/schema.ts"],"names":[],"mappings":"AAYA,eAAO,MAAM,UAAU,6pFA2DtB,CAAC;AAEF,wFAAwF;AACxF,eAAO,MAAM,cAAc,IAAI,CAAC"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
// SQLite schema for the ContextSliver index.
|
|
2
|
+
// Run once on init via `db.exec(SCHEMA_SQL)` — fully idempotent (IF NOT EXISTS).
|
|
3
|
+
//
|
|
4
|
+
// All four tables live in a single .sliver/index.db file:
|
|
5
|
+
// files — one row per indexed source file
|
|
6
|
+
// symbols — one row per extracted symbol (function/class/interface/...)
|
|
7
|
+
// edges — directed symbol→symbol relationships (calls/imports/extends/...)
|
|
8
|
+
// sessions + ledger_entries — per-session record of what context was already sent
|
|
9
|
+
//
|
|
10
|
+
// See contextsliver-spec.md §6 for the design rationale (SQLite + recursive CTEs,
|
|
11
|
+
// WAL mode for concurrent watcher/server access).
|
|
12
|
+
export const SCHEMA_SQL = `
|
|
13
|
+
PRAGMA journal_mode = WAL;
|
|
14
|
+
PRAGMA synchronous = NORMAL;
|
|
15
|
+
PRAGMA foreign_keys = ON;
|
|
16
|
+
|
|
17
|
+
-- One row per indexed file
|
|
18
|
+
CREATE TABLE IF NOT EXISTS files (
|
|
19
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
20
|
+
path TEXT NOT NULL UNIQUE, -- relative to project root, posix-style
|
|
21
|
+
content_hash TEXT NOT NULL, -- SHA-256 of file content
|
|
22
|
+
indexed_at INTEGER NOT NULL, -- unix timestamp (ms)
|
|
23
|
+
language TEXT NOT NULL -- 'typescript' | 'python' | ...
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
-- One row per extracted symbol (function, class, interface, variable, type)
|
|
27
|
+
CREATE TABLE IF NOT EXISTS symbols (
|
|
28
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
29
|
+
file_id INTEGER NOT NULL REFERENCES files(id) ON DELETE CASCADE,
|
|
30
|
+
name TEXT NOT NULL, -- e.g. 'AuthService'
|
|
31
|
+
kind TEXT NOT NULL, -- 'function' | 'class' | 'interface' | 'variable' | 'type'
|
|
32
|
+
line_start INTEGER NOT NULL,
|
|
33
|
+
line_end INTEGER NOT NULL,
|
|
34
|
+
signature TEXT, -- condensed definition (name + params), not full body
|
|
35
|
+
package TEXT -- monorepo: owning package name (v0.3)
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
CREATE INDEX IF NOT EXISTS idx_symbols_name ON symbols(name);
|
|
39
|
+
CREATE INDEX IF NOT EXISTS idx_symbols_file_id ON symbols(file_id);
|
|
40
|
+
CREATE INDEX IF NOT EXISTS idx_symbols_package ON symbols(package);
|
|
41
|
+
|
|
42
|
+
-- Directed edges: symbol A references symbol B
|
|
43
|
+
CREATE TABLE IF NOT EXISTS edges (
|
|
44
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
45
|
+
from_id INTEGER NOT NULL REFERENCES symbols(id) ON DELETE CASCADE,
|
|
46
|
+
to_id INTEGER NOT NULL REFERENCES symbols(id) ON DELETE CASCADE,
|
|
47
|
+
kind TEXT NOT NULL, -- 'calls' | 'imports' | 'extends' | 'implements' | 'uses'
|
|
48
|
+
UNIQUE(from_id, to_id, kind)
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
CREATE INDEX IF NOT EXISTS idx_edges_from ON edges(from_id);
|
|
52
|
+
CREATE INDEX IF NOT EXISTS idx_edges_to ON edges(to_id);
|
|
53
|
+
|
|
54
|
+
-- Session ledger: what was already sent in each agent session
|
|
55
|
+
CREATE TABLE IF NOT EXISTS sessions (
|
|
56
|
+
id TEXT PRIMARY KEY, -- UUID
|
|
57
|
+
created_at INTEGER NOT NULL,
|
|
58
|
+
project_root TEXT NOT NULL
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
CREATE TABLE IF NOT EXISTS ledger_entries (
|
|
62
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
63
|
+
session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
|
|
64
|
+
symbol_id INTEGER NOT NULL REFERENCES symbols(id) ON DELETE CASCADE,
|
|
65
|
+
content_hash TEXT NOT NULL, -- hash of what was sent at the time
|
|
66
|
+
sent_at INTEGER NOT NULL,
|
|
67
|
+
UNIQUE(session_id, symbol_id)
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
CREATE INDEX IF NOT EXISTS idx_ledger_session ON ledger_entries(session_id);
|
|
71
|
+
`;
|
|
72
|
+
/** Languages currently supported by the index. Matches parser/languages/registry.ts. */
|
|
73
|
+
export const SCHEMA_VERSION = 1;
|
|
74
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/graph/schema.ts"],"names":[],"mappings":"AAAA,6CAA6C;AAC7C,iFAAiF;AACjF,EAAE;AACF,0DAA0D;AAC1D,qDAAqD;AACrD,iFAAiF;AACjF,sFAAsF;AACtF,oFAAoF;AACpF,EAAE;AACF,kFAAkF;AAClF,kDAAkD;AAElD,MAAM,CAAC,MAAM,UAAU,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2DzB,CAAC;AAEF,wFAAwF;AACxF,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type Database from 'better-sqlite3';
|
|
2
|
+
import type { SymbolRow, EdgeKind, FileRow } from './types.js';
|
|
3
|
+
export declare class GraphStore {
|
|
4
|
+
private db;
|
|
5
|
+
constructor(db: Database.Database);
|
|
6
|
+
/** Insert or replace a file row. Returns the file id. */
|
|
7
|
+
upsertFile(path: string, contentHash: string, language: string): number;
|
|
8
|
+
getFileId(path: string): number | undefined;
|
|
9
|
+
getFile(path: string): FileRow | undefined;
|
|
10
|
+
/** Delete a file and cascade-delete its symbols (and their edges via ON DELETE CASCADE). */
|
|
11
|
+
deleteFile(path: string): void;
|
|
12
|
+
/** All indexed files. Used for full re-index accounting. */
|
|
13
|
+
countFiles(): number;
|
|
14
|
+
/** Hash of a file's content as stored at last index, or undefined if not indexed. */
|
|
15
|
+
getFileHash(path: string): string | undefined;
|
|
16
|
+
/** Insert a symbol for a file. Returns the new symbol id. */
|
|
17
|
+
insertSymbol(sym: {
|
|
18
|
+
file_id: number;
|
|
19
|
+
name: string;
|
|
20
|
+
kind: string;
|
|
21
|
+
line_start: number;
|
|
22
|
+
line_end: number;
|
|
23
|
+
signature: string | null;
|
|
24
|
+
package: string | null;
|
|
25
|
+
}): number;
|
|
26
|
+
/** Remove all symbols belonging to a file (edges cascade). Used before re-inserting. */
|
|
27
|
+
deleteFileSymbols(fileId: number): void;
|
|
28
|
+
/** Find a symbol by exact name (first match). Returns the enriched SymbolRow. */
|
|
29
|
+
findSymbolByName(name: string): SymbolRow | undefined;
|
|
30
|
+
/** All symbols matching a name (names are not globally unique). */
|
|
31
|
+
findSymbolsByName(name: string): SymbolRow[];
|
|
32
|
+
/** Full-row symbol by id (joined with file path). */
|
|
33
|
+
getSymbol(id: number): SymbolRow | undefined;
|
|
34
|
+
/** FTS-lite substring search across symbol name + file path. Used by cs_search_symbols. */
|
|
35
|
+
searchSymbols(query: string, limit: number): SymbolRow[];
|
|
36
|
+
/** Look up a symbol by name within a specific file (for import resolution). */
|
|
37
|
+
findSymbolInFile(fileId: number, name: string): SymbolRow | undefined;
|
|
38
|
+
/** Insert an edge (UNIQUE constraint dedupes on from/to/kind). Ignores if exists. */
|
|
39
|
+
insertEdge(fromId: number, toId: number, kind: EdgeKind): void;
|
|
40
|
+
/** Symbols this symbol points to (forward edges), any kind. */
|
|
41
|
+
getDependencies(symbolId: number): SymbolRow[];
|
|
42
|
+
/** Symbols that point to this one (reverse edges), any kind. */
|
|
43
|
+
getCallers(symbolId: number): SymbolRow[];
|
|
44
|
+
/** Run a function inside a DB transaction (batches writes). */
|
|
45
|
+
transaction<T>(fn: () => T): T;
|
|
46
|
+
/** Expose the raw db for traversal/manager modules that need their own prepared statements. */
|
|
47
|
+
get raw(): Database.Database;
|
|
48
|
+
/** Index health stats for cs_index_status. */
|
|
49
|
+
stats(): {
|
|
50
|
+
files: number;
|
|
51
|
+
symbols: number;
|
|
52
|
+
edges: number;
|
|
53
|
+
lastIndexedAt: number | null;
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/graph/store.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAE3C,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE/D,qBAAa,UAAU;IACrB,OAAO,CAAC,EAAE,CAAoB;gBAElB,EAAE,EAAE,QAAQ,CAAC,QAAQ;IAOjC,yDAAyD;IACzD,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM;IAkBvE,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAO3C,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS;IAM1C,4FAA4F;IAC5F,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAI9B,4DAA4D;IAC5D,UAAU,IAAI,MAAM;IAKpB,qFAAqF;IACrF,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAS7C,6DAA6D;IAC7D,YAAY,CAAC,GAAG,EAAE;QAChB,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,UAAU,EAAE,MAAM,CAAC;QACnB,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;QACzB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;KACxB,GAAG,MAAM;IAUV,wFAAwF;IACxF,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAIvC,iFAAiF;IACjF,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS;IAYrD,mEAAmE;IACnE,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,EAAE;IAW5C,qDAAqD;IACrD,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS;IAW5C,2FAA2F;IAC3F,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE;IAgBxD,+EAA+E;IAC/E,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS;IAcrE,qFAAqF;IACrF,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG,IAAI;IAQ9D,+DAA+D;IAC/D,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAAE;IAW9C,gEAAgE;IAChE,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAAE;IAazC,+DAA+D;IAC/D,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC;IAI9B,+FAA+F;IAC/F,IAAI,GAAG,IAAI,QAAQ,CAAC,QAAQ,CAE3B;IAED,8CAA8C;IAC9C,KAAK,IAAI;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE;CAYzF"}
|