@skilly-hand/skilly-hand 0.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.
Files changed (34) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/LICENSE +23 -0
  3. package/README.md +107 -0
  4. package/catalog/README.md +30 -0
  5. package/catalog/catalog-index.json +6 -0
  6. package/catalog/skills/agents-root-orchestrator/SKILL.md +135 -0
  7. package/catalog/skills/agents-root-orchestrator/assets/AGENTS-ROOT-TEMPLATE.md +67 -0
  8. package/catalog/skills/agents-root-orchestrator/manifest.json +34 -0
  9. package/catalog/skills/skill-creator/SKILL.md +176 -0
  10. package/catalog/skills/skill-creator/assets/SKILL-TEMPLATE.md +94 -0
  11. package/catalog/skills/skill-creator/manifest.json +36 -0
  12. package/catalog/skills/spec-driven-development/SKILL.md +168 -0
  13. package/catalog/skills/spec-driven-development/agents/apply.md +26 -0
  14. package/catalog/skills/spec-driven-development/agents/orchestrate.md +25 -0
  15. package/catalog/skills/spec-driven-development/agents/plan.md +27 -0
  16. package/catalog/skills/spec-driven-development/agents/verify.md +24 -0
  17. package/catalog/skills/spec-driven-development/assets/delta-spec-template.md +51 -0
  18. package/catalog/skills/spec-driven-development/assets/design-template.md +31 -0
  19. package/catalog/skills/spec-driven-development/assets/spec-template.md +56 -0
  20. package/catalog/skills/spec-driven-development/assets/validation-checklist.md +32 -0
  21. package/catalog/skills/spec-driven-development/manifest.json +41 -0
  22. package/catalog/skills/token-optimizer/SKILL.md +141 -0
  23. package/catalog/skills/token-optimizer/manifest.json +33 -0
  24. package/catalog/skills/token-optimizer/references/complexity-indicators.md +138 -0
  25. package/catalog/templates/AGENTS.template.md +37 -0
  26. package/package.json +41 -0
  27. package/packages/catalog/package.json +6 -0
  28. package/packages/catalog/src/index.js +223 -0
  29. package/packages/cli/package.json +9 -0
  30. package/packages/cli/src/bin.js +144 -0
  31. package/packages/core/package.json +6 -0
  32. package/packages/core/src/index.js +304 -0
  33. package/packages/detectors/package.json +6 -0
  34. package/packages/detectors/src/index.js +169 -0
@@ -0,0 +1,138 @@
1
+ # Task Complexity Indicators
2
+
3
+ Use this reference to score task complexity before selecting reasoning depth and token budget.
4
+
5
+ ---
6
+
7
+ ## Scoring Bands
8
+
9
+ | Total Points | Tier |
10
+ | --- | --- |
11
+ | 0-2 | Trivial |
12
+ | 3-5 | Simple |
13
+ | 6-10 | Moderate |
14
+ | 11-15 | Complex |
15
+ | 16+ | Expert |
16
+
17
+ ---
18
+
19
+ ## Scoring Matrix
20
+
21
+ ### File Scope
22
+
23
+ | Indicator | Points |
24
+ | --- | --- |
25
+ | Single file, known location | 0 |
26
+ | Single file, needs search | +1 |
27
+ | 2-3 related files | +2 |
28
+ | 4-6 files | +4 |
29
+ | 7+ files or cross-package | +6 |
30
+ | Build/config/tooling impact | +3 |
31
+
32
+ ### Decision Complexity
33
+
34
+ | Indicator | Points |
35
+ | --- | --- |
36
+ | Single obvious approach | 0 |
37
+ | 2-3 valid approaches, clear best option | +2 |
38
+ | Multiple trade-off-heavy approaches | +4 |
39
+ | Architectural design required | +6 |
40
+ | System-wide pattern impact | +8 |
41
+
42
+ ### Context Requirements
43
+
44
+ | Indicator | Points |
45
+ | --- | --- |
46
+ | Can answer from current context | 0 |
47
+ | Requires 1-2 file reads | +1 |
48
+ | Requires 3-5 file reads | +2 |
49
+ | Requires codebase-wide search | +3 |
50
+ | Requires dependency understanding | +4 |
51
+ | Requires external docs/specs | +2 |
52
+
53
+ ### Impact Level
54
+
55
+ | Indicator | Points |
56
+ | --- | --- |
57
+ | Internal helper only | 0 |
58
+ | Private module behavior | +1 |
59
+ | Public API behavior | +3 |
60
+ | Shared utility used broadly | +4 |
61
+ | Breaking public change | +6 |
62
+ | Security-sensitive code | +8 |
63
+ | Performance-critical path | +6 |
64
+
65
+ ### Testing and Validation
66
+
67
+ | Indicator | Points |
68
+ | --- | --- |
69
+ | No tests needed | 0 |
70
+ | Small unit test update | +1 |
71
+ | Multiple test scenarios | +2 |
72
+ | Integration/e2e coverage changes | +3 |
73
+ | Manual QA verification required | +3 |
74
+ | Accessibility validation required | +4 |
75
+
76
+ ### User Clarity (Reduction)
77
+
78
+ | Indicator | Points |
79
+ | --- | --- |
80
+ | Vague request | 0 |
81
+ | Clear goal | -1 |
82
+ | Exact file paths provided | -2 |
83
+ | Specific line numbers provided | -3 |
84
+ | Reference implementation provided | -4 |
85
+ | Explicit acceptance criteria | -2 |
86
+
87
+ ---
88
+
89
+ ## Keyword Signals
90
+
91
+ High-complexity signals (+3 to +5):
92
+
93
+ - optimize, performance, security, refactor, migrate, architect, scale
94
+
95
+ Moderate signals (+1 to +2):
96
+
97
+ - improve, extend, integrate, validate, fix bug
98
+
99
+ Low signals (0):
100
+
101
+ - show, list, find, read, check existence
102
+
103
+ ---
104
+
105
+ ## Context Size Heuristic
106
+
107
+ | Context Size | Reads/Searches | Typical Tier |
108
+ | --- | --- | --- |
109
+ | Minimal | 0-1 | Trivial-Simple |
110
+ | Light | 2-3 | Simple-Moderate |
111
+ | Moderate | 4-7 | Moderate |
112
+ | Heavy | 8-15 | Complex |
113
+ | Extensive | 16+ | Expert |
114
+
115
+ ---
116
+
117
+ ## Reassessment Triggers
118
+
119
+ Re-score during execution when:
120
+
121
+ 1. Scope expands into additional systems.
122
+ 2. The initial approach fails and alternatives are needed.
123
+ 3. User adds new constraints or quality requirements.
124
+ 4. Gathered context is insufficient for a safe answer.
125
+
126
+ Escalate one tier when any of these materially changes risk or effort.
127
+
128
+ ---
129
+
130
+ ## Quick Card
131
+
132
+ ```text
133
+ TRIVIAL (0-2) -> Minimal reasoning, direct answer
134
+ SIMPLE (3-5) -> Light reasoning, focused context
135
+ MODERATE (6-10) -> Selective reasoning, targeted exploration
136
+ COMPLEX (11-15) -> Regular reasoning, systematic analysis
137
+ EXPERT (16+) -> Deep reasoning, broad trade-off evaluation
138
+ ```
@@ -0,0 +1,37 @@
1
+ # {{projectName}} AI Agent Orchestrator
2
+
3
+ This file is generated by `skilly-hand`.
4
+
5
+ ## Where
6
+
7
+ - Scope: repository root and all descendants unless overridden by deeper AGENTS files.
8
+ - Installation generated at: `{{generatedAt}}`.
9
+ - Detected technologies: `{{detectedTechnologies}}`.
10
+
11
+ ## What
12
+
13
+ ### Installed Skill Registry
14
+
15
+ | Skill | Purpose | Tags |
16
+ | ----- | ------- | ---- |
17
+ {{skillsTable}}
18
+
19
+ ## When
20
+
21
+ ### Auto-invoke Triggers
22
+
23
+ | Action | Skill |
24
+ | ------ | ----- |
25
+ {{autoInvokeTable}}
26
+
27
+ ## Chaining Notations
28
+
29
+ Chaining notations document integrated workflows where multiple skills are sequentially invoked for complex tasks. Always invoke skills in documented order.
30
+
31
+ ### Root AGENTS Maintenance Workflow
32
+
33
+ ```text
34
+ Updating root AGENTS.md guidance
35
+ -> agents-root-orchestrator
36
+ -> skill-creator (if reusable workflow docs changed)
37
+ ```
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "@skilly-hand/skilly-hand",
3
+ "version": "0.1.0",
4
+ "license": "CC-BY-NC-4.0",
5
+ "type": "module",
6
+ "publishConfig": {
7
+ "access": "public"
8
+ },
9
+ "bin": {
10
+ "skilly-hand": "packages/cli/src/bin.js"
11
+ },
12
+ "files": [
13
+ "catalog",
14
+ "packages",
15
+ "README.md",
16
+ "CHANGELOG.md",
17
+ "LICENSE"
18
+ ],
19
+ "workspaces": [
20
+ "packages/*"
21
+ ],
22
+ "engines": {
23
+ "node": ">=20.0.0"
24
+ },
25
+ "scripts": {
26
+ "build": "node ./scripts/build-catalog-index.mjs",
27
+ "catalog:check": "node ./scripts/check-catalog.mjs",
28
+ "catalog:sync": "node ./scripts/sync-catalog-readme.mjs",
29
+ "agentic:self:sync": "node ./scripts/sync-self-agentic.mjs",
30
+ "test": "node --test tests/*.test.js",
31
+ "verify:packlist": "node ./scripts/verify-packlist.mjs",
32
+ "verify:publish": "npm run catalog:check && npm test && npm run verify:packlist",
33
+ "prepublishOnly": "npm run verify:publish",
34
+ "version": "node ./scripts/release-changelog.mjs",
35
+ "changelog:release": "node ./scripts/release-changelog.mjs",
36
+ "cli": "node ./packages/cli/src/bin.js",
37
+ "detect": "node ./packages/cli/src/bin.js detect",
38
+ "list": "node ./packages/cli/src/bin.js list",
39
+ "doctor": "node ./packages/cli/src/bin.js doctor"
40
+ }
41
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "name": "@skilly-hand/catalog",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "type": "module"
6
+ }
@@ -0,0 +1,223 @@
1
+ import { cp, mkdir, readFile, readdir, stat, writeFile } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+
5
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
6
+ const rootDir = path.resolve(__dirname, "../../..");
7
+ export const catalogDir = path.join(rootDir, "catalog");
8
+ export const skillsDir = path.join(catalogDir, "skills");
9
+ export const templatesDir = path.join(catalogDir, "templates");
10
+
11
+ const REQUIRED_FIELDS = [
12
+ "id",
13
+ "title",
14
+ "description",
15
+ "portable",
16
+ "tags",
17
+ "detectors",
18
+ "installsFor",
19
+ "agentSupport",
20
+ "files",
21
+ "dependencies"
22
+ ];
23
+
24
+ export function getCatalogRoot() {
25
+ return catalogDir;
26
+ }
27
+
28
+ export async function listSkillIds() {
29
+ const entries = await readdir(skillsDir, { withFileTypes: true });
30
+ return entries
31
+ .filter((entry) => entry.isDirectory())
32
+ .map((entry) => entry.name)
33
+ .sort();
34
+ }
35
+
36
+ export async function loadSkillManifest(skillId) {
37
+ const manifestPath = path.join(skillsDir, skillId, "manifest.json");
38
+ const manifest = JSON.parse(await readFile(manifestPath, "utf8"));
39
+ validateSkillManifest(manifest);
40
+ return manifest;
41
+ }
42
+
43
+ export async function loadAllSkills() {
44
+ const ids = await listSkillIds();
45
+ const manifests = [];
46
+
47
+ for (const skillId of ids) {
48
+ manifests.push(await loadSkillManifest(skillId));
49
+ }
50
+
51
+ return manifests;
52
+ }
53
+
54
+ export function validateSkillManifest(manifest) {
55
+ for (const field of REQUIRED_FIELDS) {
56
+ if (!(field in manifest)) {
57
+ throw new Error(`Missing required field "${field}" in skill manifest`);
58
+ }
59
+ }
60
+
61
+ if (!Array.isArray(manifest.tags) || manifest.tags.length === 0) {
62
+ throw new Error(`Skill "${manifest.id}" must declare at least one tag`);
63
+ }
64
+
65
+ if (!Array.isArray(manifest.agentSupport) || manifest.agentSupport.length === 0) {
66
+ throw new Error(`Skill "${manifest.id}" must declare agentSupport`);
67
+ }
68
+
69
+ if (!Array.isArray(manifest.files) || manifest.files.length === 0) {
70
+ throw new Error(`Skill "${manifest.id}" must declare files`);
71
+ }
72
+
73
+ return true;
74
+ }
75
+
76
+ export async function copySkillTo(targetCatalogDir, skillId) {
77
+ const source = path.join(skillsDir, skillId);
78
+ const destination = path.join(targetCatalogDir, skillId);
79
+
80
+ await mkdir(targetCatalogDir, { recursive: true });
81
+ await cp(source, destination, { recursive: true, force: true });
82
+
83
+ return destination;
84
+ }
85
+
86
+ export async function readTemplate(templateName) {
87
+ return readFile(path.join(templatesDir, templateName), "utf8");
88
+ }
89
+
90
+ export function renderAgentsMarkdown({ skills, detections, generatedAt, projectName }) {
91
+ const sortedSkills = [...skills].sort((a, b) => a.id.localeCompare(b.id));
92
+ const sortedDetections = [...detections].sort((a, b) => a.technology.localeCompare(b.technology));
93
+ const autoInvokeSkills = sortedSkills.filter((skill) => skill.skillMetadata?.["auto-invoke"]);
94
+
95
+ const lines = [
96
+ "<!-- Managed by skilly-hand. Re-run `npx skilly-hand install` or `npm run agentic:self:sync` to regenerate. -->",
97
+ `# ${projectName || "Project"} AI Agent Orchestrator`,
98
+ "",
99
+ "> Root guidance for repository-wide AI routing. Use this file to understand where work belongs, what skills to invoke, and when triggers apply.",
100
+ "",
101
+ "## Where",
102
+ "",
103
+ "- Scope: repository root and all descendant folders unless a deeper AGENTS guide overrides locally.",
104
+ `- Generated at: ${generatedAt}`,
105
+ `- Detected technologies: ${sortedDetections.length === 0 ? "none" : sortedDetections.map((item) => item.technology).join(", ")}`,
106
+ "- Escalation boundary: when work changes global architecture, CI/CD, release, or security policy, escalate before implementation.",
107
+ "",
108
+ "## What",
109
+ "",
110
+ "### Installed Skill Registry",
111
+ "",
112
+ "| Skill | Description | Tags |",
113
+ "| ----- | ----------- | ---- |"
114
+ ];
115
+
116
+ for (const skill of sortedSkills) {
117
+ lines.push(`| \`${skill.id}\` | ${skill.description} | ${skill.tags.join(", ")} |`);
118
+ }
119
+
120
+ lines.push(
121
+ "",
122
+ "### Task Routing",
123
+ "",
124
+ "**SDD-first policy:** for feature delivery, bug fixes, or any multi-step implementation, start with `spec-driven-development` unless the task is clearly trivial and one-step.",
125
+ "",
126
+ "| Task Type | Recommended Skill Chain |",
127
+ "| --------- | ----------------------- |",
128
+ "| Planning feature work, bug fixes, and multi-phase implementation | `spec-driven-development` |",
129
+ "| Executing approved implementation plans | `spec-driven-development` -> task-specific skills |",
130
+ "| Creating or updating reusable skills | `skill-creator` |",
131
+ "| Creating or updating root AGENTS orchestration guidance | `agents-root-orchestrator` |",
132
+ "",
133
+ "## When",
134
+ "",
135
+ "### Auto-invoke Triggers",
136
+ ""
137
+ );
138
+
139
+ if (autoInvokeSkills.length === 0) {
140
+ lines.push("No explicit auto-invoke triggers were found in installed skill metadata.");
141
+ } else {
142
+ lines.push("| Action | Skill |", "| ------ | ----- |");
143
+ for (const skill of autoInvokeSkills) {
144
+ lines.push(`| ${skill.skillMetadata["auto-invoke"]} | \`${skill.id}\` |`);
145
+ }
146
+ }
147
+
148
+ lines.push(
149
+ "",
150
+ "### Sequencing Rules",
151
+ "",
152
+ "1. Classify task intent and scope first.",
153
+ "2. If work is non-trivial, invoke `spec-driven-development` before implementation.",
154
+ "3. Invoke prerequisite skills before implementation skills.",
155
+ "4. Verify outcomes and update this routing map when workflows change.",
156
+ "",
157
+ "## Chaining Notations",
158
+ "",
159
+ "Chaining notations document integrated workflows where multiple skills are sequentially invoked for complex tasks. Always invoke skills in documented order.",
160
+ "",
161
+ "### Root AGENTS Maintenance Workflow",
162
+ "",
163
+ "```text",
164
+ "Updating root AGENTS.md guidance",
165
+ " -> agents-root-orchestrator",
166
+ " -> skill-creator (if reusable workflow docs changed)",
167
+ "```",
168
+ "",
169
+ "### Skill Introduction Workflow",
170
+ "",
171
+ "```text",
172
+ "Asking for a new reusable skill",
173
+ " -> skill-creator",
174
+ " -> spec-driven-development",
175
+ " -> agents-root-orchestrator",
176
+ "```",
177
+ "",
178
+ "### SDD-First Delivery Workflow",
179
+ "",
180
+ "```text",
181
+ "Feature, bug, or multi-step execution request",
182
+ " -> spec-driven-development",
183
+ " -> task-specific implementation skill(s)",
184
+ " -> agents-root-orchestrator (if routing guidance changed)",
185
+ "```",
186
+ "",
187
+ "## Usage",
188
+ "",
189
+ "- Read the relevant `SKILL.md` file before starting a specialized task.",
190
+ "- Prefer installed skills under `.skilly-hand/catalog/` or repository `catalog/skills` as the source of truth.",
191
+ "- Use project-specific docs only as a supplement to these portable rules."
192
+ );
193
+
194
+ return lines.join("\n") + "\n";
195
+ }
196
+
197
+ export async function writeCatalogIndex() {
198
+ const ids = await listSkillIds();
199
+ const outputPath = path.join(catalogDir, "catalog-index.json");
200
+ await writeFile(outputPath, JSON.stringify(ids, null, 2) + "\n", "utf8");
201
+ return outputPath;
202
+ }
203
+
204
+ export async function verifyCatalogFiles() {
205
+ const skillIds = await listSkillIds();
206
+ const issues = [];
207
+
208
+ for (const skillId of skillIds) {
209
+ const skillPath = path.join(skillsDir, skillId);
210
+ const manifest = await loadSkillManifest(skillId);
211
+
212
+ for (const file of manifest.files) {
213
+ const filePath = path.join(skillPath, file.path);
214
+ try {
215
+ await stat(filePath);
216
+ } catch {
217
+ issues.push(`Missing file for ${skillId}: ${file.path}`);
218
+ }
219
+ }
220
+ }
221
+
222
+ return issues;
223
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "name": "@skilly-hand/cli",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "bin": {
7
+ "skilly-hand": "./src/bin.js"
8
+ }
9
+ }
@@ -0,0 +1,144 @@
1
+ #!/usr/bin/env node
2
+ import path from "node:path";
3
+ import { loadAllSkills } from "../../catalog/src/index.js";
4
+ import { installProject, runDoctor, uninstallProject } from "../../core/src/index.js";
5
+ import { detectProject } from "../../detectors/src/index.js";
6
+
7
+ function parseArgs(argv) {
8
+ const args = [...argv];
9
+ const positional = [];
10
+ const flags = {
11
+ dryRun: false,
12
+ yes: false,
13
+ verbose: false,
14
+ agents: [],
15
+ include: [],
16
+ exclude: []
17
+ };
18
+
19
+ while (args.length > 0) {
20
+ const token = args.shift();
21
+ if (!token.startsWith("-")) {
22
+ positional.push(token);
23
+ continue;
24
+ }
25
+
26
+ if (token === "--dry-run") flags.dryRun = true;
27
+ else if (token === "--yes" || token === "-y") flags.yes = true;
28
+ else if (token === "--verbose" || token === "-v") flags.verbose = true;
29
+ else if (token === "--agent" || token === "-a") flags.agents.push(args.shift());
30
+ else if (token === "--cwd") flags.cwd = args.shift();
31
+ else if (token === "--include") flags.include.push(args.shift());
32
+ else if (token === "--exclude") flags.exclude.push(args.shift());
33
+ else if (token === "--help" || token === "-h") flags.help = true;
34
+ else throw new Error(`Unknown flag: ${token}`);
35
+ }
36
+
37
+ return { command: positional[0], flags };
38
+ }
39
+
40
+ function printHelp() {
41
+ console.log(`skilly-hand
42
+
43
+ Usage:
44
+ npx skilly-hand [install]
45
+ npx skilly-hand detect
46
+ npx skilly-hand list
47
+ npx skilly-hand doctor
48
+ npx skilly-hand uninstall
49
+
50
+ Flags:
51
+ --dry-run
52
+ --yes
53
+ --verbose
54
+ --agent <codex|claude|cursor|gemini|copilot>
55
+ --cwd <path>
56
+ --include <tag>
57
+ --exclude <tag>
58
+ `);
59
+ }
60
+
61
+ function printDetections(detections) {
62
+ if (detections.length === 0) {
63
+ console.log("No technology signals were detected.");
64
+ return;
65
+ }
66
+
67
+ for (const item of detections) {
68
+ console.log(`- ${item.technology} (${item.confidence})`);
69
+ console.log(` reasons: ${item.reasons.join("; ")}`);
70
+ console.log(` recommended skills: ${item.recommendedSkillIds.join(", ")}`);
71
+ }
72
+ }
73
+
74
+ function printPlan(plan) {
75
+ console.log(`Project: ${plan.cwd}`);
76
+ console.log(`Install root: ${plan.installRoot}`);
77
+ console.log(`Agents: ${plan.agents.join(", ")}`);
78
+ console.log("Detected technologies:");
79
+ printDetections(plan.detections);
80
+ console.log("Skills to install:");
81
+ for (const skill of plan.skills) {
82
+ console.log(`- ${skill.id}: ${skill.title} [${skill.tags.join(", ")}]`);
83
+ }
84
+ }
85
+
86
+ async function main() {
87
+ const { command, flags } = parseArgs(process.argv.slice(2));
88
+
89
+ if (flags.help) {
90
+ printHelp();
91
+ return;
92
+ }
93
+
94
+ const cwd = path.resolve(flags.cwd || process.cwd());
95
+ const effectiveCommand = command || "install";
96
+
97
+ if (effectiveCommand === "detect") {
98
+ printDetections(await detectProject(cwd));
99
+ return;
100
+ }
101
+
102
+ if (effectiveCommand === "list") {
103
+ const skills = await loadAllSkills();
104
+ for (const skill of skills) {
105
+ console.log(`- ${skill.id}: ${skill.title}`);
106
+ console.log(` tags: ${skill.tags.join(", ")}`);
107
+ console.log(` agents: ${skill.agentSupport.join(", ")}`);
108
+ }
109
+ return;
110
+ }
111
+
112
+ if (effectiveCommand === "doctor") {
113
+ const result = await runDoctor(cwd);
114
+ console.log(JSON.stringify(result, null, 2));
115
+ return;
116
+ }
117
+
118
+ if (effectiveCommand === "uninstall") {
119
+ const result = await uninstallProject(cwd);
120
+ console.log(result.removed ? "skilly-hand installation removed." : result.reason);
121
+ return;
122
+ }
123
+
124
+ if (effectiveCommand === "install") {
125
+ const result = await installProject({
126
+ cwd,
127
+ agents: flags.agents,
128
+ dryRun: flags.dryRun,
129
+ includeTags: flags.include,
130
+ excludeTags: flags.exclude
131
+ });
132
+
133
+ printPlan(result.plan);
134
+ console.log(result.applied ? "Installation completed." : "Dry run only; nothing was written.");
135
+ return;
136
+ }
137
+
138
+ throw new Error(`Unknown command: ${effectiveCommand}`);
139
+ }
140
+
141
+ main().catch((error) => {
142
+ console.error(error.message);
143
+ process.exitCode = 1;
144
+ });
@@ -0,0 +1,6 @@
1
+ {
2
+ "name": "@skilly-hand/core",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "type": "module"
6
+ }