@curdx/flow 3.3.2 → 3.5.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/CHANGELOG.md +19 -0
- package/README.md +3 -0
- package/dist/index.mjs +61 -4
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,25 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to `@curdx/flow` are documented here. Format follows [Keep a Changelog](https://keepachangelog.com/) and the project follows [Semantic Versioning](https://semver.org/).
|
|
4
4
|
|
|
5
|
+
## 3.5.0 — 2026-04-27
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
|
|
9
|
+
- **`ralph-specum` is now a required bundled plugin** — it no longer appears as an optional checkbox in the install multiselect. Instead, it's listed in a dedicated "always installed" header above the prompt, alongside its current state (not installed / up-to-date / update available). When the flow runs, ralph-specum is auto-installed or auto-updated whenever it needs action; up-to-date installs are silently skipped. The other six items (pua, claude-mem, chrome-devtools-mcp, frontend-design, sequential-thinking, context7) remain optional. `--ids X` now also auto-includes required plugins that need action; users can still explicitly run `--ids ralph-specum` to force a reinstall confirmation. Uninstall flow is unchanged — users may still uninstall ralph-specum, and the next install will re-add it.
|
|
10
|
+
- **Internal:** `Pkg` type gains a `required?: boolean` field so future bundled plugins can opt into the same "always installed" semantics without touching install-flow code.
|
|
11
|
+
|
|
12
|
+
## 3.4.0 — 2026-04-27
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
- **`ralph-specum` is now a bundled plugin** — spec-driven development with autonomous task-by-task execution (research → requirements → design → tasks → implement, plus epic triage). Originally authored by [tzachbon](https://github.com/tzachbon/smart-ralph); ralph-specum v4.9.1 has been migrated into this repository as the canonical home and is no longer tracked against upstream. MIT license and authorship are preserved at `plugins/ralph-specum/LICENSE` and `plugins/ralph-specum/NOTICE.md`.
|
|
17
|
+
- **curdx-flow itself is now a Claude Code marketplace** — the repo ships `.claude-plugin/marketplace.json` so Claude CLI can install bundled plugins via `claude plugin marketplace add curdx/curdx-flow` + `claude plugin install ralph-specum@curdx-flow`. The flow installer wires this up automatically; users just run `npx @curdx/flow install` and ralph-specum is pre-checked in the multiselect along with the other not-installed items.
|
|
18
|
+
|
|
19
|
+
### Notes
|
|
20
|
+
|
|
21
|
+
- If you previously installed ralph-specum from the upstream `tzachbon/smart-ralph` marketplace, run `claude plugin uninstall ralph-specum@smart-ralph` before installing this version to avoid a name collision. Going forward, only the `ralph-specum@curdx-flow` build is maintained.
|
|
22
|
+
- Plugin files are not shipped in the npm tarball (`package.json` `files` is unchanged: `["dist", "CHANGELOG.md"]`). They live in the GitHub repo and are pulled by Claude CLI when the marketplace is added — so a `git push` of this repo must precede `npm publish` for a new release to be installable.
|
|
23
|
+
|
|
5
24
|
## 3.3.2 — 2026-04-27
|
|
6
25
|
|
|
7
26
|
### Fixed
|
package/README.md
CHANGED
|
@@ -31,9 +31,12 @@ npx @curdx/flow --lang en # override language
|
|
|
31
31
|
| `claude-mem` | plugin | `thedotmack/claude-mem` |
|
|
32
32
|
| `chrome-devtools-mcp` | plugin | `ChromeDevTools/chrome-devtools-mcp` |
|
|
33
33
|
| `frontend-design` | plugin | `claude-plugins-official` (built-in) |
|
|
34
|
+
| `ralph-specum` | plugin | bundled in this repo — spec-driven dev with autonomous task execution (originally [tzachbon/smart-ralph](https://github.com/tzachbon/smart-ralph), MIT) |
|
|
34
35
|
| `sequential-thinking` | mcp | `@modelcontextprotocol/server-sequential-thinking` |
|
|
35
36
|
| `context7` | mcp | HTTP — `https://mcp.context7.com/mcp` (optional API key) |
|
|
36
37
|
|
|
38
|
+
> If you previously installed ralph-specum from `tzachbon/smart-ralph`, run `claude plugin uninstall ralph-specum@smart-ralph` before installing this version. Only the `ralph-specum@curdx-flow` build is maintained going forward.
|
|
39
|
+
|
|
37
40
|
## What it writes to your filesystem
|
|
38
41
|
|
|
39
42
|
After every successful `install` / `update` / `uninstall`, flow keeps a short managed block in your global `~/.claude/CLAUDE.md` so Claude Code knows at session start which tools are installed and when to use them. The block looks like:
|
package/dist/index.mjs
CHANGED
|
@@ -30,6 +30,7 @@ var messages = {
|
|
|
30
30
|
"marketplace.refreshed": "\u5DF2\u5237\u65B0 {count} \u4E2A marketplace",
|
|
31
31
|
"marketplace.refreshSkipped": "marketplace \u7F13\u5B58\u4ECD\u662F\u65B0\u9C9C\u7684\uFF0C\u8DF3\u8FC7\u5237\u65B0",
|
|
32
32
|
"install.updating": '\u66F4\u65B0 "{name}" \u5230 v{version}',
|
|
33
|
+
"install.requiredHeader": "\u4EE5\u4E0B\u6761\u76EE\u968F @curdx/flow \u9ED8\u8BA4\u5B89\u88C5\uFF08\u4E0D\u53EF\u53D6\u6D88\uFF09",
|
|
33
34
|
"install.selectPrompt": "\u52FE\u9009\u8981\u5B89\u88C5 / \u91CD\u88C5\u7684\u6761\u76EE\uFF08\u9ED8\u8BA4\u52FE\u9009\u672A\u5B89\u88C5\u7684\uFF09",
|
|
34
35
|
"install.nothingSelected": "\u6CA1\u6709\u9009\u62E9\u4EFB\u4F55\u6761\u76EE\uFF0C\u5DF2\u9000\u51FA\u3002",
|
|
35
36
|
"install.confirmReinstall": '"{name}" \u5DF2\u5B89\u88C5\uFF0C\u662F\u5426\u91CD\u65B0\u5B89\u88C5\uFF08\u5148\u5378\u8F7D\u518D\u5B89\u88C5\uFF09\uFF1F',
|
|
@@ -101,6 +102,7 @@ var messages2 = {
|
|
|
101
102
|
"marketplace.refreshed": "Refreshed {count} marketplace(s)",
|
|
102
103
|
"marketplace.refreshSkipped": "Marketplace caches are fresh, skipping refresh",
|
|
103
104
|
"install.updating": 'Updating "{name}" to v{version}',
|
|
105
|
+
"install.requiredHeader": "Always installed by @curdx/flow (cannot be unchecked)",
|
|
104
106
|
"install.selectPrompt": "Select items to install / reinstall (not-installed are pre-selected)",
|
|
105
107
|
"install.nothingSelected": "Nothing selected. Exiting.",
|
|
106
108
|
"install.confirmReinstall": '"{name}" is already installed. Reinstall (uninstall then install)?',
|
|
@@ -518,6 +520,36 @@ var frontendDesign = {
|
|
|
518
520
|
};
|
|
519
521
|
var frontend_design_default = frontendDesign;
|
|
520
522
|
|
|
523
|
+
// src/registry/plugins/ralph-specum.ts
|
|
524
|
+
var PLUGIN_ID5 = "ralph-specum@curdx-flow";
|
|
525
|
+
var PLUGIN_NAME3 = "ralph-specum";
|
|
526
|
+
var MARKETPLACE_NAME4 = "curdx-flow";
|
|
527
|
+
var MARKETPLACE_SOURCE4 = "curdx/curdx-flow";
|
|
528
|
+
var ralphSpecum = {
|
|
529
|
+
id: "ralph-specum",
|
|
530
|
+
name: "ralph-specum",
|
|
531
|
+
description: "curdx-flow (originally tzachbon/smart-ralph) \u2014 spec-driven dev with autonomous task execution",
|
|
532
|
+
type: "plugin",
|
|
533
|
+
required: true,
|
|
534
|
+
slashNamespace: "/ralph-specum:*",
|
|
535
|
+
whenToUse: "for spec-driven multi-task work \u2014 research \u2192 requirements \u2192 design \u2192 tasks \u2192 autonomous execution per task. Use when starting a feature that benefits from upfront spec; skip for one-shot fixes or simple edits.",
|
|
536
|
+
marketplaces: () => [MARKETPLACE_NAME4],
|
|
537
|
+
isInstalled: () => isPluginInstalled(PLUGIN_ID5),
|
|
538
|
+
installedVersion: async () => {
|
|
539
|
+
const p10 = await findPlugin(PLUGIN_ID5);
|
|
540
|
+
const v = p10?.version;
|
|
541
|
+
return v && v !== "unknown" ? v : null;
|
|
542
|
+
},
|
|
543
|
+
latestVersion: () => getMarketplacePluginVersion(MARKETPLACE_NAME4, PLUGIN_NAME3),
|
|
544
|
+
install: async (ctx) => {
|
|
545
|
+
await ensureMarketplace(MARKETPLACE_NAME4, MARKETPLACE_SOURCE4, ctx);
|
|
546
|
+
await installPluginById(PLUGIN_ID5, ctx);
|
|
547
|
+
},
|
|
548
|
+
uninstall: (ctx) => uninstallPluginById(PLUGIN_ID5, ctx),
|
|
549
|
+
update: (ctx) => updatePluginById(PLUGIN_ID5, ctx)
|
|
550
|
+
};
|
|
551
|
+
var ralph_specum_default = ralphSpecum;
|
|
552
|
+
|
|
521
553
|
// src/registry/mcps/sequential-thinking.ts
|
|
522
554
|
var MCP_NAME = "sequential-thinking";
|
|
523
555
|
var sequentialThinking = {
|
|
@@ -615,6 +647,7 @@ var PKGS = [
|
|
|
615
647
|
claude_mem_default,
|
|
616
648
|
chrome_devtools_mcp_default,
|
|
617
649
|
frontend_design_default,
|
|
650
|
+
ralph_specum_default,
|
|
618
651
|
sequential_thinking_default,
|
|
619
652
|
context7_default
|
|
620
653
|
];
|
|
@@ -830,11 +863,17 @@ function stateLabel(pkg, s) {
|
|
|
830
863
|
}
|
|
831
864
|
}
|
|
832
865
|
async function selectInteractive(states) {
|
|
833
|
-
const
|
|
866
|
+
const requiredPkgs = PKGS.filter((pkg) => pkg.required);
|
|
867
|
+
const optionalPkgs = PKGS.filter((pkg) => !pkg.required);
|
|
868
|
+
if (requiredPkgs.length > 0) {
|
|
869
|
+
const lines = requiredPkgs.map((pkg) => ` ${stateLabel(pkg, states.get(pkg.id))}`);
|
|
870
|
+
p4.note(lines.join("\n"), t("install.requiredHeader"));
|
|
871
|
+
}
|
|
872
|
+
const options = optionalPkgs.map((pkg) => {
|
|
834
873
|
const s = states.get(pkg.id);
|
|
835
874
|
return { value: pkg.id, label: stateLabel(pkg, s), hint: pkg.description };
|
|
836
875
|
});
|
|
837
|
-
const initialValues =
|
|
876
|
+
const initialValues = optionalPkgs.filter((pkg) => {
|
|
838
877
|
const s = states.get(pkg.id);
|
|
839
878
|
return s.kind === "not_installed" || s.kind === "update_available";
|
|
840
879
|
}).map((pkg) => pkg.id);
|
|
@@ -845,7 +884,9 @@ async function selectInteractive(states) {
|
|
|
845
884
|
required: false
|
|
846
885
|
});
|
|
847
886
|
if (p4.isCancel(picked)) return null;
|
|
848
|
-
|
|
887
|
+
const userPicked = picked.map((id) => findPkg(id)).filter((x2) => Boolean(x2));
|
|
888
|
+
const requiredAuto = requiredPkgs.filter((pkg) => states.get(pkg.id)?.kind !== "up_to_date");
|
|
889
|
+
return [...requiredAuto, ...userPicked];
|
|
849
890
|
}
|
|
850
891
|
function selectFromIds(opts) {
|
|
851
892
|
if (opts.all) return [...PKGS];
|
|
@@ -961,6 +1002,13 @@ async function installFlow(opts = {}) {
|
|
|
961
1002
|
p4.log.info(t("install.nothingSelected"));
|
|
962
1003
|
return;
|
|
963
1004
|
}
|
|
1005
|
+
if (opts.ids && opts.ids.length > 0) {
|
|
1006
|
+
for (const pkg of PKGS) {
|
|
1007
|
+
if (pkg.required && !candidates.some((c) => c.id === pkg.id)) {
|
|
1008
|
+
candidates.push(pkg);
|
|
1009
|
+
}
|
|
1010
|
+
}
|
|
1011
|
+
}
|
|
964
1012
|
const stateMap = /* @__PURE__ */ new Map();
|
|
965
1013
|
const sp = p4.spinner();
|
|
966
1014
|
sp.start(t("state.checking"));
|
|
@@ -976,7 +1024,16 @@ async function installFlow(opts = {}) {
|
|
|
976
1024
|
}
|
|
977
1025
|
let targets;
|
|
978
1026
|
if (explicit) {
|
|
979
|
-
|
|
1027
|
+
if (opts.ids && opts.ids.length > 0) {
|
|
1028
|
+
const userListedIds = new Set(opts.ids);
|
|
1029
|
+
targets = candidates.filter((pkg) => {
|
|
1030
|
+
if (!pkg.required) return true;
|
|
1031
|
+
if (userListedIds.has(pkg.id)) return true;
|
|
1032
|
+
return stateMap.get(pkg.id)?.kind !== "up_to_date";
|
|
1033
|
+
});
|
|
1034
|
+
} else {
|
|
1035
|
+
targets = candidates;
|
|
1036
|
+
}
|
|
980
1037
|
} else {
|
|
981
1038
|
const picked = await selectInteractive(stateMap);
|
|
982
1039
|
if (picked === null) {
|