@aistastudio/myc 0.3.2 → 0.3.4

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 +112 -3
  2. package/dist/myc.js +1367 -499
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -31,7 +31,7 @@ Installation is one command:
31
31
 
32
32
  ```bash
33
33
  bun install -g @aistastudio/myc # 3.20 MB, 10 files, no models pulled at install
34
- myc --version # myc 0.3.2 (schema 1)
34
+ myc --version # myc 0.3.4 (schema 1)
35
35
  ```
36
36
 
37
37
  The embedding model is **not** downloaded during install. Semantic search is
@@ -56,6 +56,7 @@ writing a config that silently won't start.
56
56
  ```bash
57
57
  ./dist/myc init # .myc/ + SQLite + migrations in this repo
58
58
  ./dist/myc wire # hooks for Claude Code / Codex / opencode / Kimi
59
+ ./dist/myc wire --scope user # the same for agents in git worktrees (Claude Code's user layer)
59
60
  ./dist/myc ready # what can be picked up right now
60
61
  ./dist/myc remember "why X, not Y" # record a fact or decision
61
62
  ./dist/myc recall "how retrieval works"
@@ -65,6 +66,82 @@ writing a config that silently won't start.
65
66
 
66
67
  Full command list: `./dist/myc --help`.
67
68
 
69
+ **Agents in git worktrees.** `myc wire` writes into the project:
70
+ `.claude/settings.json`, `.mcp.json`. An agent that orca starts in a git
71
+ worktree of a nested repository (`~/orca/workspaces/<repo>/<branch>`) lives in
72
+ the team's tree, where those files are not, even though `myc` itself finds the
73
+ main copy's workspace from there. `myc wire --scope user` puts the same into
74
+ Claude Code's user layer, which every session reads:
75
+ `~/.claude/helpers/myc-hooks.mjs`, SessionStart/PreCompact/PostToolUse hooks and
76
+ `Bash(myc <command>:*)` rules in `~/.claude/settings.json` (merged node by node;
77
+ the hooks of orca, herdr and other tools stay byte for byte), the skill in
78
+ `~/.claude/skills/myc`, and the MCP server through `claude mcp add --scope user`.
79
+ Before anything else the helper checks, without starting myc, whether there is
80
+ a workspace here (a git worktree is resolved through its main copy), and stays
81
+ silent when there is none or the project wires myc itself: in a project without
82
+ myc the hook costs one node start, and prime never arrives twice. Outside a
83
+ workspace the MCP server offers zero tools and no instructions. The user's
84
+ `statusLine` is never touched (it belongs to orca), and `--hook-mode replace`
85
+ is refused here. The journal is `~/.myc/wire-user.json`; `myc unwire --scope
86
+ user` restores the settings node by node and removes the MCP server.
87
+
88
+ ## Heavy commands take turns
89
+
90
+ Several agents on one machine — in one tree or in neighbouring projects — each
91
+ run the heavy things: the full test suite, builds, benchmarks. Run at once, they
92
+ get in each other's way: full runs take twice as long, and latency budgets fail
93
+ because of the neighbour, not the code. `myc run` puts such a command into one
94
+ queue shared by every repository of the machine user (`~/.myc/queue.db`), waits
95
+ for a free slot (first come, first served) and then runs it with the terminal
96
+ and the exit code left alone:
97
+
98
+ ```bash
99
+ myc run -- bun test # waits its turn (--max-wait 5m by default), then runs
100
+ myc run --max-wait 15m -- make # a longer wait for a longer tool timeout
101
+ myc queue # who is running, who is waiting, for how long
102
+ ```
103
+
104
+ ```
105
+ $ myc queue
106
+ heavy · slots 1 · 1 running · 1 waiting · ~/.myc/queue.db
107
+ running #1 4s bun test ~/src/api session 6468c59d · orca term_efe4850f · pid 44815 · command pid 44827
108
+ waiting #2 3s bun run build ~/src/web session 6468c59d · orca term_efe4850f · pid 44850 (#1 in line)
109
+ ```
110
+
111
+ A waiting command says on stderr whom it waits for; past `--max-wait` it gives
112
+ up with exit code 9 and names what is ahead:
113
+
114
+ ```
115
+ myc run: waiting for a 'heavy' slot (1/1 busy, 1 waiting ahead), waited 0.0s of max 3s — held by 'bun test' in ~/src/api, session 6468c59d, orca term_efe4850f, pid 44815, running 13s
116
+ ```
117
+
118
+ A holder that dies — even by `SIGKILL` — frees its slot; a `myc run` nested
119
+ inside another one runs at once, in its parent's slot. One slot per lane by
120
+ default, `MYC_HEAVY_SLOTS=2` for two.
121
+
122
+ **Agents don't have to remember it.** `myc wire --queue-hook` installs a Claude
123
+ Code `PreToolUse` hook that rewrites a heavy Bash command into
124
+ `myc run -- <the same command>` before it runs. Heavy means a full test run or a
125
+ build: `bun test` with no paths, `bun run build` / `typecheck`, `npm` / `pnpm` /
126
+ `yarn` `test` and `build`, `cargo test` / `build`, `go test ./...`, `pytest`
127
+ with no paths, `make`. A targeted `bun test path/file.test.ts`, a command already
128
+ under `myc run`, a background one and a nested one pass untouched.
129
+ `MYC_QUEUE_HEAVY` replaces the list (`+…` adds to it, `off` turns the hook off).
130
+ It is opt-in: `wire` without the flag writes no such hook, and `unwire` removes
131
+ it. It is cheap, because it runs on every Bash call: a command that is not heavy
132
+ is let through by the host's own shell without starting bun or node — 3.4 ms at
133
+ the median and 4.3 ms at p99 in the run of 2026-09-11, against 30 ms for the
134
+ prime hook (`bun test packages/cli/src/hooks/queue-hook.multiprocess.test.ts`).
135
+
136
+ **`myc run` is not a way around permissions.** It runs whatever it is given, so
137
+ a queued command goes through without a question only when your own rules would
138
+ let the original command through — `Bash(bun test:*)` keeps `bun test` silent
139
+ under the queue as well. Otherwise Claude Code asks, and the question shows the
140
+ whole command; a deny or ask rule on the original command still holds. The same
141
+ goes for a `myc run -- <cmd>` an agent types itself. For the same reason `wire`
142
+ no longer writes the broad `Bash(myc:*)`: it allows myc's subcommands one by
143
+ one, and `run`, `statusline --then`, `wire` and `unwire` ask.
144
+
68
145
  ## What makes it different
69
146
 
70
147
  **Speed is a constraint, not an optimisation.** Every hot path has a budget
@@ -193,8 +270,12 @@ in git.** There is no server, no ACL and no team mode. Those are designed
193
270
  (`docs/design/03…`, `04…`, `05…`) and tracked, not implemented.
194
271
 
195
272
  Code intelligence is built in, and it is the same engine the alternatives use:
196
- tree-sitter, with grammars fetched on demand rather than shipped (all 36 weigh
197
- 49 MB against a 12 MB package). `myc code index` builds it — on this repository,
273
+ tree-sitter, with grammars fetched on demand rather than shipped. Symbols,
274
+ callers and code search work for TypeScript, TSX, JavaScript (js, jsx, mjs,
275
+ cjs) and Python — the languages myc has definition rules for. The grammar
276
+ package holds 36; a language is added as a pair, a rule and a catalog entry,
277
+ so a grammar that would yield no symbols is never offered. Every other file
278
+ still gets `code grep`, anchors and staleness. `myc code index` builds it — on this repository,
198
279
  826 files and 3 949 symbols in 904 ms — and four commands read it:
199
280
 
200
281
  ```
@@ -205,6 +286,34 @@ myc code grep "<lit>" exhaustive, every occurrence; --in <path> narrows it
205
286
  myc skeleton <file> the file's API — 26× cheaper than reading it
206
287
  ```
207
288
 
289
+ The file list is git's own (`git ls-files`, so `.gitignore` applies; a tree
290
+ without git is walked, and the command says so). On top of any list,
291
+ secret-named files are never indexed, whatever `.gitignore` says: `.env` and
292
+ `.env.*` (templates like `.env.example` are indexed), `*.pem`, `*.key`,
293
+ keystores, private SSH keys, `.npmrc`, `.netrc` and other credential files —
294
+ `code index` counts them without naming them, and `code grep` refuses to read one.
295
+
296
+ **Nested repositories and git worktrees.** A workspace can be an ecosystem: a
297
+ root that is a git repository with independent repositories inside it (not
298
+ submodules). It has one code index, built from the root — one row per file,
299
+ paths like `messaging-server/server/src/x.ts`. From inside a nested
300
+ repository every code command answers from that repository's part of the
301
+ root index, with paths relative to the repository you are in; from the root
302
+ the answers do not change. `myc code index` run inside a nested repository
303
+ refreshes its part of the root index instead of building a second copy of the
304
+ same files, and so does the background refresh. A git worktree — even one
305
+ outside the workspace tree — is answered from the index of the main checkout:
306
+ there is no index per branch. When the worktree is on another commit, or has
307
+ uncommitted changes to tracked files, every answer carries
308
+ `WARN code_index.worktree_divergent` naming both branches, because lines and
309
+ spans may not match your files. `code grep` reads the worktree's files (the
310
+ line numbers are yours, the owning symbols come from the index); `skeleton`
311
+ shows the main copy's declarations when your copy differs from what the index
312
+ saw, and says so. When nothing covers the repository, the hint is the command
313
+ for the workspace root (`myc -C <root> code index`), not one that would build a
314
+ duplicate. Anchors set from the root and from inside a repository are stored
315
+ under different keys; `code symbol` reads both.
316
+
208
317
  Anchors tie knowledge to a span and follow the code as it moves; that half is
209
318
  language-agnostic and was verified on Python as well as TypeScript.
210
319