@aistastudio/myc 0.3.6 → 0.3.9
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 +252 -124
- package/bin/myc.js +24 -10
- package/bin/preflight.js +5 -4
- package/dist/myc.js +666 -541
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
# myc
|
|
2
2
|
|
|
3
3
|
A local, fast task-and-memory layer for coding agents: a task queue, an oplog of
|
|
4
|
-
facts and decisions,
|
|
5
|
-
memory — with no network calls
|
|
4
|
+
facts and decisions, hybrid (lexical + vector) search over the project's
|
|
5
|
+
memory, and a built-in code index — with no network calls of its own and no
|
|
6
|
+
mandatory LLM key. The network is reached only when you ask: `myc models
|
|
7
|
+
fetch`, `myc code fetch`, `myc version --check` (or `MYC_UPDATE_CHECK=1`, a
|
|
8
|
+
background version check at most once a day from `init` and `wire`).
|
|
6
9
|
|
|
7
10
|
Agents forget. `myc` is the part that doesn't: decisions survive context
|
|
8
11
|
compaction, work survives process death, and both survive being moved between
|
|
@@ -11,11 +14,15 @@ machines through plain git.
|
|
|
11
14
|
Design docs live in `docs/design/` (start with `00-brief.md`); the measurements
|
|
12
15
|
quoted below are reproducible from `bench/` and `scripts/`.
|
|
13
16
|
|
|
14
|
-
**Site: <https://aistastudio.github.io/myc/>** —
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
**Site: <https://aistastudio.github.io/myc/>** — every capability with the
|
|
18
|
+
release it arrived in and a command that shows it, the roadmap, and the
|
|
19
|
+
measurements as charts, in English and Russian, with the command that
|
|
20
|
+
reproduces each number printed next to it. It is the one source of numbers:
|
|
21
|
+
`bun run site/build.ts` checks every figure on the site against the measurement
|
|
22
|
+
artefacts in this repository, the figures in this README and in the Russian one
|
|
23
|
+
against the site's `site/measurements.json`, and every `myc` command and flag
|
|
24
|
+
on the site and in both READMEs against this build's `--help`; a mismatch fails
|
|
25
|
+
the build.
|
|
19
26
|
|
|
20
27
|
## Requires Bun — this is not fine print
|
|
21
28
|
|
|
@@ -30,20 +37,23 @@ Install Bun: https://bun.sh
|
|
|
30
37
|
Installation is one command:
|
|
31
38
|
|
|
32
39
|
```bash
|
|
33
|
-
bun install -g @aistastudio/myc # 3.
|
|
34
|
-
myc --version # myc 0.3.
|
|
40
|
+
bun install -g @aistastudio/myc # 3.41 MB compressed, 12.57 MB unpacked, 13 files; no models pulled
|
|
41
|
+
myc --version # myc 0.3.9 (schema 1)
|
|
35
42
|
```
|
|
36
43
|
|
|
37
|
-
It runs on macOS and Linux
|
|
44
|
+
It runs on macOS and Linux. On Windows, use WSL and install Bun and myc inside
|
|
45
|
+
it: the `myc` launcher does not start in cmd or PowerShell, and an npm install
|
|
46
|
+
on Windows says so.
|
|
38
47
|
|
|
39
48
|
The embedding model is **not** downloaded during install. Semantic search is
|
|
40
49
|
opt-in and explicit: `myc models fetch` (129 MB, ~7 s). Until then search is
|
|
41
|
-
lexical and says so.
|
|
50
|
+
lexical and says so on every answer (`WARN degraded.embeddings`). The grammars
|
|
51
|
+
for the code index are fetched the same way, once: `myc code fetch`.
|
|
42
52
|
|
|
43
53
|
To run the newest code instead of the published release, build from source:
|
|
44
54
|
|
|
45
55
|
```bash
|
|
46
|
-
git clone
|
|
56
|
+
git clone https://github.com/aistastudio/myc && cd myc
|
|
47
57
|
bun install
|
|
48
58
|
bun run build # produces a single binary: dist/myc
|
|
49
59
|
./dist/myc --version
|
|
@@ -55,18 +65,40 @@ writing a config that silently won't start.
|
|
|
55
65
|
|
|
56
66
|
## Quick start
|
|
57
67
|
|
|
68
|
+
Two commands set a project up; the rest is the loop an agent lives in. (From a
|
|
69
|
+
source build, `./dist/myc` instead of `myc`.)
|
|
70
|
+
|
|
58
71
|
```bash
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
72
|
+
myc init # .myc/ + SQLite + migrations in this repo
|
|
73
|
+
myc wire # hooks + MCP for Claude Code, Codex, opencode and Kimi
|
|
74
|
+
myc ready --claim # take the next task
|
|
75
|
+
myc show <id> # all that is known about it
|
|
76
|
+
myc close <id>
|
|
77
|
+
myc remember "why X, not Y" # record a fact or decision
|
|
78
|
+
myc recall "how retrieval works"
|
|
79
|
+
myc prime # session context packet (agents call it)
|
|
80
|
+
myc code fetch # grammars for this repo's languages, once
|
|
81
|
+
myc code index # symbols, callers, code search
|
|
82
|
+
myc doctor # schema, counters, hooks — says "don't know" where it doesn't
|
|
67
83
|
```
|
|
68
84
|
|
|
69
|
-
Full command list:
|
|
85
|
+
Full command list: `myc --help`; details of each: `myc <command> --help`.
|
|
86
|
+
|
|
87
|
+
## Wiring agents
|
|
88
|
+
|
|
89
|
+
`myc wire` writes only its own files in full and merges JSON configs node by
|
|
90
|
+
node with a `.myc.bak` alongside; `CLAUDE.md` is never touched. Running it twice
|
|
91
|
+
changes nothing. Everything past the plain `wire` is opt-in:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
myc wire --dry-run # show every change, write nothing
|
|
95
|
+
myc wire --agents claude,codex # only some of the agents
|
|
96
|
+
myc wire --status-line # + myc's status line under Claude Code's prompt
|
|
97
|
+
myc wire --queue-hook # + heavy commands take turns (below)
|
|
98
|
+
myc wire --agents-md # + the myc block in AGENTS.md
|
|
99
|
+
myc wire --scope user # the same for agents in git worktrees (Claude Code's user layer)
|
|
100
|
+
myc unwire # remove what wire put in
|
|
101
|
+
```
|
|
70
102
|
|
|
71
103
|
**Agents in git worktrees.** `myc wire` writes into the project:
|
|
72
104
|
`.claude/settings.json`, `.mcp.json`. An agent that orca starts in a git
|
|
@@ -94,15 +126,15 @@ journal, not in our command, and gets the same stdin on every redraw, never
|
|
|
94
126
|
waited on: orca takes a line whose command mentions its
|
|
95
127
|
`agent-hooks/claude-statusline.sh` for its own and removes it when it
|
|
96
128
|
uninstalls (a foreign line it leaves alone), so ours never carries the word
|
|
97
|
-
`claude-statusline`. A
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
129
|
+
`claude-statusline`. A project with its own myc line keeps it, and that line
|
|
130
|
+
hands the input to the same recorded line. If another tool replaces the user
|
|
131
|
+
line after wire, `myc doctor --hooks` says so; `myc wire --scope user
|
|
132
|
+
--status-line` puts ours back and makes the new line the previous one, and `myc
|
|
133
|
+
unwire --scope user` puts the previous line back byte for byte. `myc doctor
|
|
134
|
+
--hooks` checks the whole user layer against the journal: myc's hook entries and
|
|
135
|
+
rules still in `~/.claude/settings.json`, the helpers exactly what this build
|
|
136
|
+
writes (a stale one is named with the build that wrote it), the status line, the
|
|
137
|
+
MCP server.
|
|
106
138
|
|
|
107
139
|
## Heavy commands take turns
|
|
108
140
|
|
|
@@ -144,14 +176,14 @@ Code `PreToolUse` hook that rewrites a heavy Bash command into
|
|
|
144
176
|
`myc run -- <the same command>` before it runs. Heavy means a full test run or a
|
|
145
177
|
build: `bun test` with no paths, `bun run build` / `typecheck`, `npm` / `pnpm` /
|
|
146
178
|
`yarn` `test` and `build`, `cargo test` / `build`, `go test ./...`, `pytest`
|
|
147
|
-
with no paths, `make`. A targeted `bun test path
|
|
179
|
+
with no paths, `make`. A targeted `bun test <path>`, a command already
|
|
148
180
|
under `myc run`, a background one and a nested one pass untouched.
|
|
149
181
|
`MYC_QUEUE_HEAVY` replaces the list (`+…` adds to it, `off` turns the hook off).
|
|
150
182
|
It is opt-in: `wire` without the flag writes no such hook, and `unwire` removes
|
|
151
183
|
it. It is cheap, because it runs on every Bash call: a command that is not heavy
|
|
152
184
|
is let through by the host's own shell without starting bun or node — 3.4 ms at
|
|
153
|
-
the median and 4.3 ms at p99 in the run of 2026-09-11, against
|
|
154
|
-
|
|
185
|
+
the median and 4.3 ms at p99 in the run of 2026-09-11, against the prime hook's
|
|
186
|
+
30 ms p99 budget (`bun test packages/cli/src/hooks/queue-hook.multiprocess.test.ts`).
|
|
155
187
|
|
|
156
188
|
**`myc run` is not a way around permissions.** It runs whatever it is given, so
|
|
157
189
|
a queued command goes through without a question only when your own rules would
|
|
@@ -159,26 +191,139 @@ let the original command through — `Bash(bun test:*)` keeps `bun test` silent
|
|
|
159
191
|
under the queue as well. Otherwise Claude Code asks, and the question shows the
|
|
160
192
|
whole command; a deny or ask rule on the original command still holds. The same
|
|
161
193
|
goes for a `myc run -- <cmd>` an agent types itself. For the same reason `wire`
|
|
162
|
-
|
|
163
|
-
|
|
194
|
+
does not write the broad `Bash(myc:*)`: it allows myc's subcommands one by one,
|
|
195
|
+
and `run`, `statusline --then`, `wire` and `unwire` ask.
|
|
196
|
+
|
|
197
|
+
## Code intelligence
|
|
198
|
+
|
|
199
|
+
Code intelligence is built in, and it is the same engine the alternatives use:
|
|
200
|
+
tree-sitter, with grammars fetched on demand rather than shipped. Symbols,
|
|
201
|
+
callers and code search work for TypeScript, TSX, JavaScript (js, jsx, mjs,
|
|
202
|
+
cjs) and Python — the languages myc has definition rules for. The grammar
|
|
203
|
+
package holds 36; a language is added as a pair, a rule and a catalog entry,
|
|
204
|
+
so a grammar that would yield no symbols is never offered. Every other file
|
|
205
|
+
still gets `code grep`, anchors and staleness.
|
|
206
|
+
|
|
207
|
+
`myc code fetch` downloads exactly the grammars this repository's files need,
|
|
208
|
+
checked by sha256 — the only step that goes to the network; indexing never does,
|
|
209
|
+
and a language whose grammar is missing is skipped and named. `myc code index`
|
|
210
|
+
builds the index, incrementally: a repeat run over an unchanged tree reads
|
|
211
|
+
nothing, and after that the index is refreshed in the background. These read it,
|
|
212
|
+
from the CLI and over MCP alike:
|
|
213
|
+
|
|
214
|
+
```
|
|
215
|
+
myc code symbol <name> where it is defined, and what knowledge is anchored there
|
|
216
|
+
myc callers <name> who calls it; --direction out, --depth all
|
|
217
|
+
myc code search "…" by meaning, when you do not know the name
|
|
218
|
+
myc code grep "<lit>" exhaustive, every occurrence; --in <path> narrows it
|
|
219
|
+
myc code map orientation: directory clusters, their hubs, who depends on them
|
|
220
|
+
myc skeleton <file> the file's API, and how many times cheaper that was than reading it
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
The file list is git's own (`git ls-files`, so `.gitignore` applies; a tree
|
|
224
|
+
without git is walked, and the command says so). On top of any list,
|
|
225
|
+
secret-named files are never indexed, whatever `.gitignore` says: `.env` and
|
|
226
|
+
`.env.*` (templates like `.env.example` are indexed), `*.pem`, `*.key`,
|
|
227
|
+
keystores, private SSH keys, `.npmrc`, `.netrc` and other credential files —
|
|
228
|
+
`code index` counts them without naming them, and `code grep` refuses to read one.
|
|
229
|
+
|
|
230
|
+
**Nested repositories and git worktrees.** A workspace can be an ecosystem: a
|
|
231
|
+
root that is a git repository with independent repositories inside it (not
|
|
232
|
+
submodules). It has one code index, built from the root — one row per file,
|
|
233
|
+
paths like `messaging-server/server/src/x.ts`. From inside a nested
|
|
234
|
+
repository every code command answers from that repository's part of the
|
|
235
|
+
root index, with paths relative to the repository you are in; from the root
|
|
236
|
+
the answers do not change. `myc code index` run inside a nested repository
|
|
237
|
+
refreshes its part of the root index instead of building a second copy of the
|
|
238
|
+
same files. The index also keeps itself fresh: after any myc command, when its
|
|
239
|
+
last run is older than 15 minutes (`MYC_CODE_INDEX_PERIOD_MS`), one background
|
|
240
|
+
`code index` per workspace is queued and runs detached at low priority, never
|
|
241
|
+
delaying the command; the status line and the code commands say when it is
|
|
242
|
+
refreshing, queued or stale. A git worktree — even one
|
|
243
|
+
outside the workspace tree — is answered from the index of the main checkout:
|
|
244
|
+
there is no index per branch. When the worktree is on another commit, or has
|
|
245
|
+
uncommitted changes to tracked files, every answer carries
|
|
246
|
+
`WARN code_index.worktree_divergent` naming both branches, because lines and
|
|
247
|
+
spans may not match your files. `code grep` reads the worktree's files (the
|
|
248
|
+
line numbers are yours, the owning symbols come from the index); `skeleton`
|
|
249
|
+
shows the main copy's declarations when your copy differs from what the index
|
|
250
|
+
saw, and says so. When nothing covers the repository, the hint is the command
|
|
251
|
+
for the workspace root (`myc -C <root> code index`), not one that would build a
|
|
252
|
+
duplicate. Anchors set from the root and from inside a repository are stored
|
|
253
|
+
under different keys; `code symbol` reads both.
|
|
254
|
+
|
|
255
|
+
Anchors tie knowledge to a span and follow the code as it moves; that half is
|
|
256
|
+
language-agnostic and was verified on Python as well as TypeScript.
|
|
257
|
+
|
|
258
|
+
## Migration from beads
|
|
259
|
+
|
|
260
|
+
```bash
|
|
261
|
+
cd <beads-project>
|
|
262
|
+
myc init
|
|
263
|
+
myc import-beads --dry-run # count what would come over, change nothing
|
|
264
|
+
myc import-beads # collects the snapshot itself: bd export --include-memories
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
Run it again later and it is a sync, not a second copy: fields changed in beads
|
|
268
|
+
(status, priority, labels, close reason, parent, blockers) are applied as normal
|
|
269
|
+
graph changes, and local myc edits are never silently overwritten — one-sided
|
|
270
|
+
local changes are kept and named, two-sided ones are named as conflicts and left
|
|
271
|
+
alone. A snapshot file moves the same between machines:
|
|
272
|
+
`bd export --include-memories > snapshot.json`, then
|
|
273
|
+
`myc import-beads snapshot.json`.
|
|
274
|
+
|
|
275
|
+
**It is real, not a demo.** A working project imported into an empty workspace
|
|
276
|
+
in 889 ms: 796 tasks, 972 dependencies, 265 notes, 41 memories — with unknown
|
|
277
|
+
issue types carried over verbatim and named, and out-of-range priorities
|
|
278
|
+
clamped and named, instead of one odd row aborting the import. Those numbers are
|
|
279
|
+
from the first release (0.1.1, 2026-09-07), and that run silently dropped the
|
|
280
|
+
export's comments while reporting every note as imported; it was found the next
|
|
281
|
+
day on a real project and fixed in 0.2.0 (`git show aac5d1f`). What the import
|
|
282
|
+
carries now:
|
|
283
|
+
|
|
284
|
+
- comments, into the node's thread with their authors; unknown top-level
|
|
285
|
+
fields are named instead of dropped (0.2.0);
|
|
286
|
+
- acceptance criteria and design, into the task body between managed markers,
|
|
287
|
+
and the source's own dates, author and owner (0.3.3);
|
|
288
|
+
- statuses myc has no name for, such as `deferred`, as `blocked` with the
|
|
289
|
+
original word kept — never as `open` (0.3.3);
|
|
290
|
+
- sub-repositories of a shared workspace, each with its own repository reach;
|
|
291
|
+
an empty source is a refusal with a hint, not a silent zero (0.3.3).
|
|
292
|
+
|
|
293
|
+
On that same graph both ready queues now return the same 152 tasks. They did
|
|
294
|
+
not always: myc used to offer 195 against beads' 144, because beads inherits
|
|
295
|
+
blockers down the parent chain and myc looked only at a task's own. Those 51
|
|
296
|
+
were inside a still-blocked epic and beads was right to hide them;
|
|
297
|
+
`memory-atcm254ry6c7` is closed, `anc_blockers` is materialised by trigger, and
|
|
298
|
+
the queue now says `281 blocked (51 through an ancestor)` rather than quietly
|
|
299
|
+
offering them.
|
|
164
300
|
|
|
165
301
|
## What makes it different
|
|
166
302
|
|
|
167
|
-
**Speed is a constraint, not an optimisation.** Every hot path has a budget
|
|
168
|
-
|
|
169
|
-
|
|
303
|
+
**Speed is a constraint, not an optimisation.** Every hot path has a budget,
|
|
304
|
+
and a budget test makes three kinds of claims: structural (the query plan, the
|
|
305
|
+
prefilter), relative (the healthy path against a deliberately degraded rival,
|
|
306
|
+
measured alternately, so the hardware cancels out) and absolute. On every push
|
|
307
|
+
CI checks the first two. The absolute budgets and the 15% p95 regression line
|
|
308
|
+
are calibrated on darwin-arm64-14 and bind there; CI and the nightly run use
|
|
309
|
+
GitHub's 4-core runners, which are not that machine and are declared
|
|
310
|
+
uncalibrated (`MYC_BENCH_ABSOLUTE=0`), so there the absolute numbers are printed
|
|
311
|
+
and logged, not enforced. Measured on 100 000 nodes on 2026-09-11,
|
|
312
|
+
darwin-arm64-14, myc 0.3.6, not re-measured since
|
|
313
|
+
(`bun run scripts/bench-latency.ts`):
|
|
170
314
|
|
|
171
315
|
| operation | p99 | budget |
|
|
172
316
|
|---|---|---|
|
|
173
|
-
| `prime` (session context) | 0.
|
|
174
|
-
| read | 0.
|
|
175
|
-
| search |
|
|
176
|
-
| write | 0.
|
|
177
|
-
| cold start |
|
|
317
|
+
| `prime` (session context) | 0.608 ms | 30 ms |
|
|
318
|
+
| read | 0.010 ms | 3 ms |
|
|
319
|
+
| search | 8.215 ms | 25 ms |
|
|
320
|
+
| write | 0.327 ms | 5 ms |
|
|
321
|
+
| cold start | 21.337 ms | 60 ms |
|
|
178
322
|
|
|
179
323
|
**Ranking is measured, not asserted.** Two labelled corpora with graded
|
|
180
324
|
relevance, each containing a *control group that gets worse* when the feature
|
|
181
|
-
works — so a gain cannot be manufactured by shaping the corpus
|
|
325
|
+
works — so a gain cannot be manufactured by shaping the corpus (both re-measured
|
|
326
|
+
2026-09-10):
|
|
182
327
|
|
|
183
328
|
- boosts (priority, freshness, layer): MRR@10 **0.520 → 0.867** (`bench/boost-eval.ts`)
|
|
184
329
|
- graph expansion to 2 hops: MRR@10 **0.193 → 0.422** (`bench/graph-eval.ts`),
|
|
@@ -205,6 +350,29 @@ episode sess-5jh8je4g050m saved (265 B)
|
|
|
205
350
|
NEXT myc show sess-5jh8je4g050m · myc ready --claim
|
|
206
351
|
```
|
|
207
352
|
|
|
353
|
+
**Decisions pulled from a compaction are candidates, not facts.** The same hook
|
|
354
|
+
lifts "we decided / because" lines out of the transcript and stores them as
|
|
355
|
+
candidates (`state pending_review`); recall, search, prime and MCP do not
|
|
356
|
+
return them until someone confirms. `prime` names them in its footer —
|
|
357
|
+
`N pending review hidden — myc review` — and `myc review` lists them, this
|
|
358
|
+
session's first, for a person or an agent to settle. Confirming makes the
|
|
359
|
+
candidate knowledge the way a new note is born (embedding and absorb
|
|
360
|
+
classification queued); rejecting retracts it with the reason kept in the node.
|
|
361
|
+
An agent does the same through MCP: `myc_ready` with `review` lists,
|
|
362
|
+
`myc_update` with `confirm` or `reject` settles; the web knowledge base puts
|
|
363
|
+
the two buttons on the candidate's row.
|
|
364
|
+
|
|
365
|
+
```
|
|
366
|
+
$ myc review
|
|
367
|
+
PENDING REVIEW 2 · 1 in this session's prime · 1 from other sessions · session 3f9c21aa
|
|
368
|
+
$ myc review confirm memory-6k2x…
|
|
369
|
+
$ myc review reject memory-9x1q… --reason "restates the task, not a decision"
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
A retracted note — a rejected candidate among them — is out of every retrieval
|
|
373
|
+
path, not only replaced versions: superseded, retracted and cancelled are one
|
|
374
|
+
list shared by recall, prime and the status line.
|
|
375
|
+
|
|
208
376
|
**A status line with what the agent cannot see.** `myc wire --status-line`
|
|
209
377
|
puts one line under Claude Code's prompt — how full the context is, the task
|
|
210
378
|
queue, the code index, the project's memory, and how many of this session's
|
|
@@ -233,17 +401,20 @@ project-wide.
|
|
|
233
401
|
$ MYC_SESSION_ID=s1 myc recall "retries" $ MYC_SESSION_ID=s2 myc recall "retries"
|
|
234
402
|
… prj project note: retries use jitter … prj project note: retries use jitter
|
|
235
403
|
… ses session note: retries back off… … ses* session note: retries back off…
|
|
236
|
-
3 of 3 · bm25 only
|
|
404
|
+
3 of 3 · bm25 only · … 3 of 3 · bm25 only · … · 2 from other sessions
|
|
237
405
|
```
|
|
238
406
|
|
|
239
407
|
**Memory has three independent axes**, and the surface says what it hid:
|
|
240
408
|
tier (project vs personal), session reach, repository reach. `prime` prints
|
|
241
|
-
`N
|
|
409
|
+
`N from other sessions hidden` and `N notes from other repos hidden` rather
|
|
410
|
+
than quietly narrowing results.
|
|
242
411
|
|
|
243
412
|
**Degradation is loud.** No silent fallbacks: when the vector branch is
|
|
244
413
|
unavailable the output says so and marks the answer as lexical-only; when a
|
|
245
414
|
budget is exceeded it is named with the number. The invariant is that a
|
|
246
|
-
degraded answer must never be indistinguishable from a healthy one.
|
|
415
|
+
degraded answer must never be indistinguishable from a healthy one. With
|
|
416
|
+
`--strict` a degraded answer also exits with code 6 instead of 0, and the
|
|
417
|
+
`WARN` line still prints.
|
|
247
418
|
|
|
248
419
|
**Multi-machine sync through plain git, merged per field.** Only the oplog is
|
|
249
420
|
committed. Two machines editing the same node converge: one changes title and
|
|
@@ -251,91 +422,48 @@ priority, the other title and tags — after exchange both show the later title,
|
|
|
251
422
|
the first machine's priority and the second's tags. Nothing is lost to
|
|
252
423
|
last-writer-wins over whole records.
|
|
253
424
|
|
|
254
|
-
**Migration from beads is real, not a demo.** A working project imported in
|
|
255
|
-
889 ms: 796 tasks, 972 dependencies, 265 notes, 41 memories — with unknown
|
|
256
|
-
issue types carried over verbatim and named, and out-of-range priorities
|
|
257
|
-
clamped and named, instead of one odd row aborting the import. On that same
|
|
258
|
-
graph both queues now return the same 152 tasks. They did not always: myc used
|
|
259
|
-
to offer 195 against beads' 144, because beads inherits blockers down the
|
|
260
|
-
parent chain and myc looked only at a task's own. Those 51 were inside a
|
|
261
|
-
still-blocked epic and beads was right to hide them; `memory-atcm254ry6c7` is
|
|
262
|
-
closed, `anc_blockers` is materialised by trigger, and the queue now says
|
|
263
|
-
`281 blocked (51 through an ancestor)` rather than quietly offering them.
|
|
264
|
-
|
|
265
425
|
**Guards are proved by mutation.** Every refusal and every invariant is
|
|
266
426
|
accompanied by a mutation that removes it; a guard whose removal breaks no test
|
|
267
|
-
is treated as absent.
|
|
268
|
-
|
|
269
|
-
## Roadmap
|
|
427
|
+
is treated as absent. The full suite: 3625 pass / 0 fail / 16 skip
|
|
428
|
+
(`bun test`, 2026-09-11).
|
|
270
429
|
|
|
271
|
-
|
|
272
|
-
2026-09-10. Done and not-done are shown the same way on purpose. Totals grow
|
|
273
|
-
when work uncovers work: M0 went 33 → 39 because measuring it found four real
|
|
274
|
-
defects, not because the plan changed.
|
|
275
|
-
|
|
276
|
-
| milestone | status |
|
|
277
|
-
|---|---|
|
|
278
|
-
| **M0** core and tasks | 40 / 43 |
|
|
279
|
-
| **M0.5** self-hosting (myc developed through myc) | **4 / 4 — closed** |
|
|
280
|
-
| **M1** memory | 22 / 24 |
|
|
281
|
-
| **M2** semantics | 20 / 22 |
|
|
282
|
-
| **M7** human interface (board, cards, threads, routing panel, status line) | **15 / 15** |
|
|
283
|
-
| **M3** code intelligence | 6 / 10 |
|
|
284
|
-
| **M4** team: `myc serve`, ACL, network sync, Postgres, containers | 3 / 14 |
|
|
285
|
-
| **M5** swarm self-learning: routing by cost and outcome | 0 / 13 |
|
|
286
|
-
| **M6** distillation | 0 / 7 |
|
|
287
|
-
|
|
288
|
-
What that means in practice: **today myc is a single-user local tool over files
|
|
289
|
-
in git.** There is no server, no ACL and no team mode. Those are designed
|
|
290
|
-
(`docs/design/03…`, `04…`, `05…`) and tracked, not implemented.
|
|
430
|
+
## What myc does
|
|
291
431
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
432
|
+
Tasks with leases, dependencies and blockers inherited down the parent chain;
|
|
433
|
+
memory that survives compaction and is scoped by session and repository;
|
|
434
|
+
ranked hybrid search; the code index above; hooks and MCP for four agents;
|
|
435
|
+
the machine-wide queue for heavy commands; the status line; import from beads;
|
|
436
|
+
a local web interface (`myc viz`: graph, queue, board, cards, search, health —
|
|
437
|
+
edits go through the same write path as the CLI); git worktrees and nested
|
|
438
|
+
repositories; sync through git and a `doctor` that compares claims with a
|
|
439
|
+
recount.
|
|
300
440
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
myc
|
|
305
|
-
myc code grep "<lit>" exhaustive, every occurrence; --in <path> narrows it
|
|
306
|
-
myc skeleton <file> the file's API — 26× cheaper than reading it
|
|
307
|
-
```
|
|
441
|
+
The full list — each capability with the release it arrived in and a command
|
|
442
|
+
that shows it on your machine, every command checked against this build's
|
|
443
|
+
`--help` when the site is built — is on the site:
|
|
444
|
+
<https://aistastudio.github.io/myc/#features>.
|
|
308
445
|
|
|
309
|
-
|
|
310
|
-
without git is walked, and the command says so). On top of any list,
|
|
311
|
-
secret-named files are never indexed, whatever `.gitignore` says: `.env` and
|
|
312
|
-
`.env.*` (templates like `.env.example` are indexed), `*.pem`, `*.key`,
|
|
313
|
-
keystores, private SSH keys, `.npmrc`, `.netrc` and other credential files —
|
|
314
|
-
`code index` counts them without naming them, and `code grep` refuses to read one.
|
|
446
|
+
## Roadmap
|
|
315
447
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
line numbers are yours, the owning symbols come from the index); `skeleton`
|
|
331
|
-
shows the main copy's declarations when your copy differs from what the index
|
|
332
|
-
saw, and says so. When nothing covers the repository, the hint is the command
|
|
333
|
-
for the workspace root (`myc -C <root> code index`), not one that would build a
|
|
334
|
-
duplicate. Anchors set from the root and from inside a repository are stored
|
|
335
|
-
under different keys; `code symbol` reads both.
|
|
448
|
+
Where each milestone stands — closed/total subtasks of every epic in the
|
|
449
|
+
project's own tracker, and every task still open inside it, with no dates — is
|
|
450
|
+
on the site: <https://aistastudio.github.io/myc/#planned>. The counts are not
|
|
451
|
+
typed in: `bun run site/roadmap.ts` reads them from myc before a release, and
|
|
452
|
+
the site build refuses a plan that describes a task the tracker no longer has
|
|
453
|
+
open.
|
|
454
|
+
|
|
455
|
+
In short: the core, memory, semantics and the human interface (M0–M2, M7) are
|
|
456
|
+
done or nearly done, and so is English output for every CLI and MCP line; code
|
|
457
|
+
intelligence (M3, including the built-in replacement for graft) and the
|
|
458
|
+
heavy-command queue have shipped, with tasks still open; the team milestone
|
|
459
|
+
(M4: `myc serve`, ACL, network sync, Postgres) is mostly design; swarm
|
|
460
|
+
self-learning (M5: routing by cost and outcome, with a shared pool of agent
|
|
461
|
+
statistics) and distillation (M6) have not started.
|
|
336
462
|
|
|
337
|
-
|
|
338
|
-
|
|
463
|
+
What that means in practice: **today myc is a single-user local tool over files
|
|
464
|
+
in git.** There is no server, no ACL and no team mode. Those are designed
|
|
465
|
+
(`docs/design/03-interfaces-and-integration.md`,
|
|
466
|
+
`docs/design/04-swarm-learning-and-routing.md`) and tracked, not implemented.
|
|
339
467
|
|
|
340
468
|
## Syncing between machines
|
|
341
469
|
|
package/bin/myc.js
CHANGED
|
@@ -28,7 +28,8 @@
|
|
|
28
28
|
* после интерпретатора ОДНИМ аргументом. -S есть в GNU coreutils ≥ 8.30 и в
|
|
29
29
|
* env macOS/BSD. На Windows такой shebang не исполним: шим `bun add -g` берёт
|
|
30
30
|
* `-S` за программу, а cmd-shim npm -S понимает, но Bun на Windows не
|
|
31
|
-
* открывает /dev/null — myc там только через WSL (
|
|
31
|
+
* открывает /dev/null — myc там только через WSL (говорят preflight.js и
|
|
32
|
+
* refusal() ниже, если этот файл всё же запустили под Node).
|
|
32
33
|
* Запуск МИМО shebang (`bun …/myc.js`) флагов не получает; второй рубеж для
|
|
33
34
|
* `myc run` — callerEnv в src/commands/run.ts.
|
|
34
35
|
*/
|
|
@@ -82,31 +83,44 @@ function resolveVec0() {
|
|
|
82
83
|
}
|
|
83
84
|
}
|
|
84
85
|
|
|
86
|
+
/**
|
|
87
|
+
* Текст отказа — по-английски, как весь вывод CLI (эпик memory-rc2s0m1e9kpz).
|
|
88
|
+
* На Windows совет «поставьте Bun» был бы ложным: shebang там не исполним и с
|
|
89
|
+
* Bun (см. шапку и preflight.js), поэтому совет там один — WSL, тем же текстом,
|
|
90
|
+
* что в рамке preflight.js.
|
|
91
|
+
*/
|
|
85
92
|
function refusal() {
|
|
86
93
|
const node = process.versions.node;
|
|
87
94
|
const lines = [
|
|
88
95
|
"",
|
|
89
96
|
" myc requires Bun — it cannot run on Node.",
|
|
90
97
|
"",
|
|
91
|
-
`
|
|
92
|
-
"
|
|
98
|
+
` This is Node ${node}, and myc runs only on Bun: its storage is built`,
|
|
99
|
+
" on Bun's built-in `bun:sqlite`, which Node does not have.",
|
|
93
100
|
"",
|
|
94
101
|
];
|
|
95
|
-
if (
|
|
102
|
+
if (process.platform === "win32") {
|
|
103
|
+
lines.push(
|
|
104
|
+
" myc runs on macOS and Linux; on Windows use WSL.",
|
|
105
|
+
" The `myc` launcher will not start in cmd or PowerShell, with or without Bun.",
|
|
106
|
+
" wsl --install",
|
|
107
|
+
" Then, inside WSL: install Bun and @aistastudio/myc there.",
|
|
108
|
+
"",
|
|
109
|
+
);
|
|
110
|
+
} else if (bunOnPath()) {
|
|
96
111
|
lines.push(
|
|
97
|
-
" Bun
|
|
98
|
-
" bun x myc
|
|
99
|
-
"
|
|
112
|
+
" Bun is installed — run myc through it:",
|
|
113
|
+
" bun x myc <command>",
|
|
114
|
+
" or reinstall the package with bun:",
|
|
100
115
|
" bun add -g @aistastudio/myc",
|
|
101
116
|
"",
|
|
102
117
|
);
|
|
103
118
|
} else {
|
|
104
119
|
lines.push(
|
|
105
|
-
"
|
|
120
|
+
" Install Bun (>= 1.3.0) and try again:",
|
|
106
121
|
" curl -fsSL https://bun.sh/install | bash # macOS, Linux, WSL",
|
|
107
|
-
' powershell -c "irm bun.sh/install.ps1 | iex" # Windows',
|
|
108
122
|
"",
|
|
109
|
-
"
|
|
123
|
+
" Then: myc --version",
|
|
110
124
|
"",
|
|
111
125
|
);
|
|
112
126
|
}
|
package/bin/preflight.js
CHANGED
|
@@ -38,14 +38,15 @@ if (process.platform === "win32") {
|
|
|
38
38
|
]),
|
|
39
39
|
);
|
|
40
40
|
} else if (typeof process.versions.bun !== "string" && !bunOnPath()) {
|
|
41
|
+
// По-английски, как весь вывод CLI (эпик memory-rc2s0m1e9kpz).
|
|
41
42
|
process.stderr.write(
|
|
42
|
-
frame("@aistastudio/myc
|
|
43
|
-
"myc
|
|
44
|
-
"Bun
|
|
43
|
+
frame("@aistastudio/myc is installed, but it will not start yet", [
|
|
44
|
+
"myc runs only on Bun (its storage is bun:sqlite).",
|
|
45
|
+
"Bun was not found on this system.",
|
|
45
46
|
"",
|
|
46
47
|
" curl -fsSL https://bun.sh/install | bash",
|
|
47
48
|
"",
|
|
48
|
-
"
|
|
49
|
+
"Then: myc --version",
|
|
49
50
|
]),
|
|
50
51
|
);
|
|
51
52
|
}
|