eminiar 0.0.0-stage → 0.5.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.
@@ -0,0 +1,12 @@
1
+ {
2
+ "name": "eminiar",
3
+ "owner": { "name": "Ryan Dick" },
4
+ "description": "Local-first context, memory and knowledge graph plugin for Claude Code.",
5
+ "plugins": [
6
+ {
7
+ "name": "eminiar",
8
+ "source": "./",
9
+ "description": "Local-first context, memory and knowledge graph for Claude Code."
10
+ }
11
+ ]
12
+ }
@@ -0,0 +1,28 @@
1
+ {
2
+ "name": "eminiar",
3
+ "displayName": "Eminiar",
4
+ "version": "0.5.1",
5
+ "description": "Local-first context, memory and knowledge graph for Claude Code: sandboxed execution, FTS5 + vector search, session continuity, code graph.",
6
+ "author": {
7
+ "name": "Ryan Dick"
8
+ },
9
+ "license": "MIT",
10
+ "keywords": [
11
+ "context",
12
+ "memory",
13
+ "search",
14
+ "sandbox",
15
+ "knowledge-graph"
16
+ ],
17
+ "hooks": "./hooks/hooks.json",
18
+ "mcpServers": {
19
+ "eminiar": {
20
+ "command": "${CLAUDE_PLUGIN_ROOT}/bin/em-server",
21
+ "args": [],
22
+ "env": {
23
+ "EMINIAR_PLUGIN_ROOT": "${CLAUDE_PLUGIN_ROOT}",
24
+ "EMINIAR_PLUGIN_DATA": "${CLAUDE_PLUGIN_DATA}"
25
+ }
26
+ }
27
+ }
28
+ }
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Ryan Dick
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 CHANGED
@@ -1,3 +1,207 @@
1
- # Temporary Holding Version
1
+ <div align="center">
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ # eminiar
4
+
5
+ **A memory, a code map and a clean context window for Claude Code — all on your machine.**
6
+
7
+ *Pronounced ee-MIN-ee-ar*
8
+
9
+ [![License: MIT](https://img.shields.io/badge/license-MIT-3b82f6.svg)](#license)
10
+ [![Node](https://img.shields.io/badge/node-%E2%89%A522.12-64748b.svg)](https://nodejs.org)
11
+ [![Claude Code plugin](https://img.shields.io/badge/Claude%20Code-plugin-3b82f6.svg)](https://docs.claude.com/en/docs/claude-code)
12
+ [![Local-first](https://img.shields.io/badge/local--first-no%20cloud-64748b.svg)](docs/how-it-works.md#privacy-and-data)
13
+
14
+ [Quick start](#quick-start) · [Features](#what-you-get) · [How it works](docs/how-it-works.md) · [Tools](docs/tools.md) · [Docs](docs/README.md)
15
+
16
+ <br/>
17
+
18
+ <picture>
19
+ <source media="(prefers-color-scheme: dark)" srcset="docs/images/dashboard-explore-dark.webp">
20
+ <img alt="The eminiar dashboard: source explorer with file impact, dependents and linked memories" src="docs/images/dashboard-explore-light.webp" width="900">
21
+ </picture>
22
+
23
+ <sub>The local dashboard: source, file impact and the memories linked to the file.</sub>
24
+
25
+ </div>
26
+
27
+ ---
28
+
29
+ ## The problem
30
+
31
+ Claude Code is very capable, but three things slow it down on a real project:
32
+
33
+ 1. **The context window fills with noise.** One `git log`, test run or API response can use
34
+ thousands of tokens. Claude needs only a few lines of it.
35
+ 2. **Every session starts from zero.** Decisions, constraints and fixed bugs are lost after a
36
+ `/compact` or a new session. Claude asks again, or repeats a mistake.
37
+ 3. **Claude reads code without a map.** It does not know which files are fragile, which files
38
+ import a function, or why a line changed.
39
+
40
+ ## The solution
41
+
42
+ eminiar is a Claude Code plugin. It adds an MCP server with 22 `em_*` tools and a set of hooks.
43
+ Everything runs locally in one SQLite database per project.
44
+
45
+ | | Without eminiar | With eminiar |
46
+ |---|---|---|
47
+ | **Large output** | The full output goes into context | Output is indexed. Only the sections that match your `intent` come back |
48
+ | **Memory** | Lost at `/compact` or a new session | Markdown memories in your repo, given back to Claude when they are relevant |
49
+ | **Code structure** | `grep` and full-file reads | A knowledge graph of files, symbols, calls, routes and hotspots |
50
+ | **Git history** | Raw `git log` / `git blame` | Classified commits, with each fix traced back to the commit that caused it |
51
+ | **Library docs** | Web search on each question | A local, searchable index of the docs your project uses |
52
+ | **Getting knowledge** | Claude must remember to ask | Hooks push the relevant knowledge to Claude **automatically** |
53
+
54
+ ## What you get
55
+
56
+ ### 🧪 Sandboxed execution — keep raw output out of context
57
+
58
+ `em_execute`, `em_batch_execute` and `em_execute_file` run shell, JavaScript and TypeScript, plus
59
+ Python, Ruby, Go, PHP, Perl, R, Elixir, Rust and C# when they are installed. Output over 5 KB is
60
+ indexed. Claude gets back only the sections that match its `intent`. Snippets obey your Claude
61
+ Code `permissions.deny` rules.
62
+
63
+ ### 🔎 Hybrid search — keyword and meaning together
64
+
65
+ SQLite FTS5 (porter + trigram, BM25, typo correction) is fused with local ONNX embeddings
66
+ (`bge-small` through `sqlite-vec`). Search covers command output, files, fetched pages,
67
+ documentation, memories, git messages and session history. It never waits for the model to
68
+ download.
69
+
70
+ ### 🧠 Memory that comes back by itself
71
+
72
+ `em_remember` writes plain markdown files to `.eminiar/memories/`. You can read them, edit them
73
+ and commit them. Decisions have an ADR-style status (`proposed`, `accepted`, `superseded`). Hooks
74
+ attach matching memories to your prompts, to file reads and edits, to failed commands and to
75
+ subagent briefs. **Claude does not have to remember to look.**
76
+
77
+ ### 🕸️ Code knowledge graph — a map before an edit
78
+
79
+ tree-sitter parses TypeScript, JavaScript, Python and Go into files, symbols, imports, calls,
80
+ references, inheritance and HTTP routes (Express, Fastify, Koa, hapi, Hono, Moleculer, Next.js,
81
+ Python decorator routes and Go routers). eminiar
82
+ adds fan-in, complexity, churn, a hotspot score, module clusters, import cycles and git co-change
83
+ coupling. Ask *"what breaks if I change this?"* with `em_graph_impact`.
84
+
85
+ ### 📜 Git history, read for Claude
86
+
87
+ `em_history` classifies every commit (feat, fix, refactor, perf …). It traces each fix back to
88
+ the commit that wrote the broken lines. Files get a risk score with reasons. Before Claude edits
89
+ a bug-prone file, it sees the record.
90
+
91
+ ### 📚 Documentation knowledge base
92
+
93
+ `em_docs` finds your local docs (READMEs, ADRs, OpenAPI, Postman) and the libraries, services
94
+ and third-party APIs your code calls. It indexes their documentation locally. OpenAPI specs are
95
+ split into one section per endpoint, so a lookup returns the exact operation.
96
+
97
+ ### 📊 Local dashboard
98
+
99
+ `eminiar ui` opens a local web app with token savings, a source explorer with impact analysis, a
100
+ graph "galaxy", an architecture map, a history explorer, a memory editor and a docs manager.
101
+
102
+ | | |
103
+ |:---:|:---:|
104
+ | [<img alt="Galaxy: the knowledge graph around a file" src="docs/images/dashboard-galaxy-dark.webp" width="430">](docs/dashboard.md#galaxy) | [<img alt="History: commits classified by kind, with the branch graph" src="docs/images/dashboard-history-dark.webp" width="430">](docs/dashboard.md#history) |
105
+ | **Galaxy:** the knowledge graph | **History:** classified commits and fix tracing |
106
+ | [<img alt="Memory: a decision with its linked files" src="docs/images/dashboard-memory-dark.webp" width="430">](docs/dashboard.md#memory) | [<img alt="Hotspots: fan-in, churn and complexity per file" src="docs/images/dashboard-hotspots-dark.webp" width="430">](docs/dashboard.md#architecture) |
107
+ | **Memory:** decisions linked to code | **Hotspots:** where change is risky |
108
+
109
+ ## What Claude sees
110
+
111
+ Hooks add short notes to the conversation at the right moment. These examples are real output:
112
+
113
+ ```text
114
+ eminiar recall — project memories and indexed docs that match this request:
115
+ - memory decision/proactive-recall-in-hooks [decision]: Project knowledge is pushed to Claude by hooks …
116
+
117
+ eminiar history: src/cli.ts is bug-prone (1/6 commits were fixes; 1 earlier change later needed
118
+ fixing; last fix 3f8c697 Fix MCP registration, make enforce routing and dev upgrades safe).
119
+
120
+ eminiar graph: src/cli.ts is imported by 6 files; em_graph_impact {node:"file:src/cli.ts"} lists
121
+ them before you change an exported signature.
122
+ ```
123
+
124
+ Each note appears once per context window. After a `/compact`, notes come back when they are
125
+ relevant again.
126
+
127
+ ## Quick start
128
+
129
+ **Requirements:** Node.js 22.12 or later, and Claude Code.
130
+
131
+ ```sh
132
+ npx eminiar install # registers the plugin, installs a stable copy, downloads the model
133
+ npx eminiar doctor # checks every part
134
+ ```
135
+
136
+ Restart Claude Code. Then, in your project:
137
+
138
+ ```text
139
+ /em-onboard # writes onboarding memories and builds the docs knowledge base
140
+ ```
141
+
142
+ That is all. Use Claude Code as usual. To see how much context eminiar saves, run `/em-stats` or
143
+ open the dashboard with `eminiar ui`.
144
+
145
+ **For a team:** run `npx eminiar install --team` once and commit `eminiar.config.json` and
146
+ `.eminiar/`. Teammates then run `npx eminiar install`. See
147
+ [Getting started](docs/getting-started.md#team-setup).
148
+
149
+ ## How it works
150
+
151
+ ```mermaid
152
+ flowchart LR
153
+ CC["Claude Code"]
154
+ subgraph eminiar ["eminiar (local)"]
155
+ H["Hooks<br/>recall · routing · capture"]
156
+ S["MCP server<br/>22 em_* tools"]
157
+ SB["Sandbox<br/>shell · JS · TS · Python …"]
158
+ DB[("SQLite per project<br/>FTS5 · vectors · graph")]
159
+ M["Memory files<br/>.eminiar/memories/*.md"]
160
+ end
161
+ CC -->|prompts, tool calls| H
162
+ H -->|notes: memories, history, graph| CC
163
+ CC -->|em_* calls| S
164
+ S -->|small, relevant answers| CC
165
+ S --> SB
166
+ S <--> DB
167
+ H <--> DB
168
+ M <--> DB
169
+ ```
170
+
171
+ - **Hooks** run on session start, prompts, tool calls and failures. They capture session events,
172
+ route noisy commands to the sandbox, and attach relevant knowledge.
173
+ - **The MCP server** provides the `em_*` tools and keeps the index and graph up to date.
174
+ - **Storage** is one SQLite file per project under `~/.eminiar/`. Memories also live as markdown
175
+ in your repo.
176
+
177
+ Read more in [How it works](docs/how-it-works.md).
178
+
179
+ ## Documentation
180
+
181
+ | Guide | Contents |
182
+ |---|---|
183
+ | [Getting started](docs/getting-started.md) | Install, team setup, first steps, upgrade and uninstall |
184
+ | [How it works](docs/how-it-works.md) | Architecture, routing modes, session continuity, privacy |
185
+ | [Tools reference](docs/tools.md) | Every `em_*` tool and slash command |
186
+ | [Memory and recall](docs/memory-and-recall.md) | Memory files, decisions, automatic recall |
187
+ | [Knowledge graph and history](docs/knowledge-graph.md) | Graph, symbols, impact analysis, git history |
188
+ | [Documentation knowledge base](docs/documentation-kb.md) | Discover, index and look up docs |
189
+ | [Dashboard](docs/dashboard.md) | The `eminiar ui` web app |
190
+ | [Configuration](docs/configuration.md) | Every config key with its default |
191
+ | [CLI](docs/cli.md) | The `eminiar` command |
192
+ | [Troubleshooting](docs/troubleshooting.md) | Common problems and fixes |
193
+ | [Development](docs/development.md) | Build, test, benchmark and project layout |
194
+
195
+ ## Privacy
196
+
197
+ Your code, tool output and memories stay on your machine. eminiar uses the network only to:
198
+
199
+ - download the embedding model once (you can skip this with `install --no-model`);
200
+ - fetch web pages and documentation that you or Claude ask it to index;
201
+ - look up package metadata in the npm, PyPI and Go registries when it adds documentation.
202
+
203
+ The dashboard listens on `127.0.0.1` only.
204
+
205
+ ## License
206
+
207
+ MIT © Ryan Dick
@@ -0,0 +1,51 @@
1
+ #!/bin/sh
2
+ # Sourced by bin/em-server, bin/em-hook and bin/eminiar (never executed directly).
3
+ # Sets NODE (the Node binary to run) and RUN (the package root whose dist/ to run).
4
+ #
5
+ # Claude Code may launch a plugin from the copy it keeps under
6
+ # ~/.claude/plugins/cache/<marketplace>/<plugin>/<version>. That copy carries dist/
7
+ # but no node_modules/, so dist/*.js cannot import better-sqlite3 and friends. The
8
+ # installer pins the stable copy (~/.eminiar/plugin/node_modules/eminiar, with its
9
+ # dependencies beside it) in $EMINIAR_HOME/root-path; when the directory this shim
10
+ # lives in cannot resolve its dependencies, we run the pinned copy's dist/ instead.
11
+ EM_HOME="${EMINIAR_HOME:-$HOME/.eminiar}"
12
+ # EM_SELF: the shim's real path when it was reached through a symlink (bin/eminiar).
13
+ DIR="$(cd "$(dirname "${EM_SELF:-$0}")/.." && pwd)"
14
+
15
+ # V8 compile cache (Node >= 22.1): bytecode for dist/*.js is reused across launches,
16
+ # trimming server and hook start-up. Older Node ignores the variable.
17
+ if [ -z "$NODE_COMPILE_CACHE" ]; then
18
+ NODE_COMPILE_CACHE="$EM_HOME/compile-cache"
19
+ export NODE_COMPILE_CACHE
20
+ fi
21
+
22
+ # Node: the binary pinned at install time (so nvm/volta PATHs never matter), else PATH.
23
+ NODE=""
24
+ if [ -f "$EM_HOME/node-path" ]; then
25
+ NODE="$(cat "$EM_HOME/node-path" 2>/dev/null)"
26
+ fi
27
+ if [ ! -x "$NODE" ]; then
28
+ NODE="$(command -v node 2>/dev/null)"
29
+ fi
30
+
31
+ # A package root is runnable when its dependencies resolve: node_modules/ inside it
32
+ # (dev checkout, npm -g) or beside it (stable copy inside ~/.eminiar/plugin/node_modules).
33
+ em_runnable() {
34
+ [ -e "$1/node_modules/better-sqlite3/package.json" ] || [ -e "$1/../better-sqlite3/package.json" ]
35
+ }
36
+
37
+ RUN="$DIR"
38
+ if ! em_runnable "$DIR"; then
39
+ RUN=""
40
+ if [ -f "$EM_HOME/root-path" ]; then
41
+ ALT="$(cat "$EM_HOME/root-path" 2>/dev/null)"
42
+ if [ -n "$ALT" ] && [ -f "$ALT/dist/server.js" ] && em_runnable "$ALT"; then
43
+ RUN="$ALT"
44
+ # Point version/grammar lookups at the code that actually runs; keep the
45
+ # launch directory for diagnostics (em_doctor shows "launched from").
46
+ EMINIAR_PLUGIN_ROOT="$ALT"
47
+ EMINIAR_LAUNCH_ROOT="$DIR"
48
+ export EMINIAR_PLUGIN_ROOT EMINIAR_LAUNCH_ROOT
49
+ fi
50
+ fi
51
+ fi
package/bin/em-hook ADDED
@@ -0,0 +1,15 @@
1
+ #!/bin/sh
2
+ # Hook entry shim. Node and package-root resolution live in _resolve.sh.
3
+ # A hook must never block Claude: if nothing can run, print an empty JSON object.
4
+ . "$(dirname "$0")/_resolve.sh"
5
+ if [ ! -x "$NODE" ]; then
6
+ echo "eminiar hook: no node binary found (run: npx eminiar install)" >&2
7
+ echo '{}'
8
+ exit 0
9
+ fi
10
+ if [ -z "$RUN" ]; then
11
+ echo "eminiar hook: $DIR has no node_modules and no stable copy is pinned (run: npx eminiar install)" >&2
12
+ echo '{}'
13
+ exit 0
14
+ fi
15
+ exec "$NODE" "$RUN/dist/hook.js" "$@"
package/bin/em-server ADDED
@@ -0,0 +1,12 @@
1
+ #!/bin/sh
2
+ # MCP server shim (stdio). Node and package-root resolution live in _resolve.sh.
3
+ . "$(dirname "$0")/_resolve.sh"
4
+ if [ ! -x "$NODE" ]; then
5
+ echo "eminiar: no node binary found (run: npx eminiar install)" >&2
6
+ exit 1
7
+ fi
8
+ if [ -z "$RUN" ]; then
9
+ echo "eminiar: $DIR has no node_modules and no stable copy is pinned in $EM_HOME/root-path (run: npx eminiar install)" >&2
10
+ exit 1
11
+ fi
12
+ exec "$NODE" "$RUN/dist/server.js" "$@"
package/bin/eminiar ADDED
@@ -0,0 +1,22 @@
1
+ #!/bin/sh
2
+ # CLI shim. Node and package-root resolution live in _resolve.sh.
3
+ # npm links this file into node_modules/.bin (npx, npm -g) as a symlink; follow it so
4
+ # _resolve.sh and the package root are found next to the real file.
5
+ EM_SELF="$0"
6
+ while [ -L "$EM_SELF" ]; do
7
+ EM_LINK="$(readlink "$EM_SELF")"
8
+ case "$EM_LINK" in
9
+ /*) EM_SELF="$EM_LINK" ;;
10
+ *) EM_SELF="$(dirname "$EM_SELF")/$EM_LINK" ;;
11
+ esac
12
+ done
13
+ . "$(dirname "$EM_SELF")/_resolve.sh"
14
+ if [ ! -x "$NODE" ]; then
15
+ echo "eminiar: node >= 22.12 is required" >&2
16
+ exit 1
17
+ fi
18
+ if [ -z "$RUN" ]; then
19
+ echo "eminiar: $DIR has no node_modules and no stable copy is pinned in $EM_HOME/root-path (run: npx eminiar install)" >&2
20
+ exit 1
21
+ fi
22
+ exec "$NODE" "$RUN/dist/cli.js" "$@"