basemind-opencode 0.0.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/README.md ADDED
@@ -0,0 +1,45 @@
1
+ # basemind-opencode
2
+
3
+ OpenCode plugin for [basemind](https://github.com/Goldziher/basemind) — a
4
+ tree-sitter code-map + git context MCP server.
5
+
6
+ ## Install
7
+
8
+ Add to your `opencode.json` (global or project-level):
9
+
10
+ ```json
11
+ {
12
+ "plugin": ["basemind-opencode@latest"]
13
+ }
14
+ ```
15
+
16
+ Restart OpenCode. The plugin registers the basemind MCP server and the bundled
17
+ skills directory.
18
+
19
+ You also need the `basemind` binary on your `PATH`:
20
+
21
+ ```bash
22
+ npm install -g basemind # or: pip install basemind / cargo install basemind
23
+ ```
24
+
25
+ Then scan your repo once before starting OpenCode:
26
+
27
+ ```bash
28
+ cd /path/to/your/repo
29
+ basemind scan
30
+ ```
31
+
32
+ ## What this registers
33
+
34
+ - **MCP server** named `basemind` running `basemind serve` over stdio. Exposes
35
+ the full code-map and git toolset — `outline`, `search_symbols`,
36
+ `find_references`, `find_callers`, `recent_changes`, `blame_symbol`, etc.
37
+ - **Skills directory** with two pre-authored skills (`basemind`,
38
+ `basemind-stats`) that document how to drive the MCP toolset.
39
+
40
+ See the [root README](https://github.com/Goldziher/basemind#readme) for the
41
+ full MCP tool table, architecture notes, and per-language coverage.
42
+
43
+ ## License
44
+
45
+ MIT
package/basemind.js ADDED
@@ -0,0 +1,51 @@
1
+ /**
2
+ * basemind plugin for OpenCode.ai
3
+ *
4
+ * Registers the basemind MCP server (`basemind serve`) and the skills
5
+ * directory shipped with the repo. OpenCode discovers the plugin via the
6
+ * `plugin` array in `opencode.json`; the function exported here is called
7
+ * once at startup with the live client + directory and returns a config
8
+ * hook that mutates OpenCode's resolved config in place.
9
+ *
10
+ * Exported as both the default and a named export so OpenCode picks it up
11
+ * regardless of which convention its plugin loader resolves first.
12
+ */
13
+
14
+ import fs from "fs";
15
+ import path from "path";
16
+ import { fileURLToPath } from "url";
17
+
18
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
19
+
20
+ // Resolve the skills directory across both install modes:
21
+ // - npm install: skills/ sits next to basemind.js inside
22
+ // node_modules/basemind-opencode/ (the prepack hook copies it in).
23
+ // - git+URL / monorepo dev: skills/ lives at the repo root, one level above
24
+ // opencode-plugin/.
25
+ // Whichever exists wins; this keeps both install paths working without
26
+ // duplicating the dev tree.
27
+ const bundledSkillsDir = path.join(__dirname, "skills");
28
+ const repoSkillsDir = path.join(__dirname, "..", "skills");
29
+ const skillsDir = fs.existsSync(bundledSkillsDir) ? bundledSkillsDir : repoSkillsDir;
30
+
31
+ const hooks = () => ({
32
+ config: async (config) => {
33
+ config.skills = config.skills || {};
34
+ config.skills.paths = config.skills.paths || [];
35
+ if (!config.skills.paths.includes(skillsDir)) {
36
+ config.skills.paths.push(skillsDir);
37
+ }
38
+
39
+ config.mcp = config.mcp || {};
40
+ if (!config.mcp.basemind) {
41
+ config.mcp.basemind = {
42
+ type: "local",
43
+ command: ["basemind", "serve"],
44
+ enabled: true,
45
+ };
46
+ }
47
+ },
48
+ });
49
+
50
+ export const BasemindPlugin = async () => hooks();
51
+ export default async () => hooks();
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "basemind-opencode",
3
+ "version": "0.0.1",
4
+ "description": "Tree-sitter code-map + git context MCP server. Use for navigating large or unfamiliar codebases: outline files, find references/callers, search symbols, walk recent history, blame and diff at the symbol level.",
5
+ "type": "module",
6
+ "main": "basemind.js",
7
+ "keywords": [
8
+ "mcp",
9
+ "tree-sitter",
10
+ "code-map",
11
+ "scanner",
12
+ "indexer"
13
+ ],
14
+ "author": {
15
+ "name": "Na'aman Hirschfeld",
16
+ "email": "nhirschfeld@gmail.com"
17
+ },
18
+ "license": "MIT",
19
+ "repository": {
20
+ "type": "git",
21
+ "url": "https://github.com/Goldziher/basemind.git",
22
+ "directory": "opencode-plugin"
23
+ },
24
+ "homepage": "https://github.com/Goldziher/basemind#opencode",
25
+ "bugs": {
26
+ "url": "https://github.com/Goldziher/basemind/issues"
27
+ },
28
+ "scripts": {
29
+ "prepack": "rm -rf skills && cp -R ../skills skills",
30
+ "postpack": "rm -rf skills"
31
+ },
32
+ "files": [
33
+ "basemind.js",
34
+ "skills/",
35
+ "README.md"
36
+ ],
37
+ "engines": {
38
+ "node": ">=18"
39
+ }
40
+ }
@@ -0,0 +1,135 @@
1
+ ---
2
+ name: basemind
3
+ description: >-
4
+ Navigate large or unfamiliar codebases via the basemind MCP server — outlines,
5
+ symbol search, reference/caller lookups, commit history, blame, and diffs without
6
+ reading source files. Reach for it whenever the user asks "where is X defined",
7
+ "what calls Y", "what changed recently in Z", or whenever you're about to grep
8
+ or open many files to find structural information.
9
+ ---
10
+
11
+ # basemind — code-map MCP server
12
+
13
+ basemind is a tree-sitter-backed code map plus git context, served over MCP. It
14
+ pre-indexes a repository into a Fjall inverted index so structural and historical
15
+ questions resolve in milliseconds — without you reading whole files.
16
+
17
+ ## When to reach for it (instead of `grep` / `read_file`)
18
+
19
+ Use basemind for:
20
+
21
+ - **Locating a symbol**: "where is `Foo` defined?", "find the constructor for `Bar`", "show me every type ending in `Service`".
22
+ - **Following call graphs**: "what calls `process_file`?", "who depends on this module?".
23
+ - **Mapping a file's shape** before reading it: which symbols, in what order, with what signatures.
24
+ - **Walking recent history**: "what changed in this file in the last 20 commits?", "when did this symbol last change?".
25
+ - **Blame and ownership**: "who last touched this function?", "what commit introduced this line?".
26
+ - **Diffing across revisions**: "what symbols did this branch add?", "show the hunks for `foo.rs` between HEAD~5 and HEAD".
27
+
28
+ If you are about to open more than two or three files just to learn structure, stop
29
+ and use basemind first. The tools return paths + line numbers; you only `read_file`
30
+ once you know exactly which span you need.
31
+
32
+ ## Tool routing (copy this into your mental model)
33
+
34
+ | Question | Tool |
35
+ |---|---|
36
+ | "Where is X defined?" | `search_symbols` (substring match, optional `kind` filter) |
37
+ | "What's the shape of file F?" | `outline` (add `l2: true` for calls + docs) |
38
+ | "What calls X?" (any name) | `find_references` |
39
+ | "What calls this specific definition?" | `find_callers` (path + name + optional kind) |
40
+ | "Trace the call graph from a function?" | `call_graph` (BFS up or down, bounded by `max_depth` / `max_nodes`) |
41
+ | "What implements / extends / inherits from X?" | `find_implementations` (Rust, Python, TS/TSX, JS) |
42
+ | "What imports module M?" | `dependents` |
43
+ | "What files are indexed?" | `list_files` (filter by `language` or `path_contains`) |
44
+ | "What changed recently?" | `recent_changes`, `commits_touching`, `find_commits_by_path` |
45
+ | "When did symbol X last change?" | `symbol_history` |
46
+ | "Who wrote this line / symbol?" | `blame_file`, `blame_symbol` |
47
+ | "Where's the churn?" | `hot_files` |
48
+ | "What's dirty in the working tree?" | `working_tree_status` |
49
+ | "What's HEAD / branch?" | `repo_info` |
50
+ | "Show diff between revs for file F" | `diff_file`, `diff_outline` |
51
+ | "What's indexed?" | `status` |
52
+ | "Semantic search over PDFs / Office docs in the repo?" | `search_documents` (requires `--features documents`) |
53
+ | "Recall something the agent stored earlier?" | `memory_get` exact, `memory_list` prefix, `memory_search` KNN |
54
+ | "Remember this for future sessions?" | `memory_put` (delete with `memory_delete`) |
55
+ | "Refresh the index after editing code?" | `rescan` — no MCP disconnect needed; optional `paths` arg |
56
+ | "Fetch next page of results?" | Pass `next_cursor` from prior response as `cursor` |
57
+ | "Pull this URL into RAG?" | `web_scrape` (requires `--features crawl`) — single page, robots-aware |
58
+ | "Ingest a docs site section?" | `web_crawl` — link-following from a seed URL |
59
+ | "What URLs exist on this site?" | `web_map` — sitemap + link discovery, no bodies fetched |
60
+ | "How much has basemind helped today?" | `telemetry_summary` — per-tool histogram + estimated tokens saved |
61
+
62
+ ## Setup (one-time per repo)
63
+
64
+ basemind needs an index at `.basemind/` before it can answer queries. From the repo root:
65
+
66
+ ```sh
67
+ basemind scan
68
+ ```
69
+
70
+ This walks the tree, parses with tree-sitter, and writes a content-addressed blob
71
+ store + Fjall inverted index under `.basemind/`. A few seconds for small repos,
72
+ ~22 s for an ~80k-file TypeScript monorepo.
73
+
74
+ The MCP server is launched by the host (`basemind serve` — wired up in
75
+ `.claude-plugin/plugin.json` for you). You do not start it manually.
76
+
77
+ Re-run `basemind scan` after large changes, or run `basemind watch` to keep the index fresh on file save.
78
+
79
+ If a tool returns "no indexed files", that means `basemind scan` hasn't been run in this repo yet.
80
+
81
+ ## Examples
82
+
83
+ ### Locating a symbol
84
+
85
+ ```text
86
+ search_symbols { needle: "MapCache" }
87
+ → src/mcp/mod.rs:79:1 MapCache (struct)
88
+ src/mcp/mod.rs:88:1 MapCache (impl)
89
+ ```
90
+
91
+ Now you know exactly where to read.
92
+
93
+ ### Following references
94
+
95
+ ```text
96
+ find_references { name: "process_file" }
97
+ → src/scanner.rs:142:9 process_file
98
+ src/scanner.rs:201:13 process_file
99
+ ...
100
+ ```
101
+
102
+ No need to grep — the index already knows.
103
+
104
+ ### Outline a file before reading
105
+
106
+ ```text
107
+ outline { path: "src/mcp/tools.rs" }
108
+ → 21 #[tool] outline (function)
109
+ 112 #[tool] search_symbols (function)
110
+ ...
111
+ ```
112
+
113
+ A 1000-line file becomes a 30-line table of contents.
114
+
115
+ ## Notes
116
+
117
+ - All paths are repository-relative with forward-slash separators.
118
+ - Lists are capped (`limit`, default 100, max 1000). Index scanners use
119
+ `scan_cap = limit * 8` to bound work on common names.
120
+ - Matching is substring on names — `find_references("bar")` matches `Foo::bar()`
121
+ and `bar()` alike. There is no scope resolution; cross-check with `outline` if
122
+ disambiguation matters.
123
+ - Git tools require `basemind serve` to be running inside a git repository. Outside a git repo they return a clear error.
124
+ - Intelligence tools (`search_documents`, `memory_*`) require basemind to be built with
125
+ `--features full` (or the individual `documents` / `memory` flags). Without them the
126
+ tools dispatch but return an MCP error.
127
+ Memory is scoped by the normalised `origin` remote URL (`git@github.com:Foo/bar.git` and
128
+ `https://github.com/Foo/bar/` collapse to the same scope key) — clones of the same repo
129
+ share memory; unrelated repos do not see each other's entries.
130
+ - Web ingestion tools (`web_scrape`, `web_crawl`, `web_map`) require `--features crawl`.
131
+ When that feature is off they are NOT registered on the server at all — agents will simply
132
+ not see them in the tool list. Crawled pages land in the `documents` LanceDB table under
133
+ scope `web:<host>`; `search_documents { query: ..., scope: "web:<host>" }` retrieves them.
134
+ robots.txt is honoured by default; only `[crawl].respect_robots_txt = false` in
135
+ `.basemind/basemind.toml` (config-file-only) disables it.
@@ -0,0 +1,51 @@
1
+ ---
2
+ name: basemind-stats
3
+ description: >-
4
+ Show a quick dashboard of basemind activity in this session: how many code-map
5
+ tool calls have run, the per-tool histogram, and the estimated tokens saved vs
6
+ a hypothetical grep+Read baseline. Use when the user asks "what has basemind
7
+ done?", "how much is basemind helping?", "show me basemind stats", or invokes
8
+ `/basemind-stats` directly.
9
+ ---
10
+
11
+ # basemind-stats — on-demand usage dashboard
12
+
13
+ Call the `telemetry_summary` MCP tool and render the result as a markdown report.
14
+
15
+ ## What to do
16
+
17
+ 1. Call `telemetry_summary` with `{ "window": "today" }` (the default). If the
18
+ user asks for a specific range, map it to one of `"today"`, `"1h"`, `"24h"`,
19
+ `"all"`.
20
+ 2. Render a markdown block in this shape:
21
+
22
+ ```text
23
+ ## basemind activity (today)
24
+ - **N tool calls** ; top tools: outline (18), search_symbols (12), …
25
+ - **~K tokens saved** vs grep + Read baseline
26
+ - recent: outline (4ms, 312B), search_symbols (2ms, 180B), …
27
+ ```
28
+
29
+ 3. If `total_calls` is 0, say so plainly ("no basemind activity in the window yet").
30
+ Don't pretend to have data.
31
+ 4. **Always disclose the savings model.** Add one sentence at the end:
32
+
33
+ > Savings are heuristics. Tools with no realistic baseline (memory, document
34
+ > search, git wrappers) report 0 saved — see the `saved_baseline` column on
35
+ > each row.
36
+
37
+ The exact wording can vary; the principle (it's an estimate, here's why) cannot.
38
+
39
+ ## When the user asks "--explain"
40
+
41
+ If they invoke `/basemind-stats --explain` or ask how the savings number is
42
+ derived, include the per-baseline breakdown from the `per_baseline` field of the
43
+ response and call out which tools fall into which bucket. The estimator lives in
44
+ `src/mcp/savings.rs` if they want to read the code.
45
+
46
+ ## Don't
47
+
48
+ - Don't auto-display the dashboard at the start of every conversation. This skill
49
+ is strictly user-invoked.
50
+ - Don't pad missing data. If `recent` is empty, say so; don't invent example rows.
51
+ - Don't claim a token-savings number without the disclosure sentence.