@ionivetech/mugiwara 0.1.2 → 0.1.3
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 -18
- package/dist/mugiwara.js +9 -20
- package/package.json +3 -2
- package/src/args.ts +1 -1
- package/src/cli.ts +5 -15
- package/src/installer.ts +4 -6
- package/src/manifest.ts +0 -1
package/README.md
CHANGED
|
@@ -79,12 +79,12 @@ subagent machinery and may call the crew's shared skills.
|
|
|
79
79
|
| `mugiwara-resume` | Session resume: rebuild state from `.mugiwara/` after compaction/loss; never restart |
|
|
80
80
|
| `mugiwara-lessons` | Cross-mission memory: actionable lessons ledger, read at triage, written at closure |
|
|
81
81
|
|
|
82
|
-
###
|
|
82
|
+
### Every capability, always
|
|
83
83
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
84
|
+
Every install ships the full crew — all 21 skills and 15 agents, including
|
|
85
|
+
the anti-slop `mugiwara-frontend`, `mugiwara-backend`, and `mugiwara-agent-security`
|
|
86
|
+
skills. No project-type selection: you get every capability, and the harness
|
|
87
|
+
routes each task to the right skill.
|
|
88
88
|
|
|
89
89
|
## How it works
|
|
90
90
|
|
|
@@ -175,12 +175,12 @@ from source.
|
|
|
175
175
|
# npx — run without installing (recommended)
|
|
176
176
|
npx @ionivetech/mugiwara@latest
|
|
177
177
|
|
|
178
|
-
# interactive wizard (scope, target agent
|
|
179
|
-
# non-interactive: global Claude Code install,
|
|
180
|
-
npx @ionivetech/mugiwara@latest --global --target claude --
|
|
178
|
+
# interactive wizard (scope, target agent)
|
|
179
|
+
# non-interactive: global Claude Code install, no prompts
|
|
180
|
+
npx @ionivetech/mugiwara@latest --global --target claude --yes
|
|
181
181
|
|
|
182
|
-
# non-interactive: project install for opencode + GitHub Copilot
|
|
183
|
-
npx @ionivetech/mugiwara@latest --project ./my-app --target opencode,copilot --
|
|
182
|
+
# non-interactive: project install for opencode + GitHub Copilot
|
|
183
|
+
npx @ionivetech/mugiwara@latest --project ./my-app --target opencode,copilot --yes
|
|
184
184
|
```
|
|
185
185
|
|
|
186
186
|
### npm — global install
|
|
@@ -232,7 +232,7 @@ installable set.
|
|
|
232
232
|
## Quickstart
|
|
233
233
|
|
|
234
234
|
```console
|
|
235
|
-
$ npx @ionivetech/mugiwara@latest --global --target claude --
|
|
235
|
+
$ npx @ionivetech/mugiwara@latest --global --target claude --yes
|
|
236
236
|
mugiwara — installing crew for: claude
|
|
237
237
|
✓ claude 15 agents, 21 skills → ~/.claude/skills + ~/.claude/agents
|
|
238
238
|
✓ manifest wrote ~/.mugiwara/manifest.json
|
|
@@ -273,26 +273,25 @@ and review Brook's rollback note if a fix is risky.
|
|
|
273
273
|
| `--global` | Install user-wide (writes to your home directory) |
|
|
274
274
|
| `--project <dir>` | Install into a project directory (default: current directory) |
|
|
275
275
|
| `--target <ids\|all>` | Comma-separated target IDs, or `all`. Valid: `claude, opencode, copilot, gemini, codex, windsurf, cline, kilo, antigravity` |
|
|
276
|
-
| `--
|
|
277
|
-
| `--yes`, `-y` | Non-interactive. Requires `--global` or `--project`, `--target`, and `--type` |
|
|
276
|
+
| `--yes`, `-y` | Non-interactive. Requires `--global` or `--project`, and `--target` |
|
|
278
277
|
| `--force` | Overwrite files that differ (conflicting files are backed up first) |
|
|
279
278
|
| `--dry-run` | Print the actions without writing anything |
|
|
280
279
|
|
|
281
280
|
```bash
|
|
282
|
-
# non-interactive install requires
|
|
283
|
-
npx @ionivetech/mugiwara@latest --project ./app --target claude --
|
|
281
|
+
# non-interactive install requires scope + target, or it errors out
|
|
282
|
+
npx @ionivetech/mugiwara@latest --project ./app --target claude --yes
|
|
284
283
|
|
|
285
284
|
# preview what an install would write, without touching the disk
|
|
286
|
-
npx @ionivetech/mugiwara@latest --global --target all --
|
|
285
|
+
npx @ionivetech/mugiwara@latest --global --target all --yes --dry-run
|
|
287
286
|
|
|
288
287
|
# global installs skip targets that only support project scope (with a note)
|
|
289
|
-
npx @ionivetech/mugiwara@latest --global --target all --
|
|
288
|
+
npx @ionivetech/mugiwara@latest --global --target all --yes
|
|
290
289
|
```
|
|
291
290
|
|
|
292
291
|
### Install manifest
|
|
293
292
|
|
|
294
293
|
Every install writes `.mugiwara/manifest.json` (in the project dir, or `~` for
|
|
295
|
-
global). The manifest records the version, scope,
|
|
294
|
+
global). The manifest records the version, scope, targets, and the exact
|
|
296
295
|
list of written files — which is what `update` and `uninstall` use to operate
|
|
297
296
|
safely.
|
|
298
297
|
|
package/dist/mugiwara.js
CHANGED
|
@@ -7,7 +7,7 @@ import { join as join7, resolve } from "node:path";
|
|
|
7
7
|
import { pathToFileURL } from "node:url";
|
|
8
8
|
|
|
9
9
|
// src/args.ts
|
|
10
|
-
var VALUE_FLAGS = { "--project": "project", "--target": "target"
|
|
10
|
+
var VALUE_FLAGS = { "--project": "project", "--target": "target" };
|
|
11
11
|
var BOOL_FLAGS = {
|
|
12
12
|
"--global": "global",
|
|
13
13
|
"--yes": "yes",
|
|
@@ -296,8 +296,8 @@ import { homedir } from "node:os";
|
|
|
296
296
|
var CONTENT_DIR = join5(import.meta.dirname, "..", "content");
|
|
297
297
|
var pkg = JSON.parse(readFileSync(join5(import.meta.dirname, "..", "package.json"), "utf8"));
|
|
298
298
|
var VERSION = pkg.version;
|
|
299
|
-
function collectContent(
|
|
300
|
-
const skillNames = readdirSync(join5(CONTENT_DIR, "skills"), { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name)
|
|
299
|
+
function collectContent() {
|
|
300
|
+
const skillNames = readdirSync(join5(CONTENT_DIR, "skills"), { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name);
|
|
301
301
|
const skills = skillNames.map((name) => {
|
|
302
302
|
const { data, body } = parseFrontmatter(readFileSync(join5(CONTENT_DIR, "skills", name, "SKILL.md"), "utf8"));
|
|
303
303
|
return { name, data, body };
|
|
@@ -309,9 +309,9 @@ function collectContent({ includeFrontend }) {
|
|
|
309
309
|
return { skills, agents };
|
|
310
310
|
}
|
|
311
311
|
function installTo(target10, opts) {
|
|
312
|
-
const { scope, projectDir,
|
|
312
|
+
const { scope, projectDir, dryRun = false, force = false } = opts;
|
|
313
313
|
const home = opts.home ?? homedir();
|
|
314
|
-
const { skills, agents } = collectContent(
|
|
314
|
+
const { skills, agents } = collectContent();
|
|
315
315
|
const dirs = target10.paths({ scope, projectDir, home });
|
|
316
316
|
const backupRoot = join5(scope === "global" ? home : projectDir, ".mugiwara");
|
|
317
317
|
const result = { written: [], skipped: [], backedUp: [], notes: [] };
|
|
@@ -397,7 +397,6 @@ function writeManifest(file, data) {
|
|
|
397
397
|
}
|
|
398
398
|
|
|
399
399
|
// src/cli.ts
|
|
400
|
-
var TYPES = ["frontend", "backend", "fullstack", "general"];
|
|
401
400
|
var str = (v) => typeof v === "string" ? v : undefined;
|
|
402
401
|
var flag = (v) => v === true;
|
|
403
402
|
async function run(argv) {
|
|
@@ -449,22 +448,14 @@ async function resolveOptions(flags) {
|
|
|
449
448
|
if (!targets[id])
|
|
450
449
|
throw new Error(`Unknown target: ${id} (valid: ${TARGET_IDS.join(", ")}, all)`);
|
|
451
450
|
}
|
|
452
|
-
|
|
453
|
-
if (!type) {
|
|
454
|
-
if (!interactive)
|
|
455
|
-
throw new Error("Specify --type with --yes");
|
|
456
|
-
type = TYPES[await choose(rl, "Project type?", TYPES)];
|
|
457
|
-
}
|
|
458
|
-
if (!TYPES.includes(type))
|
|
459
|
-
throw new Error(`Unknown type: ${type} (valid: ${TYPES.join(", ")})`);
|
|
460
|
-
return { scope, projectDir, targetIds, type };
|
|
451
|
+
return { scope, projectDir, targetIds };
|
|
461
452
|
} finally {
|
|
462
453
|
if (rl)
|
|
463
454
|
rl.close();
|
|
464
455
|
}
|
|
465
456
|
}
|
|
466
457
|
async function install(flags) {
|
|
467
|
-
const { scope, projectDir, targetIds
|
|
458
|
+
const { scope, projectDir, targetIds } = await resolveOptions(flags);
|
|
468
459
|
const home = homedir2();
|
|
469
460
|
const allFiles = [];
|
|
470
461
|
const allNotes = [];
|
|
@@ -478,7 +469,7 @@ async function install(flags) {
|
|
|
478
469
|
installed.push(id);
|
|
479
470
|
console.log(`
|
|
480
471
|
-> ${t.label} (${scope})`);
|
|
481
|
-
const r = installTo(t, { scope, projectDir,
|
|
472
|
+
const r = installTo(t, { scope, projectDir, home, dryRun: flag(flags.dryRun), force: flag(flags.force) });
|
|
482
473
|
console.log(` written ${r.written.length}, skipped ${r.skipped.length}, backed up ${r.backedUp.length}`);
|
|
483
474
|
for (const n of r.notes)
|
|
484
475
|
console.log(` note: ${n}`);
|
|
@@ -495,7 +486,6 @@ Dry run — nothing written.`);
|
|
|
495
486
|
writeManifest(file, {
|
|
496
487
|
version: VERSION,
|
|
497
488
|
scope,
|
|
498
|
-
type,
|
|
499
489
|
installedAt: new Date().toISOString(),
|
|
500
490
|
targets: [...new Set([...prev?.targets ?? [], ...installed])],
|
|
501
491
|
files: [...new Set([...prev?.files ?? [], ...allFiles])]
|
|
@@ -579,8 +569,7 @@ Flags:
|
|
|
579
569
|
--global user-wide install
|
|
580
570
|
--project <dir> project install (default: cwd)
|
|
581
571
|
--target <ids|all> comma-separated: ${TARGET_IDS.join(", ")}
|
|
582
|
-
--
|
|
583
|
-
--yes, -y non-interactive (needs --global/--project, --target, --type)
|
|
572
|
+
--yes, -y non-interactive (needs --global/--project, --target)
|
|
584
573
|
--force overwrite differing files (with backup)
|
|
585
574
|
--dry-run print actions without writing`);
|
|
586
575
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ionivetech/mugiwara",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "The Straw Hat crew of AI agents and skills: brainstorm, plan, execute, checkpoint, quality, gates, review, security, self-healing. Installs into Claude Code, opencode, Copilot, Gemini, Codex, Windsurf, Cline, Kilo, Antigravity.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -26,7 +26,8 @@
|
|
|
26
26
|
"build": "bun build src/cli.ts --outfile dist/mugiwara.js --target node --format esm",
|
|
27
27
|
"validate": "bun scripts/validate-content.ts",
|
|
28
28
|
"evals": "bun scripts/run-evals.ts",
|
|
29
|
-
"
|
|
29
|
+
"sync-version": "bun scripts/sync-version.ts",
|
|
30
|
+
"prepack": "bun run build && bun run sync-version"
|
|
30
31
|
},
|
|
31
32
|
"keywords": [
|
|
32
33
|
"ai",
|
package/src/args.ts
CHANGED
|
@@ -6,7 +6,7 @@ export type Args = {
|
|
|
6
6
|
flags: Record<string, FlagValue>;
|
|
7
7
|
};
|
|
8
8
|
|
|
9
|
-
const VALUE_FLAGS: Record<string, string> = { '--project': 'project', '--target': 'target'
|
|
9
|
+
const VALUE_FLAGS: Record<string, string> = { '--project': 'project', '--target': 'target' };
|
|
10
10
|
const BOOL_FLAGS: Record<string, string> = {
|
|
11
11
|
'--global': 'global', '--yes': 'yes', '-y': 'yes', '--force': 'force',
|
|
12
12
|
'--dry-run': 'dryRun', '--help': 'help', '-h': 'help', '--version': 'version', '-v': 'version',
|
package/src/cli.ts
CHANGED
|
@@ -11,8 +11,6 @@ import { installTo, removeInstalled, VERSION, CONTENT_DIR } from './installer.ts
|
|
|
11
11
|
import { manifestPath, readManifest, writeManifest, type Scope } from './manifest.ts';
|
|
12
12
|
import { parseFrontmatter } from './frontmatter.ts';
|
|
13
13
|
|
|
14
|
-
const TYPES = ['frontend', 'backend', 'fullstack', 'general'];
|
|
15
|
-
|
|
16
14
|
const str = (v: FlagValue): string | undefined => (typeof v === 'string' ? v : undefined);
|
|
17
15
|
const flag = (v: FlagValue): boolean => v === true;
|
|
18
16
|
|
|
@@ -30,7 +28,7 @@ export async function run(argv: string[]): Promise<void> {
|
|
|
30
28
|
}
|
|
31
29
|
}
|
|
32
30
|
|
|
33
|
-
async function resolveOptions(flags: Args['flags']): Promise<{ scope: Scope; projectDir: string; targetIds: string[]
|
|
31
|
+
async function resolveOptions(flags: Args['flags']): Promise<{ scope: Scope; projectDir: string; targetIds: string[] }> {
|
|
34
32
|
const interactive = !flag(flags.yes);
|
|
35
33
|
const rl = interactive ? createRl() : null;
|
|
36
34
|
try {
|
|
@@ -53,20 +51,14 @@ async function resolveOptions(flags: Args['flags']): Promise<{ scope: Scope; pro
|
|
|
53
51
|
if (!targets[id]) throw new Error(`Unknown target: ${id} (valid: ${TARGET_IDS.join(', ')}, all)`);
|
|
54
52
|
}
|
|
55
53
|
|
|
56
|
-
|
|
57
|
-
if (!type) {
|
|
58
|
-
if (!interactive) throw new Error('Specify --type with --yes');
|
|
59
|
-
type = TYPES[await choose(rl!, 'Project type?', TYPES)];
|
|
60
|
-
}
|
|
61
|
-
if (!TYPES.includes(type)) throw new Error(`Unknown type: ${type} (valid: ${TYPES.join(', ')})`);
|
|
62
|
-
return { scope, projectDir, targetIds, type };
|
|
54
|
+
return { scope, projectDir, targetIds };
|
|
63
55
|
} finally {
|
|
64
56
|
if (rl) rl.close();
|
|
65
57
|
}
|
|
66
58
|
}
|
|
67
59
|
|
|
68
60
|
async function install(flags: Args['flags']): Promise<void> {
|
|
69
|
-
const { scope, projectDir, targetIds
|
|
61
|
+
const { scope, projectDir, targetIds } = await resolveOptions(flags);
|
|
70
62
|
const home = homedir();
|
|
71
63
|
const allFiles: string[] = [];
|
|
72
64
|
const allNotes: string[] = [];
|
|
@@ -79,7 +71,7 @@ async function install(flags: Args['flags']): Promise<void> {
|
|
|
79
71
|
}
|
|
80
72
|
installed.push(id);
|
|
81
73
|
console.log(`\n-> ${t.label} (${scope})`);
|
|
82
|
-
const r = installTo(t, { scope, projectDir,
|
|
74
|
+
const r = installTo(t, { scope, projectDir, home, dryRun: flag(flags.dryRun), force: flag(flags.force) });
|
|
83
75
|
console.log(` written ${r.written.length}, skipped ${r.skipped.length}, backed up ${r.backedUp.length}`);
|
|
84
76
|
for (const n of r.notes) console.log(` note: ${n}`);
|
|
85
77
|
allFiles.push(...r.written);
|
|
@@ -91,7 +83,6 @@ async function install(flags: Args['flags']): Promise<void> {
|
|
|
91
83
|
writeManifest(file, {
|
|
92
84
|
version: VERSION,
|
|
93
85
|
scope,
|
|
94
|
-
type,
|
|
95
86
|
installedAt: new Date().toISOString(),
|
|
96
87
|
targets: [...new Set([...(prev?.targets ?? []), ...installed])],
|
|
97
88
|
files: [...new Set([...(prev?.files ?? []), ...allFiles])],
|
|
@@ -164,8 +155,7 @@ Flags:
|
|
|
164
155
|
--global user-wide install
|
|
165
156
|
--project <dir> project install (default: cwd)
|
|
166
157
|
--target <ids|all> comma-separated: ${TARGET_IDS.join(', ')}
|
|
167
|
-
--
|
|
168
|
-
--yes, -y non-interactive (needs --global/--project, --target, --type)
|
|
158
|
+
--yes, -y non-interactive (needs --global/--project, --target)
|
|
169
159
|
--force overwrite differing files (with backup)
|
|
170
160
|
--dry-run print actions without writing`);
|
|
171
161
|
}
|
package/src/installer.ts
CHANGED
|
@@ -10,7 +10,6 @@ export type ContentItem = { name: string; data: FrontmatterData; body: string };
|
|
|
10
10
|
export type InstallOptions = {
|
|
11
11
|
scope: Scope;
|
|
12
12
|
projectDir: string;
|
|
13
|
-
type: string;
|
|
14
13
|
dryRun?: boolean;
|
|
15
14
|
force?: boolean;
|
|
16
15
|
home?: string;
|
|
@@ -39,10 +38,9 @@ export const CONTENT_DIR = join(import.meta.dirname, '..', 'content');
|
|
|
39
38
|
const pkg = JSON.parse(readFileSync(join(import.meta.dirname, '..', 'package.json'), 'utf8')) as { version: string };
|
|
40
39
|
export const VERSION = pkg.version;
|
|
41
40
|
|
|
42
|
-
export function collectContent(
|
|
41
|
+
export function collectContent(): { skills: ContentItem[]; agents: ContentItem[] } {
|
|
43
42
|
const skillNames = readdirSync(join(CONTENT_DIR, 'skills'), { withFileTypes: true })
|
|
44
|
-
.filter(e => e.isDirectory()).map(e => e.name)
|
|
45
|
-
.filter(name => includeFrontend || name !== 'mugiwara-frontend');
|
|
43
|
+
.filter(e => e.isDirectory()).map(e => e.name);
|
|
46
44
|
const skills = skillNames.map(name => {
|
|
47
45
|
const { data, body } = parseFrontmatter(readFileSync(join(CONTENT_DIR, 'skills', name, 'SKILL.md'), 'utf8'));
|
|
48
46
|
return { name, data, body };
|
|
@@ -57,9 +55,9 @@ export function collectContent({ includeFrontend }: { includeFrontend: boolean }
|
|
|
57
55
|
}
|
|
58
56
|
|
|
59
57
|
export function installTo(target: Target, opts: InstallOptions): InstallResult {
|
|
60
|
-
const { scope, projectDir,
|
|
58
|
+
const { scope, projectDir, dryRun = false, force = false } = opts;
|
|
61
59
|
const home = opts.home ?? homedir();
|
|
62
|
-
const { skills, agents } = collectContent(
|
|
60
|
+
const { skills, agents } = collectContent();
|
|
63
61
|
const dirs = target.paths({ scope, projectDir, home });
|
|
64
62
|
const backupRoot = join(scope === 'global' ? home : projectDir, '.mugiwara');
|
|
65
63
|
const result: InstallResult = { written: [], skipped: [], backedUp: [], notes: [] };
|