@khanhcan148/mk 0.1.10 → 0.1.12
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 +33 -57
- package/package.json +3 -3
- package/src/commands/init.js +4 -1
- package/src/commands/remove.js +2 -14
- package/src/commands/update.js +6 -15
- package/src/lib/constants.js +3 -2
- package/src/lib/copy.js +94 -1
- package/src/lib/fs-utils.js +18 -0
package/README.md
CHANGED
|
@@ -6,15 +6,8 @@
|
|
|
6
6
|
|
|
7
7
|
Modular packages that extend Claude Code with specialized knowledge, workflows, and tool integrations.
|
|
8
8
|
|
|
9
|
-
**Quick Navigation:** [Quick Reference](docs/
|
|
9
|
+
**Quick Navigation:** [Quick Reference](docs/quick-reference.md) | [Common Workflows](docs/common-workflows.md) | [Skill Index](docs/skill-index.md)
|
|
10
10
|
|
|
11
|
-
## 🔒 Access Notice
|
|
12
|
-
|
|
13
|
-
**This package has limited access.** To get access to the npm package and repository:
|
|
14
|
-
|
|
15
|
-
📧 **Email:** khanhcan148@gmail.com
|
|
16
|
-
|
|
17
|
-
Include your use case and I'll send you an invitation.
|
|
18
11
|
|
|
19
12
|
## Quick Start
|
|
20
13
|
|
|
@@ -74,7 +67,7 @@ cp -r .claude ~/.claude/
|
|
|
74
67
|
```bash
|
|
75
68
|
# Use a workflow command
|
|
76
69
|
/mk-init # Bootstrap new project
|
|
77
|
-
/mk-brainstorm # Explore options, debate trade-offs
|
|
70
|
+
/mk-brainstorm # Explore options, debate trade-offs; pass Jira/AzDO URL to fetch ticket context first
|
|
78
71
|
/mk-plan # Create implementation plan
|
|
79
72
|
/mk-implement # End-to-end feature delivery
|
|
80
73
|
/mk-test # Run tests and validate
|
|
@@ -83,20 +76,21 @@ cp -r .claude ~/.claude/
|
|
|
83
76
|
/mk-security # Security scan and audit
|
|
84
77
|
/mk-db # Database operations
|
|
85
78
|
/mk-docs # Generate documentation
|
|
79
|
+
/mk-overview # Multi-tier stakeholder overview (Executive, Product, Technical)
|
|
86
80
|
/mk-git # Git operations
|
|
87
81
|
/mk-audit # Code archaeology chain: orientation, testing, heatmap, breaking-change analysis, technical debt, domain extraction
|
|
88
|
-
/mk-skill-creator # Create and scaffold new Claude Code skills with automated validation
|
|
89
82
|
/mk-selftest # Self-validation checks on kit agents, skills, docs, workflows
|
|
83
|
+
/mk-log-analysis # Datadog + Azure App Insights log analysis with severity triage and Mermaid visual reports
|
|
90
84
|
```
|
|
91
85
|
|
|
92
86
|
## Structure
|
|
93
87
|
|
|
94
88
|
```
|
|
95
89
|
├── .claude/
|
|
96
|
-
│ ├── agents/ #
|
|
97
|
-
│ ├── skills/ #
|
|
98
|
-
│ │ ├── mk-*/ #
|
|
99
|
-
│ │ └── ... # Domain skills (frontend, backend, testing, etc.)
|
|
90
|
+
│ ├── agents/ # 31 agents (5 primary + 26 utility: implementers, quality, docs, specialized, concerns)
|
|
91
|
+
│ ├── skills/ # 65 skill packages (SKILL.md + scripts/references/assets)
|
|
92
|
+
│ │ ├── mk-*/ # 19 workflow commands (/mk-audit, /mk-brainstorm, /mk-log-analysis, /mk-overview, /mk-selftest, etc.)
|
|
93
|
+
│ │ └── ... # Domain skills (frontend, backend, testing, browser automation, etc.)
|
|
100
94
|
│ └── workflows/ # Development protocols
|
|
101
95
|
├── bin/ # CLI entry point (mk command)
|
|
102
96
|
├── src/ # CLI source code
|
|
@@ -109,7 +103,7 @@ cp -r .claude ~/.claude/
|
|
|
109
103
|
|
|
110
104
|
## Primary Workflow
|
|
111
105
|
|
|
112
|
-
Orchestration is handled by `/mk-*` skills which spawn utility agents as needed. See [Common Workflows](docs/
|
|
106
|
+
Orchestration is handled by `/mk-*` skills which spawn utility agents as needed. See [Common Workflows](docs/common-workflows.md) for practical examples.
|
|
113
107
|
|
|
114
108
|
**Architecture:**
|
|
115
109
|
|
|
@@ -126,21 +120,24 @@ User → /mk-* command (skill) → spawns utility agents → agents use knowledg
|
|
|
126
120
|
|
|
127
121
|
| Command | Purpose |
|
|
128
122
|
|---------|---------|
|
|
129
|
-
| `/mk-init` | Full project bootstrap from conception to deployment; includes brownfield detection (Phase 0 gate) and adoption workflow (B1-B4.5 stages) |
|
|
130
|
-
| `/mk-brainstorm` | Ideation, requirements exploration, structured debate (analyzer opus agent) |
|
|
131
|
-
| `/mk-audit` | Code archaeology chain: orientation report, characterization testing, topology heatmap, breaking-change analysis, technical debt dashboard, domain extraction |
|
|
123
|
+
| `/mk-init` | Full project bootstrap from conception to deployment; includes brownfield detection (Phase 0 gate) and adoption workflow (B1-B4.5 stages); generates AGENTS.md template (or migrates existing tool configs); suggests /mk-audit as next step for brownfield projects |
|
|
124
|
+
| `/mk-brainstorm` | Ideation, requirements exploration, structured debate (analyzer opus agent); pass a Jira or AzDO URL to fetch ticket hierarchy first (Phase 0.5) |
|
|
125
|
+
| `/mk-audit` | Code archaeology chain: orientation report, characterization testing, topology heatmap, breaking-change analysis, technical debt dashboard, domain extraction; enriches CLAUDE.md and AGENTS.md with auto-generated architecture and debt sections |
|
|
132
126
|
| `/mk-plan` | Create implementation plans with phases and tasks (opus) |
|
|
133
127
|
| `/mk-design` | UI/UX wireframes, design systems, mockups |
|
|
134
128
|
| `/mk-implement` | End-to-end feature delivery (sonnet) |
|
|
135
129
|
| `/mk-test` | Run tests, analyze coverage, validate builds |
|
|
136
130
|
| `/mk-review` | Code review for quality, security, performance |
|
|
137
|
-
| `/mk-debug` | Debugging workflow: investigate, diagnose, fix, verify |
|
|
131
|
+
| `/mk-debug` | Debugging workflow: investigate, diagnose, fix, verify; always offers incident journal documentation with severity hints |
|
|
138
132
|
| `/mk-security` | Security-first workflow: dependency scan, secrets detection |
|
|
139
133
|
| `/mk-db` | Database operations: diagnose, optimize, design, migrate |
|
|
140
|
-
| `/mk-docs` | Generate and update project documentation |
|
|
134
|
+
| `/mk-docs` | Generate and update project documentation; maintains AGENTS.md; Impact Areas analysis produces human-readable "What changed / Who is affected / What could go wrong" narrative |
|
|
141
135
|
| `/mk-git` | Git operations: branch, commit, push, PR, merge |
|
|
142
136
|
| `/mk-research` | Deep multi-source research on technical topics |
|
|
143
|
-
| `/mk-
|
|
137
|
+
| `/mk-spike` | Investigate external service integrations: fetch API docs, evaluate options, produce spike.md with Go/No-Go |
|
|
138
|
+
| `/mk-overview` | Synthesize project artifacts into multi-tier stakeholder overview: Executive Brief, Product Report, Technical Report |
|
|
139
|
+
| `/mk-workflow` | Trace REST endpoint call chains with upstream caller detection, variant branching, side effects/feature flags, Mermaid diagrams |
|
|
140
|
+
| `/mk-log-analysis` | Analyze production logs from Datadog or Azure Application Insights via MCP; progressive severity triage, pattern detection, mandatory stack trace investigation, mk-debug integration |
|
|
144
141
|
| `/mk-selftest` | Run self-validation checks on kit agents, skills, docs, and workflows |
|
|
145
142
|
|
|
146
143
|
## Primary Agents
|
|
@@ -153,17 +150,18 @@ Invoked directly via `/mk-*` skills:
|
|
|
153
150
|
| **planner** | Implementation planning with phases, tasks, dependencies | opus |
|
|
154
151
|
| **implementer** | End-to-end feature implementation | sonnet |
|
|
155
152
|
| **database-admin** | Database operations: diagnose, optimize, design, migrate | sonnet |
|
|
156
|
-
| **git-manager** | Git operations: commit, push, PR, merge |
|
|
153
|
+
| **git-manager** | Git operations: commit, push, PR, merge | sonnet |
|
|
157
154
|
|
|
158
155
|
## Utility Agents
|
|
159
156
|
|
|
160
157
|
Spawned by primary agents for domain-specific work:
|
|
161
158
|
|
|
162
|
-
**Implementation & Quality (
|
|
159
|
+
**Implementation & Quality (9)**
|
|
163
160
|
| Agent | Purpose |
|
|
164
161
|
|-------|---------|
|
|
165
162
|
| **backend-implementer** | API and domain logic implementation |
|
|
166
163
|
| **frontend-implementer** | UI components, consuming API contract |
|
|
164
|
+
| **mobile-implementer** | Mobile app implementation (Flutter, React Native, Swift, Kotlin) with TFD |
|
|
167
165
|
| **tester** | Test execution and validation |
|
|
168
166
|
| **debugger** | Issue investigation and diagnosis |
|
|
169
167
|
| **refactorer** | Refactoring with TFD-first safety workflow |
|
|
@@ -189,7 +187,7 @@ Spawned by primary agents for domain-specific work:
|
|
|
189
187
|
| **scout-external** | Codebase search via external tools |
|
|
190
188
|
| **mcp-manager** | MCP server integrations |
|
|
191
189
|
|
|
192
|
-
**Parallel Concern Review Agents (
|
|
190
|
+
**Parallel Concern Review Agents (11)**
|
|
193
191
|
| Agent | Purpose |
|
|
194
192
|
|-------|---------|
|
|
195
193
|
| **quality-reviewer** | Code quality, readability, maintainability (mk-review concern) |
|
|
@@ -202,33 +200,30 @@ Spawned by primary agents for domain-specific work:
|
|
|
202
200
|
| **infra-reviewer** | Infrastructure security review (mk-security concern) |
|
|
203
201
|
| **log-analyzer** | Log analysis and diagnostics (mk-debug concern) |
|
|
204
202
|
| **hypothesis-generator** | Root cause hypothesis generation (mk-debug concern) |
|
|
203
|
+
| **log-collector** | External observability platform queries — Datadog and Azure App Insights MCP (mk-log-analysis concern) |
|
|
205
204
|
|
|
206
205
|
[Full agent details →](.claude/agents/README.md)
|
|
207
206
|
|
|
208
207
|
## Skills
|
|
209
208
|
|
|
210
|
-
See [Skill Index](docs/
|
|
209
|
+
See [Skill Index](docs/skill-index.md) for a complete categorized list of all skills.
|
|
211
210
|
|
|
212
211
|
Each skill contains:
|
|
213
|
-
- `SKILL.md` (required) - Instructions (
|
|
212
|
+
- `SKILL.md` (required) - Instructions (≤250 lines)
|
|
214
213
|
- `scripts/` (optional) - Executable code with tests
|
|
215
214
|
- `references/` (optional) - Documentation chunks
|
|
216
215
|
- `assets/` (optional) - Templates, images
|
|
217
216
|
|
|
218
217
|
```bash
|
|
219
|
-
# Create new skill
|
|
220
|
-
/
|
|
221
|
-
|
|
222
|
-
# Or use scripts directly
|
|
223
|
-
.claude/skills/mk-skill-creator/scripts/init_skill.py <skill-name> --path <output-directory>
|
|
224
|
-
.claude/skills/mk-skill-creator/scripts/package_skill.py <path/to/skill-folder>
|
|
218
|
+
# Create new skill
|
|
219
|
+
python .claude/skills/skill-creator/scripts/package_skill.py <path/to/skill-folder>
|
|
225
220
|
```
|
|
226
221
|
|
|
227
222
|
## Documentation
|
|
228
223
|
|
|
229
224
|
| Document | Description |
|
|
230
225
|
|----------|-------------|
|
|
231
|
-
| [Skill Index](docs/
|
|
226
|
+
| [Skill Index](docs/skill-index.md) | Categorized list of all skills and workflows |
|
|
232
227
|
| [mk-* Workflows & Agents](docs/mk-workflow-agents.md) | How each /mk-* command works and which agents it uses |
|
|
233
228
|
| [Project Overview & PDR](docs/project-overview-pdr.md) | Requirements, constraints, success metrics |
|
|
234
229
|
| [Project Roadmap](docs/project-roadmap.md) | Phases, milestones, and risk register |
|
|
@@ -236,8 +231,8 @@ Each skill contains:
|
|
|
236
231
|
| [Code Standards](docs/code-standards.md) | Conventions, naming, quality gates |
|
|
237
232
|
| [System Architecture](docs/system-architecture.md) | Component diagrams, data flow |
|
|
238
233
|
| [Product Domain Glossary](docs/product-domain-glossary.md) | Core domain concepts, terminology, and ecosystem definitions |
|
|
239
|
-
| [Quick Reference](docs/
|
|
240
|
-
| [Common Workflows](docs/
|
|
234
|
+
| [Quick Reference](docs/quick-reference.md) | Common commands and quick lookup |
|
|
235
|
+
| [Common Workflows](docs/common-workflows.md) | Practical workflow examples |
|
|
241
236
|
|
|
242
237
|
## Core Principles
|
|
243
238
|
|
|
@@ -248,16 +243,12 @@ Each skill contains:
|
|
|
248
243
|
|
|
249
244
|
## Key Constraints
|
|
250
245
|
|
|
251
|
-
- SKILL.md must be
|
|
252
|
-
-
|
|
246
|
+
- SKILL.md must be ≤250 lines
|
|
247
|
+
- Reference files in `references/` have no line limit; loaded on-demand
|
|
253
248
|
- Scripts must include tests
|
|
254
249
|
- **Cross-platform compatibility (Windows + macOS/Linux) is mandatory**: Scripts use Python or Node.js only — no bash/shell scripts
|
|
255
250
|
- Token efficiency - minimize context usage
|
|
256
251
|
|
|
257
|
-
## Compatibility
|
|
258
|
-
|
|
259
|
-
This skill kit works in both Claude Code CLI and VSCode GitHub Copilot (1.108+).
|
|
260
|
-
|
|
261
252
|
## Cross-Platform Compatibility
|
|
262
253
|
|
|
263
254
|
This kit is designed to work on Windows, macOS, and Linux:
|
|
@@ -265,19 +256,4 @@ This kit is designed to work on Windows, macOS, and Linux:
|
|
|
265
256
|
- **Scripts**: All executable scripts use Python or Node.js (no bash/shell scripts)
|
|
266
257
|
- **Claude Code Bash tool**: Provides a Unix-like shell on all platforms, including Windows — git commands and other Bash tool invocations work everywhere
|
|
267
258
|
- **External tool installs**: Reference files include install instructions for macOS (`brew`), Ubuntu/Debian (`apt-get`), and Windows (`winget`/`choco`) where applicable
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
| Feature | Claude Code CLI | VSCode Copilot (1.108+) |
|
|
271
|
-
|---------|----------------|------------------------|
|
|
272
|
-
| Skills (SKILL.md) | Full support | Full support |
|
|
273
|
-
| Agents (.md) | Full support | Full support |
|
|
274
|
-
| CLAUDE.md | Full support | Full support |
|
|
275
|
-
| Model field | Shorthand (opus/sonnet/haiku) | Shorthand (recommended) |
|
|
276
|
-
| Task tool | Native Task() syntax | Natural language delegation* |
|
|
277
|
-
| color | Supported | Ignored (harmless) |
|
|
278
|
-
| MCP tools | Full support | Limited |
|
|
279
|
-
| AskUserQuestion | Native UI | Natural language fallback |
|
|
280
|
-
|
|
281
|
-
*VSCode Copilot users: Use natural language to invoke agents (e.g., "Use the planner agent to create a plan"). The explicit Task() syntax is Claude Code CLI-specific.
|
|
282
|
-
|
|
283
|
-
**CLI-only tools**: TodoWrite, BashOutput, KillShell, MultiEdit are Claude Code-specific. Agents gracefully fall back to standard tools (Write, Bash, sequential Edit) when these are unavailable.
|
|
259
|
+
**Supported runtime**: Claude Code CLI. All skills, agents, and workflows are designed for the Claude Code runtime.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@khanhcan148/mk",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.12",
|
|
4
4
|
"description": "CLI to install and manage MyClaudeKit (.claude/) in your projects",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
"node": ">=18.0.0"
|
|
15
15
|
},
|
|
16
16
|
"scripts": {
|
|
17
|
-
"test": "node --test test/lib/*.test.js test/commands/*.test.js test/integration/*.test.js",
|
|
18
|
-
"lint": "node --check src/**/*.js bin/**/*.js 2>/dev/null
|
|
17
|
+
"test": "node --test test/lib/*.test.js test/commands/*.test.js test/integration/*.test.js test/characterization/*.characterization.test.js test/hooks/*.test.cjs",
|
|
18
|
+
"lint": "node --check src/**/*.js bin/**/*.js 2>/dev/null",
|
|
19
19
|
"selftest": "python3 .claude/skills/mk-selftest/scripts/validate_kit.py"
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
package/src/commands/init.js
CHANGED
|
@@ -2,7 +2,7 @@ import chalk from 'chalk';
|
|
|
2
2
|
import { existsSync, readFileSync } from 'node:fs';
|
|
3
3
|
import { join, relative } from 'node:path';
|
|
4
4
|
import { fileURLToPath } from 'node:url';
|
|
5
|
-
import { copyKitFiles } from '../lib/copy.js';
|
|
5
|
+
import { copyKitFiles, mergeSettingsJson } from '../lib/copy.js';
|
|
6
6
|
import { writeManifest } from '../lib/manifest.js';
|
|
7
7
|
import { computeChecksum } from '../lib/checksum.js';
|
|
8
8
|
import { resolveTargetDir, resolveManifestPath } from '../lib/paths.js';
|
|
@@ -45,6 +45,9 @@ export async function runInit(params = {}) {
|
|
|
45
45
|
// Copy files (dry-run or real)
|
|
46
46
|
const fileList = copyKitFiles(sourceDir, targetDir, { dryRun });
|
|
47
47
|
|
|
48
|
+
// Merge settings.json (hooks configuration) — safe merge, never overwrites user keys
|
|
49
|
+
mergeSettingsJson(sourceDir, targetDir, { dryRun });
|
|
50
|
+
|
|
48
51
|
if (dryRun) {
|
|
49
52
|
return { files: fileList, totalSize: fileList.reduce((s, f) => s + f.size, 0), dryRun: true };
|
|
50
53
|
}
|
package/src/commands/remove.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
|
-
import { existsSync, unlinkSync, rmdirSync
|
|
2
|
+
import { existsSync, unlinkSync, rmdirSync } from 'node:fs';
|
|
3
3
|
import { join, dirname, resolve, sep } from 'node:path';
|
|
4
4
|
import { readManifest } from '../lib/manifest.js';
|
|
5
5
|
import { resolveTargetDir, resolveManifestPath, deriveProjectRoot, assertSafePath } from '../lib/paths.js';
|
|
6
|
+
import { isEmptyDir } from '../lib/fs-utils.js';
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* Run the remove command.
|
|
@@ -110,19 +111,6 @@ export async function runRemove(params = {}) {
|
|
|
110
111
|
return { removed, skipped, dirsCleaned };
|
|
111
112
|
}
|
|
112
113
|
|
|
113
|
-
/**
|
|
114
|
-
* Check if a directory is empty.
|
|
115
|
-
* @param {string} dir
|
|
116
|
-
* @returns {boolean}
|
|
117
|
-
*/
|
|
118
|
-
function isEmptyDir(dir) {
|
|
119
|
-
try {
|
|
120
|
-
return readdirSync(dir).length === 0;
|
|
121
|
-
} catch {
|
|
122
|
-
return false;
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
114
|
/**
|
|
127
115
|
* CLI action handler for 'mk remove'.
|
|
128
116
|
* @param {{ global: boolean }} options
|
package/src/commands/update.js
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import { createInterface } from 'node:readline';
|
|
3
|
-
import { existsSync, unlinkSync, copyFileSync, mkdirSync, readFileSync, rmdirSync
|
|
3
|
+
import { existsSync, unlinkSync, copyFileSync, mkdirSync, readFileSync, rmdirSync } from 'node:fs';
|
|
4
4
|
import { join, dirname, resolve, sep } from 'node:path';
|
|
5
5
|
import { fileURLToPath } from 'node:url';
|
|
6
6
|
import { readManifest, updateManifest, diffManifest } from '../lib/manifest.js';
|
|
7
7
|
import { computeChecksum } from '../lib/checksum.js';
|
|
8
|
-
import { copyKitFiles, collectDiskFiles } from '../lib/copy.js';
|
|
8
|
+
import { copyKitFiles, collectDiskFiles, mergeSettingsJson } from '../lib/copy.js';
|
|
9
9
|
import { resolveTargetDir, resolveManifestPath, deriveProjectRoot, assertSafePath } from '../lib/paths.js';
|
|
10
10
|
import { resolveTokenOrLogin } from '../lib/auth.js';
|
|
11
11
|
import { writeToken, readStoredToken } from '../lib/config.js';
|
|
12
12
|
import { downloadAndExtractKit, cleanupTempDir } from '../lib/download.js';
|
|
13
13
|
import { fetchLatestRelease, compareVersions } from '../lib/releases.js';
|
|
14
|
+
import { isEmptyDir } from '../lib/fs-utils.js';
|
|
14
15
|
|
|
15
16
|
// ---------------------------------------------------------------------------
|
|
16
17
|
// Prompt helper
|
|
@@ -219,6 +220,9 @@ export async function runUpdate(params = {}) {
|
|
|
219
220
|
}
|
|
220
221
|
}
|
|
221
222
|
|
|
223
|
+
// Merge settings.json hooks — additive merge, never overwrites user keys
|
|
224
|
+
mergeSettingsJson(sourceDir, targetDir);
|
|
225
|
+
|
|
222
226
|
// Update manifest with new file map.
|
|
223
227
|
// Use explicitVersion when provided (e.g. release.version from updateAction);
|
|
224
228
|
// fall back to pkg.version for direct runUpdate calls or main-branch fallback downloads.
|
|
@@ -235,19 +239,6 @@ export async function runUpdate(params = {}) {
|
|
|
235
239
|
};
|
|
236
240
|
}
|
|
237
241
|
|
|
238
|
-
/**
|
|
239
|
-
* Check if a directory is empty.
|
|
240
|
-
* @param {string} dir
|
|
241
|
-
* @returns {boolean}
|
|
242
|
-
*/
|
|
243
|
-
function isEmptyDir(dir) {
|
|
244
|
-
try {
|
|
245
|
-
return readdirSync(dir).length === 0;
|
|
246
|
-
} catch {
|
|
247
|
-
return false;
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
|
|
251
242
|
/**
|
|
252
243
|
* CLI action handler for 'mk update'.
|
|
253
244
|
* Checks GitHub Releases for a newer version, prompts the user, then downloads
|
package/src/lib/constants.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Kit subdirectories to copy/manage (relative to .claude/)
|
|
3
3
|
*/
|
|
4
|
-
export const KIT_SUBDIRS = ['agents', 'skills', 'workflows'];
|
|
4
|
+
export const KIT_SUBDIRS = ['agents', 'skills', 'workflows', 'hooks'];
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Manifest file name
|
|
@@ -19,7 +19,8 @@ export const COPY_FILTER_PATTERNS = [
|
|
|
19
19
|
'node_modules',
|
|
20
20
|
'.DS_Store',
|
|
21
21
|
'package-lock.json',
|
|
22
|
-
'.env'
|
|
22
|
+
'.env',
|
|
23
|
+
'.logs'
|
|
23
24
|
];
|
|
24
25
|
|
|
25
26
|
/**
|
package/src/lib/copy.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { join, relative } from 'node:path';
|
|
2
|
-
import { statSync, lstatSync, existsSync } from 'node:fs';
|
|
2
|
+
import { statSync, lstatSync, existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
|
|
3
3
|
import fsExtra from 'fs-extra';
|
|
4
4
|
import { KIT_SUBDIRS, COPY_FILTER_PATTERNS, WINDOWS_PATH_WARN_LENGTH } from './constants.js';
|
|
5
5
|
|
|
@@ -153,3 +153,96 @@ export function copyKitFiles(sourceDir, targetDir, options = {}) {
|
|
|
153
153
|
|
|
154
154
|
return fileList;
|
|
155
155
|
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Merge kit's settings.json into user's existing settings.json.
|
|
159
|
+
* Strategy: deep-merge "hooks" key from kit source; preserve all other user keys.
|
|
160
|
+
* If user has no settings.json, copy kit source as-is.
|
|
161
|
+
* If kit source has no settings.json, do nothing.
|
|
162
|
+
*
|
|
163
|
+
* @param {string} sourceDir - Absolute path to source .claude/
|
|
164
|
+
* @param {string} targetDir - Absolute path to target .claude/
|
|
165
|
+
* @param {{ dryRun: boolean }} options
|
|
166
|
+
* @returns {{ action: 'created'|'merged'|'skipped', merged?: string[] }}
|
|
167
|
+
*/
|
|
168
|
+
export function mergeSettingsJson(sourceDir, targetDir, options = {}) {
|
|
169
|
+
const { dryRun = false } = options;
|
|
170
|
+
const srcPath = join(sourceDir, 'settings.json');
|
|
171
|
+
const destPath = join(targetDir, 'settings.json');
|
|
172
|
+
|
|
173
|
+
if (!existsSync(srcPath)) return { action: 'skipped' };
|
|
174
|
+
|
|
175
|
+
let kitSettings;
|
|
176
|
+
try {
|
|
177
|
+
kitSettings = JSON.parse(readFileSync(srcPath, 'utf-8'));
|
|
178
|
+
} catch {
|
|
179
|
+
return { action: 'skipped' };
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// No existing user settings — copy kit source as-is
|
|
183
|
+
if (!existsSync(destPath)) {
|
|
184
|
+
if (!dryRun) {
|
|
185
|
+
mkdirSync(targetDir, { recursive: true });
|
|
186
|
+
writeFileSync(destPath, JSON.stringify(kitSettings, null, 2) + '\n', 'utf-8');
|
|
187
|
+
}
|
|
188
|
+
return { action: 'created' };
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// Existing user settings — merge hooks only, preserve everything else
|
|
192
|
+
let userSettings;
|
|
193
|
+
try {
|
|
194
|
+
userSettings = JSON.parse(readFileSync(destPath, 'utf-8'));
|
|
195
|
+
} catch {
|
|
196
|
+
// Malformed user settings — skip to avoid data loss
|
|
197
|
+
return { action: 'skipped' };
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
const merged = [];
|
|
201
|
+
|
|
202
|
+
// Merge hooks: kit entries are added/updated, user entries not in kit are preserved
|
|
203
|
+
if (kitSettings.hooks) {
|
|
204
|
+
if (!userSettings.hooks) userSettings.hooks = {};
|
|
205
|
+
for (const [event, kitEntries] of Object.entries(kitSettings.hooks)) {
|
|
206
|
+
if (!userSettings.hooks[event]) {
|
|
207
|
+
userSettings.hooks[event] = kitEntries;
|
|
208
|
+
merged.push(event);
|
|
209
|
+
} else {
|
|
210
|
+
// Merge by matcher: add kit entries whose matcher doesn't already exist
|
|
211
|
+
for (const kitEntry of kitEntries) {
|
|
212
|
+
const kitMatcher = kitEntry.matcher || '*';
|
|
213
|
+
const exists = userSettings.hooks[event].some(
|
|
214
|
+
e => (e.matcher || '*') === kitMatcher
|
|
215
|
+
);
|
|
216
|
+
if (!exists) {
|
|
217
|
+
userSettings.hooks[event].push(kitEntry);
|
|
218
|
+
merged.push(`${event}[${kitMatcher}]`);
|
|
219
|
+
}
|
|
220
|
+
// If matcher exists, check if kit hooks are present
|
|
221
|
+
if (exists) {
|
|
222
|
+
const userEntry = userSettings.hooks[event].find(
|
|
223
|
+
e => (e.matcher || '*') === kitMatcher
|
|
224
|
+
);
|
|
225
|
+
if (userEntry && userEntry.hooks && kitEntry.hooks) {
|
|
226
|
+
for (const kh of kitEntry.hooks) {
|
|
227
|
+
const hookExists = userEntry.hooks.some(
|
|
228
|
+
uh => uh.command === kh.command
|
|
229
|
+
);
|
|
230
|
+
if (!hookExists) {
|
|
231
|
+
userEntry.hooks.push(kh);
|
|
232
|
+
merged.push(`${event}[${kitMatcher}]:${kh.command}`);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
if (merged.length === 0) return { action: 'skipped' };
|
|
243
|
+
|
|
244
|
+
if (!dryRun) {
|
|
245
|
+
writeFileSync(destPath, JSON.stringify(userSettings, null, 2) + '\n', 'utf-8');
|
|
246
|
+
}
|
|
247
|
+
return { action: 'merged', merged };
|
|
248
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { readdirSync } from 'node:fs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Check if a directory is empty.
|
|
5
|
+
*
|
|
6
|
+
* Returns false (rather than throwing) if the directory does not exist
|
|
7
|
+
* or is inaccessible — callers treat non-empty as a safe default.
|
|
8
|
+
*
|
|
9
|
+
* @param {string} dir - Absolute path to directory
|
|
10
|
+
* @returns {boolean} true if directory exists and contains no entries
|
|
11
|
+
*/
|
|
12
|
+
export function isEmptyDir(dir) {
|
|
13
|
+
try {
|
|
14
|
+
return readdirSync(dir).length === 0;
|
|
15
|
+
} catch {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
}
|