@noeton/logos 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.
Files changed (3) hide show
  1. package/README.md +200 -0
  2. package/bin/logos.js +101 -0
  3. package/package.json +47 -0
package/README.md ADDED
@@ -0,0 +1,200 @@
1
+ <h1 align="center">Logos</h1>
2
+
3
+ <p align="center">
4
+ <strong>The memory you own.</strong><br>
5
+ Continuity for AI coding agents — checkpoint in one tool, resume in another.
6
+ </p>
7
+
8
+ <p align="center">
9
+ <a href="https://www.npmjs.com/package/@noeton/logos"><img alt="npm" src="https://img.shields.io/npm/v/@noeton/logos?style=flat-square&color=0b7285"></a>
10
+ <img alt="license" src="https://img.shields.io/badge/license-MIT-blue?style=flat-square">
11
+ <img alt="platforms" src="https://img.shields.io/badge/macOS%20%C2%B7%20Linux%20%C2%B7%20Windows-arm64%20%2B%20x64-555?style=flat-square">
12
+ <img alt="download" src="https://img.shields.io/badge/download-~5%20MB-555?style=flat-square">
13
+ </p>
14
+
15
+ ```
16
+ Claude Code ──▶ checkpoint ──▶ Logos ──▶ resume ──▶ Cursor
17
+ (your vault)
18
+ ```
19
+
20
+ Your agent finishes a session and everything it learned goes with it — the three
21
+ approaches it ruled out, the decision it made at 2am, the reason the obvious fix
22
+ does not work here. The next agent starts from nothing and tries the first dead
23
+ end again.
24
+
25
+ Logos is the layer that survives the session. It stores what happened as
26
+ **markdown on your disk**, and serves it back over MCP to whichever agent picks
27
+ up next.
28
+
29
+ ---
30
+
31
+ ## Install
32
+
33
+ ```bash
34
+ npx -y @noeton/logos setup
35
+ ```
36
+
37
+ That is the whole thing. No Go toolchain, no clone, no build — this package
38
+ carries a prebuilt binary for your platform, about 5 MB.
39
+
40
+ `setup` picks a vault (`~/brain` unless you say otherwise), runs the first index,
41
+ then **shows you which agents it would wire and asks before touching any of
42
+ them.** Decline everything and you still have a working install.
43
+
44
+ <details>
45
+ <summary><b>Wire a host by hand instead</b></summary>
46
+
47
+ No install at all — `npx` resolves the binary on demand:
48
+
49
+ ```json
50
+ {
51
+ "mcpServers": {
52
+ "logos": {
53
+ "command": "npx",
54
+ "args": ["-y", "@noeton/logos", "mcp", "serve"]
55
+ }
56
+ }
57
+ }
58
+ ```
59
+
60
+ That config is portable between machines, which an absolute binary path is not.
61
+ Add `"env": { "BRAIN_VAULT": "/path/to/vault" }` to point it somewhere other
62
+ than `~/brain`.
63
+
64
+ </details>
65
+
66
+ <details>
67
+ <summary><b>Claude Code users: prefer the plugin</b></summary>
68
+
69
+ ```
70
+ /plugin marketplace add Coder8124/logos
71
+ /plugin install logos@logos
72
+ ```
73
+
74
+ The plugin is more than the MCP server. It installs a **SessionStart hook** that
75
+ puts the last handoff in front of the model before it does anything — the
76
+ difference between continuity that works and continuity that works when the
77
+ model remembers to ask for it.
78
+
79
+ </details>
80
+
81
+ ---
82
+
83
+ ## What it actually does
84
+
85
+ ```console
86
+ $ logos checkpoint kestrel-one --agent claude \
87
+ --decided "aluminium frame, 6061" \
88
+ --failed "plastic frame — fails drop test at 1.2m" \
89
+ --next "quote the single-mic line"
90
+
91
+ $ logos resume kestrel-one # from Cursor. From Codex. From anywhere.
92
+ ```
93
+
94
+ The second agent gets the decisions, the dead ends, and the next step — and is
95
+ told, in the pack itself, that the dead ends are there so it does not pay for
96
+ them twice.
97
+
98
+ | | |
99
+ |---|---|
100
+ | **Negative knowledge** | Records what was *ruled out*, not just what is true. `before_you_try` answers "has this been tried?" before the agent proposes it. |
101
+ | **Structured handoff** | A checkpoint is decisions, failures, open questions and a next step — not a summary paragraph. |
102
+ | **Scope isolation** | Memory is scoped to the folder you are working in, derived from the directory — not from the agent remembering to say which project it is on. Another repository's facts do not surface unless you ask for them. |
103
+ | **Provenance** | Every fact carries where it came from, when, and how confident. |
104
+ | **Stale-plan suppression** | A next step that later work has overtaken is withdrawn, not repeated. |
105
+ | **Durability** | Delete the index, the cache, every derived artifact — the vault is markdown and nothing is lost. |
106
+
107
+ ---
108
+
109
+ ## It works with no AI runtime at all
110
+
111
+ Continuity — checkpoint, resume, dead ends, handoff — is markdown, SQL and
112
+ string matching. **No model on any path.** Retrieval falls back to lexical
113
+ search, which for code (identifiers, error strings, paths) is arguably the right
114
+ tool anyway.
115
+
116
+ Install a 274 MB embedding model later if you want semantic recall. Nothing
117
+ requires the 22 GB one.
118
+
119
+ | You code with | Extra download | You get |
120
+ |---|---|---|
121
+ | Claude Code / Cursor / Codex | **0 MB** | continuity + lexical search |
122
+ | …and want fuzzy recall | 274 MB | + semantic retrieval |
123
+
124
+ ---
125
+
126
+ ## One vault, one project per folder
127
+
128
+ Every host points at one vault, because that is what makes continuity work
129
+ across tools. Facts are still kept apart: the project is taken from the folder
130
+ the agent is working in, so two repositories open in two windows do not write
131
+ into each other's memory.
132
+
133
+ ```
134
+ ~/code/kestrel → project "kestrel"
135
+ ~/code/acme-api → project "acme-api" # cannot see kestrel's decisions
136
+ ```
137
+
138
+ Nothing has to be configured, and the agent does not have to remember to say
139
+ which project it is on — a rule a model can forget is not isolation. Override
140
+ with `BRAIN_PROJECT`, mark a fact `global` when it really does apply everywhere
141
+ (how you like replies written), and pass `all_projects` to search across all of
142
+ them when you actually want that.
143
+
144
+ ---
145
+
146
+ ## Local-first, meant literally
147
+
148
+ - Your memory is **markdown files in a directory you chose.** Open them, grep
149
+ them, commit them, delete them.
150
+ - `.brain/index.db` is a **cache.** Delete it and it rebuilds.
151
+ - Nothing is uploaded. There is no account, no server, no telemetry.
152
+ - If this project disappears tomorrow, **you keep a vault** that every text
153
+ editor on earth can read.
154
+
155
+ ---
156
+
157
+ ## Supported platforms
158
+
159
+ | | |
160
+ |---|---|
161
+ | macOS | arm64 · x64 |
162
+ | Linux | x64 · arm64 (glibc and musl — pure Go, `CGO_ENABLED=0`) |
163
+ | Windows | x64 |
164
+
165
+ The platform packages are `optionalDependencies` gated on `os` and `cpu`, so npm
166
+ fetches **one** of them, not five: about **5 MB over the wire, 11 MB on disk**.
167
+ There is **no `postinstall` script** — the binaries ship as real package
168
+ contents, so `--ignore-scripts` and offline installs both work.
169
+
170
+ ---
171
+
172
+ ## Common commands
173
+
174
+ ```sh
175
+ logos setup # pick a vault, wire your agents (asks first)
176
+ logos doctor # what is working, what is not, what it cannot check
177
+ logos doctor --integration # prove a host round-trips through to the vault
178
+ logos resume <project> # the handoff, as a human can read it
179
+ logos tried "<approach>" # has this already been ruled out?
180
+ logos mcp serve # the MCP server, over stdio
181
+ ```
182
+
183
+ `brain` is installed as an alias for `logos` — same command, either spelling.
184
+
185
+ ---
186
+
187
+ ## Two names
188
+
189
+ **Logos** is the product — the repository, this package, and the MCP server your
190
+ host talks to. **brain** is the development name and stays one internally: the Go
191
+ module `github.com/Coder8124/brain`, the `brain` command, `BRAIN_VAULT`, and
192
+ `.brain/`. Both spellings work everywhere you meet them.
193
+
194
+ ---
195
+
196
+ <p align="center">
197
+ <a href="https://github.com/Coder8124/logos">Source &amp; full documentation</a> ·
198
+ <a href="https://github.com/Coder8124/logos/blob/main/docs/continuity-benchmark.md">Benchmark</a> ·
199
+ MIT
200
+ </p>
package/bin/logos.js ADDED
@@ -0,0 +1,101 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+
4
+ // The launcher. It finds the prebuilt binary for this platform and becomes it.
5
+ //
6
+ // Why a wrapper at all: npm cannot ship one package containing five platforms'
7
+ // binaries without every user downloading all five. So the real binaries live in
8
+ // per-platform packages gated by `os`/`cpu`, npm installs only the matching one,
9
+ // and this file resolves it.
10
+ //
11
+ // On the two names: the published product is Logos, and the executable inside
12
+ // the platform packages is still called `brain` — that is the development name,
13
+ // what `scripts/release.sh` builds, and what the binary calls itself in its own
14
+ // help. This file is the seam between the two, which is why the package name and
15
+ // the file on disk differ. Keep it that way rather than renaming the Go tree.
16
+ //
17
+ // The important constraint is that `logos mcp serve` speaks newline-delimited
18
+ // JSON-RPC over stdin/stdout. Anything this wrapper writes to stdout corrupts
19
+ // that stream, and any buffering between the host and the binary risks stalling
20
+ // it. So stdio is inherited — the child gets the real file descriptors and this
21
+ // process is not in the data path at all — and every diagnostic goes to stderr.
22
+
23
+ const { spawnSync } = require("child_process");
24
+
25
+ // npm's platform vocabulary, which is Node's, not Go's.
26
+ const PLATFORMS = {
27
+ "darwin arm64": "@noeton/logos-darwin-arm64",
28
+ "darwin x64": "@noeton/logos-darwin-x64",
29
+ "linux x64": "@noeton/logos-linux-x64",
30
+ "linux arm64": "@noeton/logos-linux-arm64",
31
+ "win32 x64": "@noeton/logos-win32-x64",
32
+ };
33
+
34
+ function binaryPath() {
35
+ const key = `${process.platform} ${process.arch}`;
36
+ const pkg = PLATFORMS[key];
37
+ if (!pkg) {
38
+ fail(
39
+ `no prebuilt binary for ${key}.`,
40
+ "",
41
+ "Supported: " + Object.keys(PLATFORMS).join(", ") + ".",
42
+ "Build from source instead:",
43
+ " go install github.com/Coder8124/brain/cmd/brain@latest"
44
+ );
45
+ }
46
+
47
+ // The executable keeps its development name inside the archive; see above.
48
+ const exe = process.platform === "win32" ? "brain.exe" : "brain";
49
+ try {
50
+ // Resolve through the package's own entry so npm/pnpm/yarn layouts, symlinks
51
+ // and nested node_modules all work without guessing at directory structure.
52
+ return require.resolve(`${pkg}/bin/${exe}`);
53
+ } catch (e) {
54
+ fail(
55
+ `installed, but the binary package for ${key} is missing.`,
56
+ "",
57
+ `Expected: ${pkg}`,
58
+ "",
59
+ "This usually means optional dependencies were skipped. Try:",
60
+ " npm install --include=optional",
61
+ "",
62
+ "If you installed with --no-optional or a lockfile from another platform,",
63
+ "reinstall without it. Failing that, install directly:",
64
+ ` npm install ${pkg}`
65
+ );
66
+ }
67
+ }
68
+
69
+ function fail(...lines) {
70
+ for (const line of lines) console.error(line ? `logos: ${line}` : "");
71
+ process.exit(1);
72
+ }
73
+
74
+ // spawnSync rather than spawn: this process has nothing to do while the binary
75
+ // runs, and inheriting stdio means the JSON-RPC stream flows through the real
76
+ // descriptors with no Node layer in between.
77
+ const result = spawnSync(binaryPath(), process.argv.slice(2), {
78
+ stdio: "inherit",
79
+ windowsHide: true,
80
+ });
81
+
82
+ if (result.error) {
83
+ if (result.error.code === "EACCES") {
84
+ fail(
85
+ "the binary is not executable.",
86
+ "",
87
+ "Reinstall to restore its permissions:",
88
+ " npm install --force @noeton/logos"
89
+ );
90
+ }
91
+ fail(`could not start the binary: ${result.error.message}`);
92
+ }
93
+
94
+ // A child killed by a signal has a null status. Reproduce the signal rather
95
+ // than inventing an exit code, so `logos mcp serve` under a host that kills its
96
+ // servers reports what actually happened.
97
+ if (result.signal) {
98
+ process.kill(process.pid, result.signal);
99
+ process.exit(1);
100
+ }
101
+ process.exit(result.status === null ? 1 : result.status);
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "@noeton/logos",
3
+ "version": "0.1.1",
4
+ "description": "Logos — cross-tool memory and continuity for AI coding agents, over MCP. Your vault is markdown on your own disk.",
5
+ "keywords": [
6
+ "logos",
7
+ "mcp",
8
+ "model-context-protocol",
9
+ "memory",
10
+ "continuity",
11
+ "local-first",
12
+ "claude",
13
+ "cursor",
14
+ "codex"
15
+ ],
16
+ "homepage": "https://github.com/Coder8124/logos",
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "git+https://github.com/Coder8124/logos.git",
20
+ "directory": "npm"
21
+ },
22
+ "license": "MIT",
23
+ "bin": {
24
+ "logos": "bin/logos.js",
25
+ "brain": "bin/logos.js"
26
+ },
27
+ "files": [
28
+ "bin/logos.js",
29
+ "README.md"
30
+ ],
31
+ "engines": {
32
+ "node": ">=16"
33
+ },
34
+ "optionalDependencies": {
35
+ "@noeton/logos-darwin-arm64": "0.1.1",
36
+ "@noeton/logos-darwin-x64": "0.1.1",
37
+ "@noeton/logos-linux-x64": "0.1.1",
38
+ "@noeton/logos-linux-arm64": "0.1.1",
39
+ "@noeton/logos-win32-x64": "0.1.1"
40
+ },
41
+ "scripts": {
42
+ "build": "node scripts/build.js",
43
+ "test": "node scripts/test.js",
44
+ "release:dry": "node scripts/build.js && node scripts/test.js && node scripts/publish.js --dry-run",
45
+ "release": "node scripts/build.js && node scripts/test.js && node scripts/publish.js"
46
+ }
47
+ }