@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.
- package/README.md +200 -0
- package/bin/logos.js +101 -0
- 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 & 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
|
+
}
|