@roulabs/mx 1.11.0 → 2.1.0
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 +17 -10
- package/bin/mx.js +721 -130
- package/package.json +1 -1
- package/templates/CLAUDE.md +69 -18
- package/templates/repo/health.sh +23 -0
- package/templates/repo/hydrate.sh +28 -0
package/package.json
CHANGED
package/templates/CLAUDE.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<!-- Installed by the mx CLI. Don't hand-edit this file in the runtime —
|
|
2
|
-
edit templates/CLAUDE.md in the mx source repo and run `mx
|
|
2
|
+
edit templates/CLAUDE.md in the mx source repo and run `mx sync`. -->
|
|
3
3
|
|
|
4
4
|
# mx — multiplexed parallel work across repos
|
|
5
5
|
|
|
@@ -17,6 +17,15 @@ to read or change the work — its repos, branches, ports — you call an `mx` c
|
|
|
17
17
|
|
|
18
18
|
Every read command takes `--porcelain` for stable JSON; parse that instead of scraping text.
|
|
19
19
|
|
|
20
|
+
## Runtime version gate
|
|
21
|
+
|
|
22
|
+
This runtime carries a layout version in `<runtime>/mx.json` (an integer). The `mx` CLI supports exactly
|
|
23
|
+
one runtime version (CLI major ⇄ runtime version). If the CLI and runtime versions don't match, **every
|
|
24
|
+
runtime command refuses** with error `RUNTIME_VERSION_MISMATCH` — only `mx migrate`, `mx update`,
|
|
25
|
+
`mx help`, and `mx version` are allowed. If you hit that error, **stop and tell the user**: run
|
|
26
|
+
`mx migrate` to upgrade an older runtime, or `mx update` (then a new-major install) to upgrade the CLI for
|
|
27
|
+
a newer runtime. Don't try to work around the gate by editing files by hand.
|
|
28
|
+
|
|
20
29
|
## What this runtime is for
|
|
21
30
|
|
|
22
31
|
`mx/` is where **feature work** happens. Sessions launched here implement a feature inside a
|
|
@@ -41,26 +50,58 @@ Every read command takes `--porcelain` for stable JSON; parse that instead of sc
|
|
|
41
50
|
|
|
42
51
|
```
|
|
43
52
|
mx/
|
|
44
|
-
├── CLAUDE.md # this file (installed by the mx CLI)
|
|
45
53
|
├── .mx-root # empty marker: "this is the mx root"
|
|
54
|
+
├── mx.json # runtime config: { "version": 2 }
|
|
55
|
+
├── CLAUDE.md # this file (installed by the mx CLI)
|
|
46
56
|
├── context/ # shared memory across all features (see § Context registry)
|
|
47
57
|
│ ├── INDEX.json # single source of truth — metadata for every entry
|
|
48
58
|
│ └── <path>.md # body-only entries; nested folders allowed
|
|
49
|
-
├── repos
|
|
50
|
-
│ ├──
|
|
51
|
-
│
|
|
59
|
+
├── repos/<repo>/ # per-repo container
|
|
60
|
+
│ ├── git/ # the PRISTINE clone (read-only reference)
|
|
61
|
+
│ ├── hydrate.sh # runs after worktree add (customizable)
|
|
62
|
+
│ └── health.sh # augments `mx repo health` (customizable)
|
|
52
63
|
└── works/ # one folder per feature/work
|
|
53
64
|
└── feature-a/
|
|
54
65
|
├── work.json # manifest — owned by `mx`, do not hand-edit
|
|
55
|
-
├── feature-a.code-workspace
|
|
56
|
-
├──
|
|
57
|
-
├──
|
|
58
|
-
|
|
66
|
+
├── feature-a.code-workspace # owned by `mx` (folder paths point at wt/<repo>)
|
|
67
|
+
├── CLAUDE.md # work-specific rules — stamped once, then yours to edit (mx never overwrites)
|
|
68
|
+
├── .claude/settings.json # SessionStart hook → loads context/INDEX.json
|
|
69
|
+
├── wt/ # ALL worktrees live here
|
|
70
|
+
│ ├── repo-a/ # worktree of repo-a on this feature's branch
|
|
71
|
+
│ └── repo-b/ # worktree of repo-b on this feature's branch
|
|
72
|
+
├── scripts/ # ad-hoc per-work scripts
|
|
73
|
+
├── files/ # artifacts worth keeping (agent/user drop zone)
|
|
74
|
+
├── tmp/ # throwaway scratch — may be deleted at any time
|
|
75
|
+
└── sessions/ # session summaries (see § Session summaries)
|
|
59
76
|
```
|
|
60
77
|
|
|
61
|
-
- `repos/<repo
|
|
78
|
+
- `repos/<repo>/git` are **source-of-truth clones** — read-only reference. Worktrees fork from them
|
|
62
79
|
and share their `.git` object store. Never edit, commit, or run dev servers in `repos/`.
|
|
63
|
-
- `
|
|
80
|
+
- `repos/<repo>/hydrate.sh` and `repos/<repo>/health.sh` are mx-owned per-repo hooks you may customize:
|
|
81
|
+
`hydrate.sh` runs automatically after `mx work … worktree add <repo>` (cwd = the new worktree); `health.sh`
|
|
82
|
+
augments `mx repo health`. Edit their bodies if a repo needs custom worktree hydrate or health output.
|
|
83
|
+
- `works/<feature>/wt/<repo>` are **worktrees**, each on its own feature branch. All work happens here.
|
|
84
|
+
- `works/<feature>/CLAUDE.md` is **work-specific guidance** that loads alongside this runtime
|
|
85
|
+
`CLAUDE.md` for any session started in the work folder (Claude Code walks up from the session's cwd).
|
|
86
|
+
mx stamps it once (an explanatory comment, otherwise empty) and then **never touches it** — it's where
|
|
87
|
+
you and the user record rules specific to this work.
|
|
88
|
+
- `works/<feature>/{scripts,files,tmp}/` are the only places to put non-mx files in a work — see
|
|
89
|
+
§ The work folder holds mx-native files only.
|
|
90
|
+
|
|
91
|
+
## The work folder holds mx-native files only
|
|
92
|
+
|
|
93
|
+
**Never create ad-hoc files directly in the work-folder root.** The root is reserved for mx-native
|
|
94
|
+
files (`work.json`, the `.code-workspace`, the work `CLAUDE.md`, `.claude/`) and the mx-owned
|
|
95
|
+
subfolders. When you or the user need to write anything else, use one of these, never the root:
|
|
96
|
+
|
|
97
|
+
- **`files/`** — artifacts worth keeping: notes, exports, scratch docs, downloads you want to survive.
|
|
98
|
+
- **`tmp/`** — throwaway scratch. Its contents may be deleted at **any** time, with no guarantees —
|
|
99
|
+
never rely on anything here persisting.
|
|
100
|
+
- **`scripts/`** — ad-hoc scripts for this work.
|
|
101
|
+
|
|
102
|
+
The one exception: a runtime file a session legitimately needs to create at the work root for tooling
|
|
103
|
+
to work (e.g. an MCP connection file like `.<something>-mcp`) is fine. The rule targets *ad-hoc*
|
|
104
|
+
user/agent files — notes, downloads, temp outputs — not necessary tooling files.
|
|
64
105
|
|
|
65
106
|
## work.json (per-work manifest, owned by mx)
|
|
66
107
|
|
|
@@ -84,8 +125,10 @@ mx/
|
|
|
84
125
|
1. You are launched from a **work folder** (`works/<feature>/`), not a single repo. There is no "main repo."
|
|
85
126
|
2. Read the work's state with `mx work -n <feature> info --porcelain` to learn its repos, branches, and ports.
|
|
86
127
|
3. When you edit a repo's worktree, follow that repo's own `CLAUDE.md`, linters, and conventions —
|
|
87
|
-
its instructions live inside the worktree and apply.
|
|
88
|
-
|
|
128
|
+
its instructions live inside the worktree and apply. The work's own `CLAUDE.md` (at the work-folder
|
|
129
|
+
root) also loads for sessions started here — read it for rules specific to this work.
|
|
130
|
+
4. The work root is **not** a git repo. Run build/test/git commands from inside the relevant worktree
|
|
131
|
+
(`works/<feature>/wt/<repo>`).
|
|
89
132
|
5. If several sessions share one work, the user gives each a lane (usually one repo). Stay in your lane.
|
|
90
133
|
|
|
91
134
|
## Context registry — shared memory across every feature in this runtime
|
|
@@ -127,7 +170,7 @@ Example entry:
|
|
|
127
170
|
|
|
128
171
|
Primary path:
|
|
129
172
|
|
|
130
|
-
1. **Read `<runtime>/context/INDEX.json` on every task** — trivial or not, small or large. Skimming a metadata index is cheap; the cost of missing a relevant entry is high. This is a hard rule, not a heuristic.
|
|
173
|
+
1. **Read `<runtime>/context/INDEX.json` on every task** — trivial or not, small or large. Skimming a metadata index is cheap; the cost of missing a relevant entry is high. This is a hard rule, not a heuristic. (Each work also carries a `.claude/settings.json` `SessionStart` hook that prints this INDEX into the session at launch, so you usually start with it already in context — but re-read it when in doubt.)
|
|
131
174
|
2. Open files at `<runtime>/context/<path>.md` for entries whose metadata matches the current task.
|
|
132
175
|
|
|
133
176
|
When INDEX descriptions don't surface what you need — and often they won't — fall back to anything that works:
|
|
@@ -204,13 +247,16 @@ clarity; dropping it works while you're inside the work.
|
|
|
204
247
|
```
|
|
205
248
|
mx work -n <feature> worktree add <repo> [--branch <b>] [--base <ref>]
|
|
206
249
|
```
|
|
207
|
-
This creates the worktree from the pristine clone
|
|
208
|
-
workspace — all at once. Never run `git worktree add` yourself.
|
|
250
|
+
This creates the worktree from the pristine clone at `works/<feature>/wt/<repo>`, registers it in
|
|
251
|
+
`work.json`, and adds it to the workspace — all at once. Never run `git worktree add` yourself.
|
|
209
252
|
- `--branch <b>` is the **new** branch to create (defaults to the work name; if it already exists, it's reused).
|
|
210
253
|
- `--base <ref>` is where to **fork from** — any ref. A bare branch name (e.g. `main`,
|
|
211
254
|
`migration-to-mt-service-from-cf`) resolves to that local branch or, failing that, `origin/<name>`.
|
|
212
255
|
Run `mx repo -n <repo> fetch` first if you want the base at its latest upstream commit. Omit
|
|
213
256
|
`--base` to fork from the pristine clone's current HEAD.
|
|
257
|
+
- After the worktree is created, the repo's `repos/<repo>/hydrate.sh` runs automatically with the new
|
|
258
|
+
worktree as the working directory (copy a `.env`, install deps, etc.). Pass `--no-hydrate` to skip it,
|
|
259
|
+
or re-run it later with `mx work -n <feature> worktree hydrate <repo>`.
|
|
214
260
|
- **Allocate a port:** `mx work -n <feature> port set <repo> <service>` returns a free port (unique
|
|
215
261
|
across all works). This only records the port in `work.json` — **you** must then wire that port
|
|
216
262
|
into the repo's own env/config (`.env`, `PORT=`, etc.) and remap any outbound URL to a sibling
|
|
@@ -226,8 +272,13 @@ clarity; dropping it works while you're inside the work.
|
|
|
226
272
|
4. **Creating a worktree requires the user in the loop** — only when they explicitly tell you to in this session.
|
|
227
273
|
5. **Don't destroy anything unless asked.** Worktrees stay until the user confirms the feature is merged.
|
|
228
274
|
Teardown keeps feature branches; never delete them.
|
|
275
|
+
6. **Never create ad-hoc files in the work-folder root.** Keepable artifacts go in `files/`, throwaway
|
|
276
|
+
scratch in `tmp/`, scripts in `scripts/`. The root is mx-native only (only exception: a tooling
|
|
277
|
+
file a session genuinely needs there, e.g. an MCP connection file). See § The work folder holds
|
|
278
|
+
mx-native files only.
|
|
229
279
|
|
|
230
280
|
## The one rule that matters most
|
|
231
281
|
|
|
232
|
-
`repos/` is read-only reference; real work lives in worktrees under `works/<feature
|
|
233
|
-
owns the manifest. If a repo you need has no worktree yet, ask before adding one — then add it
|
|
282
|
+
`repos/` is read-only reference; real work lives in worktrees under `works/<feature>/wt/<repo>`; and
|
|
283
|
+
`mx` owns the manifest. If a repo you need has no worktree yet, ask before adding one — then add it
|
|
284
|
+
with `mx`.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
#
|
|
3
|
+
# mx per-repo health hook.
|
|
4
|
+
#
|
|
5
|
+
# `mx repo -n <repo> health` first runs mx's built-in structured checks (current
|
|
6
|
+
# vs default branch, uncommitted/untracked, ahead/behind origin, last fetched)
|
|
7
|
+
# and then runs this script, capturing its stdout as an extra section. Use it
|
|
8
|
+
# for repo-specific checks mx can't know about — e.g. node_modules present, a
|
|
9
|
+
# dev DB reachable, a required tool installed.
|
|
10
|
+
#
|
|
11
|
+
# Runs with the repo's git clone as the working directory. Context via env:
|
|
12
|
+
# MX_REPO repo name
|
|
13
|
+
# MX_REPO_PATH repo container (repos/<repo>)
|
|
14
|
+
# MX_GIT_DIR the git clone (repos/<repo>/git)
|
|
15
|
+
# MX_RUNTIME runtime root
|
|
16
|
+
#
|
|
17
|
+
# Whatever you echo appears under the health report. No output by default.
|
|
18
|
+
set -euo pipefail
|
|
19
|
+
|
|
20
|
+
# Example:
|
|
21
|
+
# [ -d node_modules ] && echo "node_modules: present" || echo "node_modules: MISSING"
|
|
22
|
+
|
|
23
|
+
exit 0
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
#
|
|
3
|
+
# mx per-worktree hydrate hook for this repo.
|
|
4
|
+
#
|
|
5
|
+
# Runs automatically after `mx work -n <work> worktree add <this repo>` creates
|
|
6
|
+
# a worktree (skip with --no-hydrate; re-run with `mx work -n <work> worktree
|
|
7
|
+
# hydrate <this repo>`). Customize it to make a fresh worktree runnable: copy a
|
|
8
|
+
# .env, allocate a port and write it into the worktree, install deps, etc.
|
|
9
|
+
#
|
|
10
|
+
# mx runs this with the new worktree as the working directory and passes context
|
|
11
|
+
# both as positional args and environment variables:
|
|
12
|
+
#
|
|
13
|
+
# $1 / $MX_WORKTREE_PATH absolute path to the new worktree
|
|
14
|
+
# $2 / $MX_BRANCH branch the worktree is on
|
|
15
|
+
# $MX_WORK work name
|
|
16
|
+
# $MX_REPO repo name
|
|
17
|
+
# $MX_BASE base ref it was forked from (may be empty)
|
|
18
|
+
# $MX_WORK_PATH absolute path to the work folder
|
|
19
|
+
# $MX_RUNTIME runtime root
|
|
20
|
+
#
|
|
21
|
+
# Ports stay mx-owned — allocate via mx, then wire the result in yourself, e.g.:
|
|
22
|
+
# port=$(mx work -n "$MX_WORK" port set "$MX_REPO" web --porcelain | jq -r .port)
|
|
23
|
+
# echo "PORT=$port" >> "$MX_WORKTREE_PATH/.env"
|
|
24
|
+
#
|
|
25
|
+
# A non-zero exit is reported as a warning and the worktree is kept.
|
|
26
|
+
set -euo pipefail
|
|
27
|
+
|
|
28
|
+
echo "Hydrate is done"
|