ctx-store 0.7.0__tar.gz
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.
- ctx_store-0.7.0/LICENSE +21 -0
- ctx_store-0.7.0/PKG-INFO +129 -0
- ctx_store-0.7.0/README.md +119 -0
- ctx_store-0.7.0/ctx_store.egg-info/PKG-INFO +129 -0
- ctx_store-0.7.0/ctx_store.egg-info/SOURCES.txt +48 -0
- ctx_store-0.7.0/ctx_store.egg-info/dependency_links.txt +1 -0
- ctx_store-0.7.0/ctx_store.egg-info/entry_points.txt +3 -0
- ctx_store-0.7.0/ctx_store.egg-info/top_level.txt +2 -0
- ctx_store-0.7.0/ctxserve/__init__.py +3 -0
- ctx_store-0.7.0/ctxserve/__main__.py +5 -0
- ctx_store-0.7.0/ctxserve/auth.py +235 -0
- ctx_store-0.7.0/ctxserve/server.py +294 -0
- ctx_store-0.7.0/ctxstore/VERSION +1 -0
- ctx_store-0.7.0/ctxstore/__init__.py +5 -0
- ctx_store-0.7.0/ctxstore/__main__.py +5 -0
- ctx_store-0.7.0/ctxstore/backend.py +273 -0
- ctx_store-0.7.0/ctxstore/bootstrap.py +168 -0
- ctx_store-0.7.0/ctxstore/cli.py +280 -0
- ctx_store-0.7.0/ctxstore/clock.py +10 -0
- ctx_store-0.7.0/ctxstore/config.py +58 -0
- ctx_store-0.7.0/ctxstore/contract.py +101 -0
- ctx_store-0.7.0/ctxstore/doctor.py +47 -0
- ctx_store-0.7.0/ctxstore/frontmatter.py +115 -0
- ctx_store-0.7.0/ctxstore/fs.py +479 -0
- ctx_store-0.7.0/ctxstore/interface.md +632 -0
- ctx_store-0.7.0/ctxstore/links.py +55 -0
- ctx_store-0.7.0/ctxstore/markdown.py +91 -0
- ctx_store-0.7.0/ctxstore/mcp.py +264 -0
- ctx_store-0.7.0/ctxstore/memory_tool.py +71 -0
- ctx_store-0.7.0/ctxstore/reads.py +308 -0
- ctx_store-0.7.0/ctxstore/search.py +234 -0
- ctx_store-0.7.0/ctxstore/secrets.py +20 -0
- ctx_store-0.7.0/ctxstore/sections.py +211 -0
- ctx_store-0.7.0/ctxstore/spec.py +45 -0
- ctx_store-0.7.0/ctxstore/store.py +401 -0
- ctx_store-0.7.0/ctxstore/upkeep.py +265 -0
- ctx_store-0.7.0/ctxstore/verbs.py +308 -0
- ctx_store-0.7.0/ctxstore/writes.py +194 -0
- ctx_store-0.7.0/pyproject.toml +26 -0
- ctx_store-0.7.0/setup.cfg +4 -0
- ctx_store-0.7.0/tests/test_backend.py +194 -0
- ctx_store-0.7.0/tests/test_contract.py +99 -0
- ctx_store-0.7.0/tests/test_doctor.py +193 -0
- ctx_store-0.7.0/tests/test_eval.py +20 -0
- ctx_store-0.7.0/tests/test_hygiene.py +74 -0
- ctx_store-0.7.0/tests/test_init.py +228 -0
- ctx_store-0.7.0/tests/test_reads.py +710 -0
- ctx_store-0.7.0/tests/test_serve.py +683 -0
- ctx_store-0.7.0/tests/test_store.py +591 -0
- ctx_store-0.7.0/tests/test_upkeep.py +555 -0
ctx_store-0.7.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 MdaaaaO
|
|
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.
|
ctx_store-0.7.0/PKG-INFO
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ctx-store
|
|
3
|
+
Version: 0.7.0
|
|
4
|
+
Summary: A markdown context store for coding agents: validated writes, budgeted reads, audit trail.
|
|
5
|
+
License: MIT
|
|
6
|
+
Requires-Python: >=3.10
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Dynamic: license-file
|
|
10
|
+
|
|
11
|
+
# ctx-store
|
|
12
|
+
|
|
13
|
+
`ctx` is a markdown context store for coding agents: one folder of `*.md` rows with YAML frontmatter as
|
|
14
|
+
the schema, a CLI with validated structured writes (`log`, `fm`, `new`, `move`), budgeted reads
|
|
15
|
+
(`brief`, `find --budget`, `resolve`, `get --section --tail`), a per-actor audit trail and a maintenance
|
|
16
|
+
pass (`init`, `validate`, `doctor`, `maintain`, `migrate`). The same core serves three front-ends: the CLI (Claude
|
|
17
|
+
Code hooks and skills call it), an Anthropic memory-tool handler (`view create str_replace insert delete
|
|
18
|
+
rename`) and an MCP server (stdio for Claude Desktop; HTTP with authentication for claude.ai, as a
|
|
19
|
+
separate package).
|
|
20
|
+
|
|
21
|
+
Production-grade by design: Python stdlib only (≥ 3.10), runs from a plain copy with no install, fixed
|
|
22
|
+
exit-code table, `--json` envelope (`"api": 1`), temp + rename writes under a lock, secret guard on every
|
|
23
|
+
payload, read-only store support, no writable state under the store for reads.
|
|
24
|
+
|
|
25
|
+
## Interface first
|
|
26
|
+
|
|
27
|
+
The interface is the contract: verbs, fixed errors and the doc model. Storage is a backend behind it.
|
|
28
|
+
Markdown files are the default backend, so a store stays a folder you can read and edit; the same calls
|
|
29
|
+
give the same answers on any other backend (`ctxstore/backend.py`, `ctx help backends`).
|
|
30
|
+
|
|
31
|
+
## Try it
|
|
32
|
+
|
|
33
|
+
```sh
|
|
34
|
+
git clone https://github.com/MdaaaaO/ctx-store && cd ctx-store
|
|
35
|
+
./ctx --version
|
|
36
|
+
./ctx doctor --store tests/fixtures/store-v1
|
|
37
|
+
./ctx help errors
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
No install step: `ctx` runs from a plain copy of the repo on Python ≥ 3.10. The interface (verbs, exit
|
|
41
|
+
codes, error strings, `--json` envelope, environment) is [`docs/interface.md`](docs/interface.md);
|
|
42
|
+
`ctx help` prints from the same file. Tests: `make ci`.
|
|
43
|
+
|
|
44
|
+
## Hooks
|
|
45
|
+
|
|
46
|
+
Every call a harness hook needs is one line. A write names its store; a read may find it by walking up.
|
|
47
|
+
|
|
48
|
+
| When | Call |
|
|
49
|
+
|---|---|
|
|
50
|
+
| Setup on a new machine, or a schema upgrade | `ctx init --store <path> --settings <file> --types <folder>` (add `--upgrade` for a new version: files edited since are kept) |
|
|
51
|
+
| After a change under the store | `ctx validate --changed` (add `--adopt` while writes still come from outside ctx) |
|
|
52
|
+
| Heartbeat | `ctx touch --session <id>` |
|
|
53
|
+
| Session start | `ctx brief --registry` |
|
|
54
|
+
| After a compaction | `ctx brief --session <id>` |
|
|
55
|
+
| A step landed | `ctx log <doc> "<what happened>"` |
|
|
56
|
+
| Session end, or on a timer | `ctx maintain` |
|
|
57
|
+
| CI, after a schema change | `ctx migrate --check` |
|
|
58
|
+
|
|
59
|
+
## Claude Desktop
|
|
60
|
+
|
|
61
|
+
```json
|
|
62
|
+
{"mcpServers": {"ctx": {"command": "/path/to/ctx-store/ctx", "args": ["mcp"],
|
|
63
|
+
"env": {"CTX_STORE": "/path/to/store", "CTX_ACTOR": "desktop"}}}}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
On Windows with the store and `ctx` inside WSL, Claude Desktop starts it through `wsl.exe`, and the
|
|
67
|
+
environment goes into the arguments:
|
|
68
|
+
|
|
69
|
+
```json
|
|
70
|
+
{"mcpServers": {"ctx": {"command": "wsl.exe",
|
|
71
|
+
"args": ["-e", "env", "CTX_STORE=/home/you/store", "CTX_ACTOR=desktop", "CTX_NO_WALK=1",
|
|
72
|
+
"/home/you/ctx-store/ctx", "mcp"]}}}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
| Install | `claude_desktop_config.json` is in |
|
|
76
|
+
|---|---|
|
|
77
|
+
| Windows, installer | `%APPDATA%\Claude\` |
|
|
78
|
+
| Windows, Microsoft Store | `%LOCALAPPDATA%\Packages\Claude_*\LocalCache\Roaming\Claude\` |
|
|
79
|
+
| macOS | `~/Library/Application Support/Claude/` |
|
|
80
|
+
|
|
81
|
+
Tested with the Microsoft Store install on Windows with WSL2: the tools are listed, and `brief`, `find`
|
|
82
|
+
and `log` work. The other two rows are where Claude Desktop documents its config; they were not tested
|
|
83
|
+
here.
|
|
84
|
+
|
|
85
|
+
Every built verb is a tool (`ctx_brief`, `ctx_find`, `ctx_log`, …). `ctx memory` takes the input of
|
|
86
|
+
Anthropic's memory tool on stdin.
|
|
87
|
+
|
|
88
|
+
## claude.ai
|
|
89
|
+
|
|
90
|
+
`ctx-serve` puts the same tools behind HTTP with authentication (OAuth for claude.ai, a bearer token for
|
|
91
|
+
Claude Code), for a store on your machine behind a tunnel: [`docs/connector.md`](docs/connector.md). It is
|
|
92
|
+
a separate package; the core has no network.
|
|
93
|
+
|
|
94
|
+
## Speed
|
|
95
|
+
|
|
96
|
+
Milliseconds per call as a caller sees it: a fresh process each time, interpreter start included
|
|
97
|
+
(about 40 ms of every number). Generated Markdown stores of 3.1 MB and 39.2 MB, 20 runs per call,
|
|
98
|
+
Python 3.14 on Linux under WSL2. The two stores were measured in separate runs on a machine that was
|
|
99
|
+
not idle: compare a row with the first row of its own column. `python3 bench/bench.py` reproduces it.
|
|
100
|
+
|
|
101
|
+
| Call | 225 docs p50 | p95 | 3 000 docs p50 | p95 |
|
|
102
|
+
|---|---:|---:|---:|---:|
|
|
103
|
+
| start of the interpreter (`--version`) | 35 | 38 | 34 | 37 |
|
|
104
|
+
| `brief <doc>` | 35 | 40 | 34 | 39 |
|
|
105
|
+
| `get <doc> --section --tail 5` | 35 | 37 | 35 | 36 |
|
|
106
|
+
| `view <doc>` | 34 | 35 | 35 | 39 |
|
|
107
|
+
| `brief --registry` | 42 | 44 | 127 | 140 |
|
|
108
|
+
| `brief --session <id>` | 42 | 50 | 127 | 134 |
|
|
109
|
+
| `resolve <key>` | 41 | 46 | 103 | 107 |
|
|
110
|
+
| `find <word in one doc>` | 44 | 45 | 155 | 163 |
|
|
111
|
+
| `find <common word>` | 69 | 77 | 173 | 199 |
|
|
112
|
+
| `find --tag` | 41 | 59 | 123 | 144 |
|
|
113
|
+
| `validate` | 54 | 60 | 295 | 309 |
|
|
114
|
+
| `validate --changed` | 49 | 55 | 184 | 194 |
|
|
115
|
+
|
|
116
|
+
**No search cache.** The rule was: a cache enters only above 3 000 docs, with `find` over 200 ms at
|
|
117
|
+
p95, or when a lookup needs ranked search a scan cannot give. At 3 000 docs every `find` stays under
|
|
118
|
+
200 ms. `find` matches terms and ranks its hits as part of the same scan (`ctx help find`), which
|
|
119
|
+
finds 17 of the 18 lookups in `bench/eval/` where the phrase match before it found 6; the one it
|
|
120
|
+
misses is a paraphrase, which an index of words would miss too. A task described in a sentence
|
|
121
|
+
or two finds its doc as well (7 of 7 in the eval). That is where the scan costs most: about 0.1 s for
|
|
122
|
+
25 words on 225 docs, about 0.9 s on 3 000. So the store has no index to build,
|
|
123
|
+
validate or lose. The question returns when a store passes 3 000 docs, or when lookups need
|
|
124
|
+
synonyms.
|
|
125
|
+
|
|
126
|
+
`validate --changed`, the call behind the after-write hook, stays under its 300 ms budget at 3 000 docs.
|
|
127
|
+
|
|
128
|
+
**Status:** P4: every verb except `row` is built; measured; no cache. Design and phasing:
|
|
129
|
+
[#1](https://github.com/MdaaaaO/ctx-store/issues/1). Licence: MIT.
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# ctx-store
|
|
2
|
+
|
|
3
|
+
`ctx` is a markdown context store for coding agents: one folder of `*.md` rows with YAML frontmatter as
|
|
4
|
+
the schema, a CLI with validated structured writes (`log`, `fm`, `new`, `move`), budgeted reads
|
|
5
|
+
(`brief`, `find --budget`, `resolve`, `get --section --tail`), a per-actor audit trail and a maintenance
|
|
6
|
+
pass (`init`, `validate`, `doctor`, `maintain`, `migrate`). The same core serves three front-ends: the CLI (Claude
|
|
7
|
+
Code hooks and skills call it), an Anthropic memory-tool handler (`view create str_replace insert delete
|
|
8
|
+
rename`) and an MCP server (stdio for Claude Desktop; HTTP with authentication for claude.ai, as a
|
|
9
|
+
separate package).
|
|
10
|
+
|
|
11
|
+
Production-grade by design: Python stdlib only (≥ 3.10), runs from a plain copy with no install, fixed
|
|
12
|
+
exit-code table, `--json` envelope (`"api": 1`), temp + rename writes under a lock, secret guard on every
|
|
13
|
+
payload, read-only store support, no writable state under the store for reads.
|
|
14
|
+
|
|
15
|
+
## Interface first
|
|
16
|
+
|
|
17
|
+
The interface is the contract: verbs, fixed errors and the doc model. Storage is a backend behind it.
|
|
18
|
+
Markdown files are the default backend, so a store stays a folder you can read and edit; the same calls
|
|
19
|
+
give the same answers on any other backend (`ctxstore/backend.py`, `ctx help backends`).
|
|
20
|
+
|
|
21
|
+
## Try it
|
|
22
|
+
|
|
23
|
+
```sh
|
|
24
|
+
git clone https://github.com/MdaaaaO/ctx-store && cd ctx-store
|
|
25
|
+
./ctx --version
|
|
26
|
+
./ctx doctor --store tests/fixtures/store-v1
|
|
27
|
+
./ctx help errors
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
No install step: `ctx` runs from a plain copy of the repo on Python ≥ 3.10. The interface (verbs, exit
|
|
31
|
+
codes, error strings, `--json` envelope, environment) is [`docs/interface.md`](docs/interface.md);
|
|
32
|
+
`ctx help` prints from the same file. Tests: `make ci`.
|
|
33
|
+
|
|
34
|
+
## Hooks
|
|
35
|
+
|
|
36
|
+
Every call a harness hook needs is one line. A write names its store; a read may find it by walking up.
|
|
37
|
+
|
|
38
|
+
| When | Call |
|
|
39
|
+
|---|---|
|
|
40
|
+
| Setup on a new machine, or a schema upgrade | `ctx init --store <path> --settings <file> --types <folder>` (add `--upgrade` for a new version: files edited since are kept) |
|
|
41
|
+
| After a change under the store | `ctx validate --changed` (add `--adopt` while writes still come from outside ctx) |
|
|
42
|
+
| Heartbeat | `ctx touch --session <id>` |
|
|
43
|
+
| Session start | `ctx brief --registry` |
|
|
44
|
+
| After a compaction | `ctx brief --session <id>` |
|
|
45
|
+
| A step landed | `ctx log <doc> "<what happened>"` |
|
|
46
|
+
| Session end, or on a timer | `ctx maintain` |
|
|
47
|
+
| CI, after a schema change | `ctx migrate --check` |
|
|
48
|
+
|
|
49
|
+
## Claude Desktop
|
|
50
|
+
|
|
51
|
+
```json
|
|
52
|
+
{"mcpServers": {"ctx": {"command": "/path/to/ctx-store/ctx", "args": ["mcp"],
|
|
53
|
+
"env": {"CTX_STORE": "/path/to/store", "CTX_ACTOR": "desktop"}}}}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
On Windows with the store and `ctx` inside WSL, Claude Desktop starts it through `wsl.exe`, and the
|
|
57
|
+
environment goes into the arguments:
|
|
58
|
+
|
|
59
|
+
```json
|
|
60
|
+
{"mcpServers": {"ctx": {"command": "wsl.exe",
|
|
61
|
+
"args": ["-e", "env", "CTX_STORE=/home/you/store", "CTX_ACTOR=desktop", "CTX_NO_WALK=1",
|
|
62
|
+
"/home/you/ctx-store/ctx", "mcp"]}}}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
| Install | `claude_desktop_config.json` is in |
|
|
66
|
+
|---|---|
|
|
67
|
+
| Windows, installer | `%APPDATA%\Claude\` |
|
|
68
|
+
| Windows, Microsoft Store | `%LOCALAPPDATA%\Packages\Claude_*\LocalCache\Roaming\Claude\` |
|
|
69
|
+
| macOS | `~/Library/Application Support/Claude/` |
|
|
70
|
+
|
|
71
|
+
Tested with the Microsoft Store install on Windows with WSL2: the tools are listed, and `brief`, `find`
|
|
72
|
+
and `log` work. The other two rows are where Claude Desktop documents its config; they were not tested
|
|
73
|
+
here.
|
|
74
|
+
|
|
75
|
+
Every built verb is a tool (`ctx_brief`, `ctx_find`, `ctx_log`, …). `ctx memory` takes the input of
|
|
76
|
+
Anthropic's memory tool on stdin.
|
|
77
|
+
|
|
78
|
+
## claude.ai
|
|
79
|
+
|
|
80
|
+
`ctx-serve` puts the same tools behind HTTP with authentication (OAuth for claude.ai, a bearer token for
|
|
81
|
+
Claude Code), for a store on your machine behind a tunnel: [`docs/connector.md`](docs/connector.md). It is
|
|
82
|
+
a separate package; the core has no network.
|
|
83
|
+
|
|
84
|
+
## Speed
|
|
85
|
+
|
|
86
|
+
Milliseconds per call as a caller sees it: a fresh process each time, interpreter start included
|
|
87
|
+
(about 40 ms of every number). Generated Markdown stores of 3.1 MB and 39.2 MB, 20 runs per call,
|
|
88
|
+
Python 3.14 on Linux under WSL2. The two stores were measured in separate runs on a machine that was
|
|
89
|
+
not idle: compare a row with the first row of its own column. `python3 bench/bench.py` reproduces it.
|
|
90
|
+
|
|
91
|
+
| Call | 225 docs p50 | p95 | 3 000 docs p50 | p95 |
|
|
92
|
+
|---|---:|---:|---:|---:|
|
|
93
|
+
| start of the interpreter (`--version`) | 35 | 38 | 34 | 37 |
|
|
94
|
+
| `brief <doc>` | 35 | 40 | 34 | 39 |
|
|
95
|
+
| `get <doc> --section --tail 5` | 35 | 37 | 35 | 36 |
|
|
96
|
+
| `view <doc>` | 34 | 35 | 35 | 39 |
|
|
97
|
+
| `brief --registry` | 42 | 44 | 127 | 140 |
|
|
98
|
+
| `brief --session <id>` | 42 | 50 | 127 | 134 |
|
|
99
|
+
| `resolve <key>` | 41 | 46 | 103 | 107 |
|
|
100
|
+
| `find <word in one doc>` | 44 | 45 | 155 | 163 |
|
|
101
|
+
| `find <common word>` | 69 | 77 | 173 | 199 |
|
|
102
|
+
| `find --tag` | 41 | 59 | 123 | 144 |
|
|
103
|
+
| `validate` | 54 | 60 | 295 | 309 |
|
|
104
|
+
| `validate --changed` | 49 | 55 | 184 | 194 |
|
|
105
|
+
|
|
106
|
+
**No search cache.** The rule was: a cache enters only above 3 000 docs, with `find` over 200 ms at
|
|
107
|
+
p95, or when a lookup needs ranked search a scan cannot give. At 3 000 docs every `find` stays under
|
|
108
|
+
200 ms. `find` matches terms and ranks its hits as part of the same scan (`ctx help find`), which
|
|
109
|
+
finds 17 of the 18 lookups in `bench/eval/` where the phrase match before it found 6; the one it
|
|
110
|
+
misses is a paraphrase, which an index of words would miss too. A task described in a sentence
|
|
111
|
+
or two finds its doc as well (7 of 7 in the eval). That is where the scan costs most: about 0.1 s for
|
|
112
|
+
25 words on 225 docs, about 0.9 s on 3 000. So the store has no index to build,
|
|
113
|
+
validate or lose. The question returns when a store passes 3 000 docs, or when lookups need
|
|
114
|
+
synonyms.
|
|
115
|
+
|
|
116
|
+
`validate --changed`, the call behind the after-write hook, stays under its 300 ms budget at 3 000 docs.
|
|
117
|
+
|
|
118
|
+
**Status:** P4: every verb except `row` is built; measured; no cache. Design and phasing:
|
|
119
|
+
[#1](https://github.com/MdaaaaO/ctx-store/issues/1). Licence: MIT.
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ctx-store
|
|
3
|
+
Version: 0.7.0
|
|
4
|
+
Summary: A markdown context store for coding agents: validated writes, budgeted reads, audit trail.
|
|
5
|
+
License: MIT
|
|
6
|
+
Requires-Python: >=3.10
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Dynamic: license-file
|
|
10
|
+
|
|
11
|
+
# ctx-store
|
|
12
|
+
|
|
13
|
+
`ctx` is a markdown context store for coding agents: one folder of `*.md` rows with YAML frontmatter as
|
|
14
|
+
the schema, a CLI with validated structured writes (`log`, `fm`, `new`, `move`), budgeted reads
|
|
15
|
+
(`brief`, `find --budget`, `resolve`, `get --section --tail`), a per-actor audit trail and a maintenance
|
|
16
|
+
pass (`init`, `validate`, `doctor`, `maintain`, `migrate`). The same core serves three front-ends: the CLI (Claude
|
|
17
|
+
Code hooks and skills call it), an Anthropic memory-tool handler (`view create str_replace insert delete
|
|
18
|
+
rename`) and an MCP server (stdio for Claude Desktop; HTTP with authentication for claude.ai, as a
|
|
19
|
+
separate package).
|
|
20
|
+
|
|
21
|
+
Production-grade by design: Python stdlib only (≥ 3.10), runs from a plain copy with no install, fixed
|
|
22
|
+
exit-code table, `--json` envelope (`"api": 1`), temp + rename writes under a lock, secret guard on every
|
|
23
|
+
payload, read-only store support, no writable state under the store for reads.
|
|
24
|
+
|
|
25
|
+
## Interface first
|
|
26
|
+
|
|
27
|
+
The interface is the contract: verbs, fixed errors and the doc model. Storage is a backend behind it.
|
|
28
|
+
Markdown files are the default backend, so a store stays a folder you can read and edit; the same calls
|
|
29
|
+
give the same answers on any other backend (`ctxstore/backend.py`, `ctx help backends`).
|
|
30
|
+
|
|
31
|
+
## Try it
|
|
32
|
+
|
|
33
|
+
```sh
|
|
34
|
+
git clone https://github.com/MdaaaaO/ctx-store && cd ctx-store
|
|
35
|
+
./ctx --version
|
|
36
|
+
./ctx doctor --store tests/fixtures/store-v1
|
|
37
|
+
./ctx help errors
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
No install step: `ctx` runs from a plain copy of the repo on Python ≥ 3.10. The interface (verbs, exit
|
|
41
|
+
codes, error strings, `--json` envelope, environment) is [`docs/interface.md`](docs/interface.md);
|
|
42
|
+
`ctx help` prints from the same file. Tests: `make ci`.
|
|
43
|
+
|
|
44
|
+
## Hooks
|
|
45
|
+
|
|
46
|
+
Every call a harness hook needs is one line. A write names its store; a read may find it by walking up.
|
|
47
|
+
|
|
48
|
+
| When | Call |
|
|
49
|
+
|---|---|
|
|
50
|
+
| Setup on a new machine, or a schema upgrade | `ctx init --store <path> --settings <file> --types <folder>` (add `--upgrade` for a new version: files edited since are kept) |
|
|
51
|
+
| After a change under the store | `ctx validate --changed` (add `--adopt` while writes still come from outside ctx) |
|
|
52
|
+
| Heartbeat | `ctx touch --session <id>` |
|
|
53
|
+
| Session start | `ctx brief --registry` |
|
|
54
|
+
| After a compaction | `ctx brief --session <id>` |
|
|
55
|
+
| A step landed | `ctx log <doc> "<what happened>"` |
|
|
56
|
+
| Session end, or on a timer | `ctx maintain` |
|
|
57
|
+
| CI, after a schema change | `ctx migrate --check` |
|
|
58
|
+
|
|
59
|
+
## Claude Desktop
|
|
60
|
+
|
|
61
|
+
```json
|
|
62
|
+
{"mcpServers": {"ctx": {"command": "/path/to/ctx-store/ctx", "args": ["mcp"],
|
|
63
|
+
"env": {"CTX_STORE": "/path/to/store", "CTX_ACTOR": "desktop"}}}}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
On Windows with the store and `ctx` inside WSL, Claude Desktop starts it through `wsl.exe`, and the
|
|
67
|
+
environment goes into the arguments:
|
|
68
|
+
|
|
69
|
+
```json
|
|
70
|
+
{"mcpServers": {"ctx": {"command": "wsl.exe",
|
|
71
|
+
"args": ["-e", "env", "CTX_STORE=/home/you/store", "CTX_ACTOR=desktop", "CTX_NO_WALK=1",
|
|
72
|
+
"/home/you/ctx-store/ctx", "mcp"]}}}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
| Install | `claude_desktop_config.json` is in |
|
|
76
|
+
|---|---|
|
|
77
|
+
| Windows, installer | `%APPDATA%\Claude\` |
|
|
78
|
+
| Windows, Microsoft Store | `%LOCALAPPDATA%\Packages\Claude_*\LocalCache\Roaming\Claude\` |
|
|
79
|
+
| macOS | `~/Library/Application Support/Claude/` |
|
|
80
|
+
|
|
81
|
+
Tested with the Microsoft Store install on Windows with WSL2: the tools are listed, and `brief`, `find`
|
|
82
|
+
and `log` work. The other two rows are where Claude Desktop documents its config; they were not tested
|
|
83
|
+
here.
|
|
84
|
+
|
|
85
|
+
Every built verb is a tool (`ctx_brief`, `ctx_find`, `ctx_log`, …). `ctx memory` takes the input of
|
|
86
|
+
Anthropic's memory tool on stdin.
|
|
87
|
+
|
|
88
|
+
## claude.ai
|
|
89
|
+
|
|
90
|
+
`ctx-serve` puts the same tools behind HTTP with authentication (OAuth for claude.ai, a bearer token for
|
|
91
|
+
Claude Code), for a store on your machine behind a tunnel: [`docs/connector.md`](docs/connector.md). It is
|
|
92
|
+
a separate package; the core has no network.
|
|
93
|
+
|
|
94
|
+
## Speed
|
|
95
|
+
|
|
96
|
+
Milliseconds per call as a caller sees it: a fresh process each time, interpreter start included
|
|
97
|
+
(about 40 ms of every number). Generated Markdown stores of 3.1 MB and 39.2 MB, 20 runs per call,
|
|
98
|
+
Python 3.14 on Linux under WSL2. The two stores were measured in separate runs on a machine that was
|
|
99
|
+
not idle: compare a row with the first row of its own column. `python3 bench/bench.py` reproduces it.
|
|
100
|
+
|
|
101
|
+
| Call | 225 docs p50 | p95 | 3 000 docs p50 | p95 |
|
|
102
|
+
|---|---:|---:|---:|---:|
|
|
103
|
+
| start of the interpreter (`--version`) | 35 | 38 | 34 | 37 |
|
|
104
|
+
| `brief <doc>` | 35 | 40 | 34 | 39 |
|
|
105
|
+
| `get <doc> --section --tail 5` | 35 | 37 | 35 | 36 |
|
|
106
|
+
| `view <doc>` | 34 | 35 | 35 | 39 |
|
|
107
|
+
| `brief --registry` | 42 | 44 | 127 | 140 |
|
|
108
|
+
| `brief --session <id>` | 42 | 50 | 127 | 134 |
|
|
109
|
+
| `resolve <key>` | 41 | 46 | 103 | 107 |
|
|
110
|
+
| `find <word in one doc>` | 44 | 45 | 155 | 163 |
|
|
111
|
+
| `find <common word>` | 69 | 77 | 173 | 199 |
|
|
112
|
+
| `find --tag` | 41 | 59 | 123 | 144 |
|
|
113
|
+
| `validate` | 54 | 60 | 295 | 309 |
|
|
114
|
+
| `validate --changed` | 49 | 55 | 184 | 194 |
|
|
115
|
+
|
|
116
|
+
**No search cache.** The rule was: a cache enters only above 3 000 docs, with `find` over 200 ms at
|
|
117
|
+
p95, or when a lookup needs ranked search a scan cannot give. At 3 000 docs every `find` stays under
|
|
118
|
+
200 ms. `find` matches terms and ranks its hits as part of the same scan (`ctx help find`), which
|
|
119
|
+
finds 17 of the 18 lookups in `bench/eval/` where the phrase match before it found 6; the one it
|
|
120
|
+
misses is a paraphrase, which an index of words would miss too. A task described in a sentence
|
|
121
|
+
or two finds its doc as well (7 of 7 in the eval). That is where the scan costs most: about 0.1 s for
|
|
122
|
+
25 words on 225 docs, about 0.9 s on 3 000. So the store has no index to build,
|
|
123
|
+
validate or lose. The question returns when a store passes 3 000 docs, or when lookups need
|
|
124
|
+
synonyms.
|
|
125
|
+
|
|
126
|
+
`validate --changed`, the call behind the after-write hook, stays under its 300 ms budget at 3 000 docs.
|
|
127
|
+
|
|
128
|
+
**Status:** P4: every verb except `row` is built; measured; no cache. Design and phasing:
|
|
129
|
+
[#1](https://github.com/MdaaaaO/ctx-store/issues/1). Licence: MIT.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
ctx_store.egg-info/PKG-INFO
|
|
5
|
+
ctx_store.egg-info/SOURCES.txt
|
|
6
|
+
ctx_store.egg-info/dependency_links.txt
|
|
7
|
+
ctx_store.egg-info/entry_points.txt
|
|
8
|
+
ctx_store.egg-info/top_level.txt
|
|
9
|
+
ctxserve/__init__.py
|
|
10
|
+
ctxserve/__main__.py
|
|
11
|
+
ctxserve/auth.py
|
|
12
|
+
ctxserve/server.py
|
|
13
|
+
ctxstore/VERSION
|
|
14
|
+
ctxstore/__init__.py
|
|
15
|
+
ctxstore/__main__.py
|
|
16
|
+
ctxstore/backend.py
|
|
17
|
+
ctxstore/bootstrap.py
|
|
18
|
+
ctxstore/cli.py
|
|
19
|
+
ctxstore/clock.py
|
|
20
|
+
ctxstore/config.py
|
|
21
|
+
ctxstore/contract.py
|
|
22
|
+
ctxstore/doctor.py
|
|
23
|
+
ctxstore/frontmatter.py
|
|
24
|
+
ctxstore/fs.py
|
|
25
|
+
ctxstore/interface.md
|
|
26
|
+
ctxstore/links.py
|
|
27
|
+
ctxstore/markdown.py
|
|
28
|
+
ctxstore/mcp.py
|
|
29
|
+
ctxstore/memory_tool.py
|
|
30
|
+
ctxstore/reads.py
|
|
31
|
+
ctxstore/search.py
|
|
32
|
+
ctxstore/secrets.py
|
|
33
|
+
ctxstore/sections.py
|
|
34
|
+
ctxstore/spec.py
|
|
35
|
+
ctxstore/store.py
|
|
36
|
+
ctxstore/upkeep.py
|
|
37
|
+
ctxstore/verbs.py
|
|
38
|
+
ctxstore/writes.py
|
|
39
|
+
tests/test_backend.py
|
|
40
|
+
tests/test_contract.py
|
|
41
|
+
tests/test_doctor.py
|
|
42
|
+
tests/test_eval.py
|
|
43
|
+
tests/test_hygiene.py
|
|
44
|
+
tests/test_init.py
|
|
45
|
+
tests/test_reads.py
|
|
46
|
+
tests/test_serve.py
|
|
47
|
+
tests/test_store.py
|
|
48
|
+
tests/test_upkeep.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|