@shrkcrft/cli 0.1.0-alpha.8 → 0.1.0-alpha.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 +1 -1
- package/dist/commands/boundaries.command.d.ts.map +1 -1
- package/dist/commands/boundaries.command.js +12 -0
- package/dist/commands/check.command.d.ts.map +1 -1
- package/dist/commands/check.command.js +30 -20
- package/dist/commands/command-catalog.d.ts +3 -7
- package/dist/commands/command-catalog.d.ts.map +1 -1
- package/dist/commands/command-catalog.js +47 -113
- package/dist/commands/commands.command.d.ts.map +1 -1
- package/dist/commands/commands.command.js +4 -4
- package/dist/commands/constructs.command.d.ts.map +1 -1
- package/dist/commands/constructs.command.js +22 -5
- package/dist/commands/doctor.command.d.ts.map +1 -1
- package/dist/commands/doctor.command.js +9 -42
- package/dist/commands/export.command.d.ts.map +1 -1
- package/dist/commands/export.command.js +3 -76
- package/dist/commands/help.command.d.ts +3 -4
- package/dist/commands/help.command.d.ts.map +1 -1
- package/dist/commands/help.command.js +21 -77
- package/dist/commands/helper.command.js +1 -1
- package/dist/commands/import.command.d.ts.map +1 -1
- package/dist/commands/import.command.js +5 -121
- package/dist/commands/init.command.d.ts.map +1 -1
- package/dist/commands/init.command.js +16 -184
- package/dist/commands/mcp.command.d.ts.map +1 -1
- package/dist/commands/mcp.command.js +131 -2
- package/dist/commands/onboard.command.d.ts.map +1 -1
- package/dist/commands/onboard.command.js +15 -3
- package/dist/commands/packs-new.d.ts +1 -1
- package/dist/commands/packs-new.d.ts.map +1 -1
- package/dist/commands/packs-new.js +36 -5
- package/dist/commands/packs.command.d.ts.map +1 -1
- package/dist/commands/packs.command.js +17 -3
- package/dist/commands/plugin.command.d.ts +11 -0
- package/dist/commands/plugin.command.d.ts.map +1 -0
- package/dist/commands/plugin.command.js +394 -0
- package/dist/commands/profiles.command.js +4 -4
- package/dist/commands/release.command.js +13 -13
- package/dist/commands/review.command.d.ts.map +1 -1
- package/dist/commands/review.command.js +28 -2
- package/dist/commands/search.command.js +1 -1
- package/dist/commands/task-context.command.js +16 -0
- package/dist/export/export-formats.d.ts +1 -1
- package/dist/export/export-formats.d.ts.map +1 -1
- package/dist/export/export-formats.js +12 -139
- package/dist/init/init-templates.d.ts.map +1 -1
- package/dist/init/init-templates.js +113 -133
- package/dist/main.d.ts +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +46 -117
- package/dist/output/failure-hints.d.ts +9 -1
- package/dist/output/failure-hints.d.ts.map +1 -1
- package/dist/output/failure-hints.js +8 -2
- package/dist/output/watch-loop.d.ts +1 -9
- package/dist/output/watch-loop.d.ts.map +1 -1
- package/dist/output/watch-loop.js +3 -13
- package/dist/schemas/json-schemas.d.ts +36 -36
- package/dist/schemas/json-schemas.js +36 -36
- package/dist/surface/about.d.ts.map +1 -1
- package/dist/surface/about.js +15 -37
- package/dist/surface/no-args-landing.d.ts.map +1 -1
- package/dist/surface/no-args-landing.js +13 -9
- package/dist/surface/surface-config-writer.d.ts.map +1 -1
- package/dist/surface/surface-config-writer.js +11 -23
- package/package.json +25 -26
- package/dist/commands/diff-check.command.d.ts +0 -30
- package/dist/commands/diff-check.command.d.ts.map +0 -1
- package/dist/commands/diff-check.command.js +0 -210
- package/dist/export/claude-commands-export.d.ts +0 -60
- package/dist/export/claude-commands-export.d.ts.map +0 -1
- package/dist/export/claude-commands-export.js +0 -276
- package/dist/init/paths-advisory.d.ts +0 -20
- package/dist/init/paths-advisory.d.ts.map +0 -1
- package/dist/init/paths-advisory.js +0 -88
|
@@ -2,9 +2,8 @@ import { existsSync, mkdirSync, writeFileSync } from 'node:fs';
|
|
|
2
2
|
import { dirname, join } from 'node:path';
|
|
3
3
|
import { inspectSharkcraft } from '@shrkcrft/inspector';
|
|
4
4
|
import { ALL_EXPORT_FORMATS, isExportFormat, renderExport, } from "../export/export-formats.js";
|
|
5
|
-
import { buildClaudeCommands } from "../export/claude-commands-export.js";
|
|
6
5
|
import { flagBool, flagNumber, flagString, resolveCwd, } from "../command-registry.js";
|
|
7
|
-
import { asJson,
|
|
6
|
+
import { asJson, header } from "../output/format-output.js";
|
|
8
7
|
import { exportBundleCommand, exportSessionCommand, exportQualityCommand, exportReviewCommand, } from "./export-bundle.command.js";
|
|
9
8
|
const ARCHIVE_SUBCOMMANDS = {
|
|
10
9
|
bundle: exportBundleCommand,
|
|
@@ -14,7 +13,7 @@ const ARCHIVE_SUBCOMMANDS = {
|
|
|
14
13
|
};
|
|
15
14
|
export const exportCommand = {
|
|
16
15
|
name: 'export',
|
|
17
|
-
description: '
|
|
16
|
+
description: 'Render SharkCraft knowledge as a flat agent-rule file (AGENTS.md / CLAUDE.md / .cursor/rules / copilot-instructions). Dry-run by default; pass --write to save.',
|
|
18
17
|
usage: 'shrk [--cwd <dir>] export <format> [--write] [--output <path>] [--task "<task>"] [--max-rules N] [--max-paths N] [--json]',
|
|
19
18
|
async run(args) {
|
|
20
19
|
const format = args.positional[0];
|
|
@@ -28,13 +27,8 @@ export const exportCommand = {
|
|
|
28
27
|
const sub = { ...args, positional: args.positional.slice(1) };
|
|
29
28
|
return archive.run(sub);
|
|
30
29
|
}
|
|
31
|
-
// Multi-file `claude-commands` dispatches separately — it emits
|
|
32
|
-
// one .md per slash command, not a single rendered file.
|
|
33
|
-
if (format === 'claude-commands') {
|
|
34
|
-
return runClaudeCommandsExport(args);
|
|
35
|
-
}
|
|
36
30
|
if (!isExportFormat(format)) {
|
|
37
|
-
process.stderr.write(`Unknown export format "${format}".\nFormats: ${ALL_EXPORT_FORMATS.join(', ')},
|
|
31
|
+
process.stderr.write(`Unknown export format "${format}".\nFormats: ${ALL_EXPORT_FORMATS.join(', ')}, bundle, session, quality, review\n`);
|
|
38
32
|
return 2;
|
|
39
33
|
}
|
|
40
34
|
const cwd = resolveCwd(args);
|
|
@@ -87,70 +81,3 @@ export const exportCommand = {
|
|
|
87
81
|
return 0;
|
|
88
82
|
},
|
|
89
83
|
};
|
|
90
|
-
/**
|
|
91
|
-
* `shrk export claude-commands` — multi-file generator for Claude
|
|
92
|
-
* Code's native `.claude/commands/` slash-command primitive. Produces
|
|
93
|
-
* one .md per command (static + per-template).
|
|
94
|
-
*
|
|
95
|
-
* Unlike single-file exports (claude-skill / claude-md / etc.) this
|
|
96
|
-
* writes a SET of files. Each file is a complete recipe Claude Code
|
|
97
|
-
* loads when the user types the matching slash command.
|
|
98
|
-
*/
|
|
99
|
-
async function runClaudeCommandsExport(args) {
|
|
100
|
-
const cwd = resolveCwd(args);
|
|
101
|
-
const inspection = await inspectSharkcraft({ cwd });
|
|
102
|
-
const result = buildClaudeCommands(inspection);
|
|
103
|
-
const wantJson = flagBool(args, 'json');
|
|
104
|
-
const doWrite = flagBool(args, 'write');
|
|
105
|
-
const force = flagBool(args, 'force');
|
|
106
|
-
if (wantJson) {
|
|
107
|
-
process.stdout.write(asJson({
|
|
108
|
-
format: 'claude-commands',
|
|
109
|
-
write: doWrite,
|
|
110
|
-
files: result.files.map((f) => ({
|
|
111
|
-
path: f.path,
|
|
112
|
-
slash: f.slash,
|
|
113
|
-
source: f.source,
|
|
114
|
-
})),
|
|
115
|
-
}) + '\n');
|
|
116
|
-
return 0;
|
|
117
|
-
}
|
|
118
|
-
if (!doWrite) {
|
|
119
|
-
process.stdout.write(header('Export (claude-commands) — dry-run'));
|
|
120
|
-
process.stdout.write(`Would write ${result.files.length} command file(s):\n\n`);
|
|
121
|
-
for (const f of result.files) {
|
|
122
|
-
process.stdout.write(` ${f.path}\n`);
|
|
123
|
-
process.stdout.write(` → users type \`/${f.slash}\` in Claude Code (${f.source})\n`);
|
|
124
|
-
}
|
|
125
|
-
process.stdout.write('\nRe-run with --write to save.\n');
|
|
126
|
-
return 0;
|
|
127
|
-
}
|
|
128
|
-
const written = [];
|
|
129
|
-
const skipped = [];
|
|
130
|
-
for (const file of result.files) {
|
|
131
|
-
const fullPath = join(cwd, file.path);
|
|
132
|
-
mkdirSync(dirname(fullPath), { recursive: true });
|
|
133
|
-
if (existsSync(fullPath) && !force) {
|
|
134
|
-
skipped.push(file.path);
|
|
135
|
-
continue;
|
|
136
|
-
}
|
|
137
|
-
writeFileSync(fullPath, file.content, 'utf8');
|
|
138
|
-
written.push(file.path);
|
|
139
|
-
}
|
|
140
|
-
process.stdout.write(header('Claude commands exported'));
|
|
141
|
-
if (written.length) {
|
|
142
|
-
process.stdout.write(`Wrote ${written.length} command file(s):\n`);
|
|
143
|
-
for (const p of written) {
|
|
144
|
-
const f = result.files.find((x) => x.path === p);
|
|
145
|
-
process.stdout.write(bullet(`${p} → \`/${f.slash}\``) + '\n');
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
if (skipped.length) {
|
|
149
|
-
process.stdout.write(`\nSkipped ${skipped.length} (already exist; use --force to overwrite):\n`);
|
|
150
|
-
for (const p of skipped)
|
|
151
|
-
process.stdout.write(bullet(p) + '\n');
|
|
152
|
-
}
|
|
153
|
-
process.stdout.write('\nClaude Code picks up `.claude/commands/*.md` automatically. ' +
|
|
154
|
-
'Open the project in Claude Code, type `/` — the slash commands are in the palette.\n');
|
|
155
|
-
return 0;
|
|
156
|
-
}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import type { CommandRegistry } from '../command-registry.js';
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* via `shrk --full-help` or browse it through `shrk surface list`.
|
|
3
|
+
* Short product start screen for bare `shrk` / `shrk --help`. Pruned
|
|
4
|
+
* to the core tier set; extended verbs live one link away via
|
|
5
|
+
* `shrk surface list`.
|
|
7
6
|
*
|
|
8
7
|
* Returns the lines (without trailing newline). Pulled into a function
|
|
9
8
|
* so tests can assert on the structure without grepping stdout.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"help.command.d.ts","sourceRoot":"","sources":["../../src/commands/help.command.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"help.command.d.ts","sourceRoot":"","sources":["../../src/commands/help.command.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAG9D;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAyB1C;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,eAAe;;;;cAK3C;QAAE,UAAU,EAAE,MAAM,EAAE,CAAC;QAAC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,CAAA;KAAE,GAAG,MAAM;EA2FpF"}
|
|
@@ -1,59 +1,33 @@
|
|
|
1
1
|
import { header } from "../output/format-output.js";
|
|
2
|
-
import { COMMAND_CATALOG, defaultShowInHelp } from "./command-catalog.js";
|
|
3
2
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* via `shrk --full-help` or browse it through `shrk surface list`.
|
|
3
|
+
* Short product start screen for bare `shrk` / `shrk --help`. Pruned
|
|
4
|
+
* to the core tier set; extended verbs live one link away via
|
|
5
|
+
* `shrk surface list`.
|
|
8
6
|
*
|
|
9
7
|
* Returns the lines (without trailing newline). Pulled into a function
|
|
10
8
|
* so tests can assert on the structure without grepping stdout.
|
|
11
9
|
*/
|
|
12
10
|
export function renderStartScreen() {
|
|
13
11
|
const lines = [];
|
|
14
|
-
lines.push('SharkCraft CLI —
|
|
12
|
+
lines.push('SharkCraft CLI — the safety layer beneath your AI coding agent.');
|
|
15
13
|
lines.push('Usage: shrk [--cwd <dir>] <command> [...args]');
|
|
16
14
|
lines.push('');
|
|
17
|
-
lines.push('
|
|
18
|
-
lines.push(' $ shrk
|
|
19
|
-
lines.push(' $ shrk
|
|
20
|
-
lines.push(' $ shrk
|
|
21
|
-
lines.push(' $ shrk init — scaffold sharkcraft/ + config skeleton (preset defaults)');
|
|
22
|
-
lines.push(' $ shrk doctor — is the workspace healthy?');
|
|
23
|
-
lines.push(' $ shrk inspect — detect frameworks, paths, package manager');
|
|
24
|
-
lines.push(' $ shrk onboard — analyze an existing repo (advisory)');
|
|
25
|
-
lines.push('');
|
|
26
|
-
lines.push('Use it for a task:');
|
|
27
|
-
lines.push(' $ shrk brief — single-page brief Claude reads first (project + rules + paths + verification)');
|
|
28
|
-
lines.push(' $ shrk recommend "<task>" — what should I do?');
|
|
29
|
-
lines.push(' $ shrk context --task "<task>" — token-budgeted relevant context');
|
|
30
|
-
lines.push(' $ shrk task "<task>" — full AI-ready task packet (JSON)');
|
|
31
|
-
lines.push(' $ shrk coverage — what knowledge is missing');
|
|
32
|
-
lines.push('');
|
|
33
|
-
lines.push('Generate code safely:');
|
|
34
|
-
lines.push(' $ shrk gen <template> <name> — generate from template (dry-run by default)');
|
|
35
|
-
lines.push(' $ shrk apply <plan.json> — apply a reviewed plan (CLI is the only write path)');
|
|
36
|
-
lines.push(' $ shrk check boundaries — enforce layer / import boundaries');
|
|
37
|
-
lines.push(' $ shrk quality — pre-PR gate (doctor + boundaries + coverage + drift)');
|
|
15
|
+
lines.push('Prove it in 60 seconds:');
|
|
16
|
+
lines.push(' $ shrk check boundaries --changed-only --since main');
|
|
17
|
+
lines.push(' $ shrk review packet --v3 --since main');
|
|
18
|
+
lines.push(' $ shrk mcp install claude-code — copy-paste the MCP entry');
|
|
38
19
|
lines.push('');
|
|
39
|
-
lines.push('
|
|
40
|
-
lines.push(' $ shrk
|
|
41
|
-
lines.push(' $ shrk
|
|
42
|
-
lines.push(' $ shrk
|
|
43
|
-
lines.push(' $ shrk
|
|
44
|
-
lines.push(' $ shrk export — render to a flat agent-rule file');
|
|
45
|
-
lines.push('');
|
|
46
|
-
lines.push('Run shrk for an agent:');
|
|
47
|
-
lines.push(' $ shrk export claude-skill --write — generate .claude/skills/<name>/SKILL.md (rules INTO the prompt — no MCP roundtrip)');
|
|
48
|
-
lines.push(' $ shrk export agents-md --write — generate AGENTS.md / CLAUDE.md / .cursor/rules / copilot-instructions');
|
|
49
|
-
lines.push(' $ shrk mcp serve — start the MCP server (stdio) for live queries');
|
|
50
|
-
lines.push(' $ shrk dashboard — start the local read-only dashboard');
|
|
20
|
+
lines.push('Core (always on):');
|
|
21
|
+
lines.push(' $ shrk doctor — is the workspace healthy?');
|
|
22
|
+
lines.push(' $ shrk recommend "<task>" — what command should I reach for?');
|
|
23
|
+
lines.push(' $ shrk init — create sharkcraft/ + config skeleton');
|
|
24
|
+
lines.push(' $ shrk surface list — every command grouped by tier');
|
|
51
25
|
lines.push('');
|
|
52
|
-
lines.push('Discover the rest (
|
|
53
|
-
lines.push(' $ shrk surface list — full
|
|
54
|
-
lines.push(' $ shrk surface
|
|
26
|
+
lines.push('Discover the rest (extended tier — always callable):');
|
|
27
|
+
lines.push(' $ shrk surface list — full surface, grouped by tier and profile');
|
|
28
|
+
lines.push(' $ shrk surface explain <cmd> — why a command has its current tier');
|
|
55
29
|
lines.push(' $ shrk help <command> — usage for a specific command');
|
|
56
|
-
lines.push(' $ shrk --full-help — long, exhaustive help');
|
|
30
|
+
lines.push(' $ shrk --full-help — the long, exhaustive help');
|
|
57
31
|
lines.push(' $ shrk --about — what shrk is and is not');
|
|
58
32
|
lines.push('');
|
|
59
33
|
lines.push('Free-form input is fine — `shrk "<task>"` routes to `shrk recommend`.');
|
|
@@ -117,41 +91,13 @@ export function makeHelpCommand(registry) {
|
|
|
117
91
|
process.stdout.write(renderStartScreen());
|
|
118
92
|
return 0;
|
|
119
93
|
}
|
|
120
|
-
|
|
121
|
-
process.stdout.write(`SharkCraft CLI — structured project intelligence for AI coding agents\n`);
|
|
94
|
+
process.stdout.write(`SharkCraft CLI — the safety layer beneath your AI coding agent.\n`);
|
|
122
95
|
process.stdout.write(`Usage: shrk [--cwd <dir>] <command> [...args]\n`);
|
|
123
|
-
// The catalog has ~360 entries; only ~30 top-level verbs pay
|
|
124
|
-
// rent (see PRIMARY_VERBS_ALLOWLIST in command-catalog.ts).
|
|
125
|
-
// Default --full-help filters to that set; `--full-help --all`
|
|
126
|
-
// dumps the entire catalog for power users.
|
|
127
|
-
const visibleVerbs = new Set();
|
|
128
|
-
if (!wantsAll) {
|
|
129
|
-
for (const entry of COMMAND_CATALOG) {
|
|
130
|
-
if (defaultShowInHelp(entry)) {
|
|
131
|
-
const verb = entry.command.split(/\s+/)[0] ?? '';
|
|
132
|
-
if (verb)
|
|
133
|
-
visibleVerbs.add(verb);
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
const visibleTopLevel = registry.list().filter((c) => {
|
|
138
|
-
if (wantsAll)
|
|
139
|
-
return true;
|
|
140
|
-
return visibleVerbs.has(c.name);
|
|
141
|
-
});
|
|
142
96
|
process.stdout.write(header('Top-level commands'));
|
|
143
|
-
for (const c of
|
|
97
|
+
for (const c of registry.list()) {
|
|
144
98
|
process.stdout.write(` ${c.name.padEnd(10)} — ${c.description}\n`);
|
|
145
99
|
}
|
|
146
|
-
|
|
147
|
-
const hiddenCount = registry.list().length - visibleTopLevel.length;
|
|
148
|
-
if (hiddenCount > 0) {
|
|
149
|
-
process.stdout.write(`\n …and ${hiddenCount} more, hidden from default help. Run \`shrk --full-help --all\` to see them, ` +
|
|
150
|
-
`or \`shrk surface list\` to browse by tier.\n`);
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
// Show each canonical group once — also filtered by the allowlist
|
|
154
|
-
// unless --all was passed.
|
|
100
|
+
// Show each canonical group once.
|
|
155
101
|
const canonicalGroups = [];
|
|
156
102
|
const aliasMap = registry.listGroupAliases();
|
|
157
103
|
const seen = new Set();
|
|
@@ -159,9 +105,7 @@ export function makeHelpCommand(registry) {
|
|
|
159
105
|
const canonical = aliasMap.get(g) ?? g;
|
|
160
106
|
if (!seen.has(canonical)) {
|
|
161
107
|
seen.add(canonical);
|
|
162
|
-
|
|
163
|
-
canonicalGroups.push(canonical);
|
|
164
|
-
}
|
|
108
|
+
canonicalGroups.push(canonical);
|
|
165
109
|
}
|
|
166
110
|
}
|
|
167
111
|
const aliasesByCanonical = new Map();
|
|
@@ -85,7 +85,7 @@ export const helperPlanCommand = {
|
|
|
85
85
|
// profile is available. Today the helper-registry detects this inside
|
|
86
86
|
// buildHelperPlan via requireProfile(); we surface a friendly message.
|
|
87
87
|
if ('requiresProfile' in def && def.requiresProfile) {
|
|
88
|
-
process.stderr.write(`Helper "${id}" requires a
|
|
88
|
+
process.stderr.write(`Helper "${id}" requires a plugin-lifecycle profile. Available:\n $ shrk plugin lifecycle profiles\n`);
|
|
89
89
|
// Still try to build the plan; the registry throws with the same idea.
|
|
90
90
|
}
|
|
91
91
|
const cwd = resolveCwd(args);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"import.command.d.ts","sourceRoot":"","sources":["../../src/commands/import.command.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"import.command.d.ts","sourceRoot":"","sources":["../../src/commands/import.command.ts"],"names":[],"mappings":"AASA,OAAO,EAKL,KAAK,eAAe,EAErB,MAAM,wBAAwB,CAAC;AAyBhC,eAAO,MAAM,aAAa,EAAE,eA8G3B,CAAC"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { existsSync, mkdirSync,
|
|
1
|
+
import { existsSync, mkdirSync, writeFileSync } from 'node:fs';
|
|
2
2
|
import * as nodePath from 'node:path';
|
|
3
|
-
import { emitKnowledgeTs, importAgentsMd, importClaudeMd, importCursorRules,
|
|
3
|
+
import { emitKnowledgeTs, importAgentsMd, importClaudeMd, importCursorRules, } from '@shrkcrft/importer';
|
|
4
4
|
import { flagBool, flagString, flagList, resolveCwd, } from "../command-registry.js";
|
|
5
|
-
import { asJson,
|
|
5
|
+
import { asJson, header, kv } from "../output/format-output.js";
|
|
6
6
|
function repeatedFlagList(args, name) {
|
|
7
7
|
return flagList(args, name, { dedupe: true });
|
|
8
8
|
}
|
|
@@ -22,8 +22,8 @@ function defaultOutput(format) {
|
|
|
22
22
|
}
|
|
23
23
|
export const importCommand = {
|
|
24
24
|
name: 'import',
|
|
25
|
-
description: 'Parse existing agent rule files (AGENTS.md / CLAUDE.md / .cursor/rules) into
|
|
26
|
-
usage: 'shrk [--cwd <dir>] import <format> [<path>] [--prefix <id>] [--tag <t>] [--scope <s>] [--output <file>] [--write] [--
|
|
25
|
+
description: 'Parse existing agent rule files (AGENTS.md / CLAUDE.md / .cursor/rules) into a structured @shrkcrft/knowledge TypeScript draft. Dry-run by default; --write saves the draft to sharkcraft/imports/.',
|
|
26
|
+
usage: 'shrk [--cwd <dir>] import <format> [<path>] [--prefix <id>] [--tag <t>] [--scope <s>] [--output <file>] [--write] [--force] [--json]',
|
|
27
27
|
async run(args) {
|
|
28
28
|
const format = args.positional[0];
|
|
29
29
|
if (!format || !KNOWN_FORMATS.includes(format)) {
|
|
@@ -57,24 +57,9 @@ export const importCommand = {
|
|
|
57
57
|
}
|
|
58
58
|
const outPath = nodePath.resolve(cwd, flagString(args, 'output') ?? flagString(args, 'out') ?? defaultOutput(fmt));
|
|
59
59
|
const write = flagBool(args, 'write');
|
|
60
|
-
const populate = flagBool(args, 'populate');
|
|
61
60
|
const tsSource = emitKnowledgeTs(result.entries, {
|
|
62
61
|
sourceLabel: `${fmt} (${result.sourceFiles.join(', ') || path})`,
|
|
63
62
|
});
|
|
64
|
-
// ── `--populate` path: distribute entries into populated
|
|
65
|
-
// sharkcraft/* files (rules.ts / paths.ts / knowledge.ts) with
|
|
66
|
-
// confidence triage. Mirrors `shrk init --infer`'s contract.
|
|
67
|
-
if (populate) {
|
|
68
|
-
return runPopulateImport({
|
|
69
|
-
cwd,
|
|
70
|
-
fmt,
|
|
71
|
-
path,
|
|
72
|
-
result,
|
|
73
|
-
write,
|
|
74
|
-
force: flagBool(args, 'force'),
|
|
75
|
-
wantJson: flagBool(args, 'json'),
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
63
|
if (flagBool(args, 'json')) {
|
|
79
64
|
process.stdout.write(asJson({
|
|
80
65
|
format: fmt,
|
|
@@ -128,104 +113,3 @@ export const importCommand = {
|
|
|
128
113
|
return 0;
|
|
129
114
|
},
|
|
130
115
|
};
|
|
131
|
-
/**
|
|
132
|
-
* `shrk import <format> --populate` path. Routes parsed entries
|
|
133
|
-
* into populated `sharkcraft/*.ts` files by KnowledgeType, with
|
|
134
|
-
* confidence triage and a companion `.imported-report.md`. Same
|
|
135
|
-
* shape as `shrk init --infer`.
|
|
136
|
-
*/
|
|
137
|
-
function runPopulateImport(args) {
|
|
138
|
-
const { cwd, fmt, path, result, write, force, wantJson } = args;
|
|
139
|
-
const sharkcraftDir = nodePath.join(cwd, 'sharkcraft');
|
|
140
|
-
const projectName = readProjectName(cwd) ?? 'project';
|
|
141
|
-
const description = `Imported from ${fmt} (${path})`;
|
|
142
|
-
const populated = synthesizePopulatedFromImport(result.entries, {
|
|
143
|
-
projectName,
|
|
144
|
-
description,
|
|
145
|
-
sourceLabel: `${fmt} (${result.sourceFiles.join(', ') || path})`,
|
|
146
|
-
});
|
|
147
|
-
if (wantJson) {
|
|
148
|
-
process.stdout.write(asJson({
|
|
149
|
-
format: fmt,
|
|
150
|
-
source: path,
|
|
151
|
-
mode: write ? 'populate' : 'populate-dry-run',
|
|
152
|
-
sharkcraftDir,
|
|
153
|
-
entryCount: result.entries.length,
|
|
154
|
-
warnings: result.warnings,
|
|
155
|
-
files: populated.files.map((f) => ({ path: f.path, kind: f.kind })),
|
|
156
|
-
report: populated.report,
|
|
157
|
-
}) + '\n');
|
|
158
|
-
return 0;
|
|
159
|
-
}
|
|
160
|
-
process.stdout.write(header(`Import (${fmt}) — populate`));
|
|
161
|
-
process.stdout.write(kv('source', path) + '\n');
|
|
162
|
-
process.stdout.write(kv('files read', String(result.sourceFiles.length)) + '\n');
|
|
163
|
-
process.stdout.write(kv('entries parsed', String(result.entries.length)) + '\n');
|
|
164
|
-
process.stdout.write(kv('target', sharkcraftDir) + '\n');
|
|
165
|
-
process.stdout.write(kv('mode', write ? 'write' : 'dry-run (preview only)') + '\n\n');
|
|
166
|
-
process.stdout.write(`Triage: ${populated.report.adoptedHigh.length} adopted directly · ` +
|
|
167
|
-
`${populated.report.adoptedMedium.length} marked for review · ` +
|
|
168
|
-
`${populated.report.dropped.length} dropped (in report).\n\n`);
|
|
169
|
-
if (result.warnings.length > 0) {
|
|
170
|
-
process.stdout.write(header('Parser warnings'));
|
|
171
|
-
for (const w of result.warnings) {
|
|
172
|
-
process.stdout.write(` ${w.origin}: ${w.message}\n`);
|
|
173
|
-
}
|
|
174
|
-
process.stdout.write('\n');
|
|
175
|
-
}
|
|
176
|
-
if (!write) {
|
|
177
|
-
process.stdout.write('Would write:\n');
|
|
178
|
-
for (const f of populated.files)
|
|
179
|
-
process.stdout.write(bullet(f.path) + '\n');
|
|
180
|
-
process.stdout.write('\nRe-run with --write to persist.\n');
|
|
181
|
-
return 0;
|
|
182
|
-
}
|
|
183
|
-
const written = [];
|
|
184
|
-
const skipped = [];
|
|
185
|
-
for (const file of populated.files) {
|
|
186
|
-
const fullPath = nodePath.join(sharkcraftDir, file.path);
|
|
187
|
-
mkdirSync(nodePath.dirname(fullPath), { recursive: true });
|
|
188
|
-
if (existsSync(fullPath) && !force) {
|
|
189
|
-
skipped.push(file.path);
|
|
190
|
-
continue;
|
|
191
|
-
}
|
|
192
|
-
writeFileSync(fullPath, file.content, 'utf8');
|
|
193
|
-
written.push(file.path);
|
|
194
|
-
}
|
|
195
|
-
if (written.length) {
|
|
196
|
-
process.stdout.write('Wrote:\n');
|
|
197
|
-
for (const p of written)
|
|
198
|
-
process.stdout.write(bullet(p) + '\n');
|
|
199
|
-
}
|
|
200
|
-
if (skipped.length) {
|
|
201
|
-
process.stdout.write('\nSkipped (already exist; use --force to overwrite):\n');
|
|
202
|
-
for (const p of skipped)
|
|
203
|
-
process.stdout.write(bullet(p) + '\n');
|
|
204
|
-
}
|
|
205
|
-
process.stdout.write(`\nRead the import report: \`${nodePath.join('sharkcraft', '.imported-report.md')}\`\n` +
|
|
206
|
-
`It lists what was adopted high-confidence, what's marked for your review, ` +
|
|
207
|
-
`and what \`shrk import\` deliberately doesn't recover from markdown.\n`);
|
|
208
|
-
process.stdout.write('\nNext:\n');
|
|
209
|
-
process.stdout.write(bullet('$ shrk doctor — verify the populated setup') + '\n');
|
|
210
|
-
process.stdout.write(bullet('$ shrk brief — single-page brief Claude reads first') + '\n');
|
|
211
|
-
process.stdout.write(bullet('$ shrk export claude-skill --write — inline the rules into Claude\'s prompt') + '\n');
|
|
212
|
-
return 0;
|
|
213
|
-
}
|
|
214
|
-
/**
|
|
215
|
-
* Best-effort read of `package.json#name` for use as `projectName`
|
|
216
|
-
* in the generated config. Falls back to undefined; the synthesizer
|
|
217
|
-
* uses 'project' as a default.
|
|
218
|
-
*/
|
|
219
|
-
function readProjectName(cwd) {
|
|
220
|
-
const pkgPath = nodePath.join(cwd, 'package.json');
|
|
221
|
-
try {
|
|
222
|
-
if (!existsSync(pkgPath))
|
|
223
|
-
return undefined;
|
|
224
|
-
const raw = readFileSync(pkgPath, 'utf8');
|
|
225
|
-
const parsed = JSON.parse(raw);
|
|
226
|
-
return parsed.name ?? undefined;
|
|
227
|
-
}
|
|
228
|
-
catch {
|
|
229
|
-
return undefined;
|
|
230
|
-
}
|
|
231
|
-
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.command.d.ts","sourceRoot":"","sources":["../../src/commands/init.command.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"init.command.d.ts","sourceRoot":"","sources":["../../src/commands/init.command.ts"],"names":[],"mappings":"AAeA,OAAO,EAAwB,KAAK,eAAe,EAA+B,MAAM,wBAAwB,CAAC;AA4QjH,eAAO,MAAM,WAAW,EAAE,eA2FzB,CAAC"}
|