@khanhcan148/mk 0.1.8 → 0.1.10
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 +35 -21
- package/package.json +1 -1
- package/src/commands/update.js +78 -3
- package/src/lib/constants.js +1 -0
- package/src/lib/copy.js +25 -0
package/README.md
CHANGED
|
@@ -2,12 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/@khanhcan148/mk)
|
|
4
4
|
|
|
5
|
-
**Built by** TRAN Le Khanh — developer and AI tooling author.
|
|
5
|
+
**Built by** TRAN Le Khanh (khanhcan148@gmail.com) — developer and AI tooling author.
|
|
6
6
|
|
|
7
7
|
Modular packages that extend Claude Code with specialized knowledge, workflows, and tool integrations.
|
|
8
8
|
|
|
9
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
|
## Quick Start
|
|
12
20
|
|
|
13
21
|
### CLI Installation (Recommended)
|
|
@@ -26,7 +34,7 @@ mk init --global
|
|
|
26
34
|
mk init --dry-run
|
|
27
35
|
```
|
|
28
36
|
|
|
29
|
-
**Note**:
|
|
37
|
+
**Note**: This package has limited access. Email khanhcan148@gmail.com for an invitation to access the npm package and repository.
|
|
30
38
|
|
|
31
39
|
### CLI Commands
|
|
32
40
|
|
|
@@ -65,17 +73,20 @@ cp -r .claude ~/.claude/
|
|
|
65
73
|
|
|
66
74
|
```bash
|
|
67
75
|
# Use a workflow command
|
|
68
|
-
/mk-init
|
|
69
|
-
/mk-brainstorm
|
|
70
|
-
/mk-plan
|
|
71
|
-
/mk-implement
|
|
72
|
-
/mk-test
|
|
73
|
-
/mk-review
|
|
74
|
-
/mk-debug
|
|
75
|
-
/mk-security
|
|
76
|
-
/mk-db
|
|
77
|
-
/mk-docs
|
|
78
|
-
/mk-git
|
|
76
|
+
/mk-init # Bootstrap new project
|
|
77
|
+
/mk-brainstorm # Explore options, debate trade-offs
|
|
78
|
+
/mk-plan # Create implementation plan
|
|
79
|
+
/mk-implement # End-to-end feature delivery
|
|
80
|
+
/mk-test # Run tests and validate
|
|
81
|
+
/mk-review # Code quality review
|
|
82
|
+
/mk-debug # Debug issues
|
|
83
|
+
/mk-security # Security scan and audit
|
|
84
|
+
/mk-db # Database operations
|
|
85
|
+
/mk-docs # Generate documentation
|
|
86
|
+
/mk-git # Git operations
|
|
87
|
+
/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
|
+
/mk-selftest # Self-validation checks on kit agents, skills, docs, workflows
|
|
79
90
|
```
|
|
80
91
|
|
|
81
92
|
## Structure
|
|
@@ -83,8 +94,8 @@ cp -r .claude ~/.claude/
|
|
|
83
94
|
```
|
|
84
95
|
├── .claude/
|
|
85
96
|
│ ├── agents/ # 29 agents (5 primary + 24 utility: implementers, quality, docs, specialized, concerns)
|
|
86
|
-
│ ├── skills/ #
|
|
87
|
-
│ │ ├── mk-*/ #
|
|
97
|
+
│ ├── skills/ # 58 skill packages (SKILL.md + scripts/references/assets)
|
|
98
|
+
│ │ ├── mk-*/ # 16 workflow commands (/mk-audit, /mk-brainstorm, /mk-skill-creator, /mk-selftest, etc.)
|
|
88
99
|
│ │ └── ... # Domain skills (frontend, backend, testing, etc.)
|
|
89
100
|
│ └── workflows/ # Development protocols
|
|
90
101
|
├── bin/ # CLI entry point (mk command)
|
|
@@ -116,8 +127,8 @@ User → /mk-* command (skill) → spawns utility agents → agents use knowledg
|
|
|
116
127
|
| Command | Purpose |
|
|
117
128
|
|---------|---------|
|
|
118
129
|
| `/mk-init` | Full project bootstrap from conception to deployment; includes brownfield detection (Phase 0 gate) and adoption workflow (B1-B4.5 stages) |
|
|
119
|
-
| `/mk-brainstorm` | Ideation, requirements exploration, structured debate (analyzer opus agent)
|
|
120
|
-
| `/mk-
|
|
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 |
|
|
121
132
|
| `/mk-plan` | Create implementation plans with phases and tasks (opus) |
|
|
122
133
|
| `/mk-design` | UI/UX wireframes, design systems, mockups |
|
|
123
134
|
| `/mk-implement` | End-to-end feature delivery (sonnet) |
|
|
@@ -128,6 +139,8 @@ User → /mk-* command (skill) → spawns utility agents → agents use knowledg
|
|
|
128
139
|
| `/mk-db` | Database operations: diagnose, optimize, design, migrate |
|
|
129
140
|
| `/mk-docs` | Generate and update project documentation |
|
|
130
141
|
| `/mk-git` | Git operations: branch, commit, push, PR, merge |
|
|
142
|
+
| `/mk-research` | Deep multi-source research on technical topics |
|
|
143
|
+
| `/mk-skill-creator` | Create and scaffold new Claude Code skills with automated SKILL.md, scripts, references, and agent |
|
|
131
144
|
| `/mk-selftest` | Run self-validation checks on kit agents, skills, docs, and workflows |
|
|
132
145
|
|
|
133
146
|
## Primary Agents
|
|
@@ -203,11 +216,12 @@ Each skill contains:
|
|
|
203
216
|
- `assets/` (optional) - Templates, images
|
|
204
217
|
|
|
205
218
|
```bash
|
|
206
|
-
#
|
|
207
|
-
|
|
219
|
+
# Create new skill (recommended)
|
|
220
|
+
/mk-skill-creator
|
|
208
221
|
|
|
209
|
-
#
|
|
210
|
-
.claude/skills/skill-creator/scripts/
|
|
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>
|
|
211
225
|
```
|
|
212
226
|
|
|
213
227
|
## Documentation
|
package/package.json
CHANGED
package/src/commands/update.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import { createInterface } from 'node:readline';
|
|
3
|
-
import { existsSync, unlinkSync, copyFileSync, mkdirSync, readFileSync } from 'node:fs';
|
|
4
|
-
import { join, dirname, resolve } from 'node:path';
|
|
3
|
+
import { existsSync, unlinkSync, copyFileSync, mkdirSync, readFileSync, rmdirSync, readdirSync } from 'node:fs';
|
|
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 } from '../lib/copy.js';
|
|
8
|
+
import { copyKitFiles, collectDiskFiles } 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';
|
|
@@ -167,6 +167,58 @@ export async function runUpdate(params = {}) {
|
|
|
167
167
|
delete newFiles[relPath];
|
|
168
168
|
}
|
|
169
169
|
|
|
170
|
+
// Orphan cleanup: files on disk (in kit subdirs) that are not in the new source
|
|
171
|
+
const diskFiles = collectDiskFiles(targetDir);
|
|
172
|
+
const orphans = [];
|
|
173
|
+
const orphanParentDirs = new Set();
|
|
174
|
+
for (const relPath of diskFiles) {
|
|
175
|
+
if (relPath in sourceFiles) continue; // present in new source — keep
|
|
176
|
+
const absPath = join(projectRoot, relPath);
|
|
177
|
+
try {
|
|
178
|
+
assertSafePath(absPath, claudeRoot, `orphan "${relPath}"`);
|
|
179
|
+
} catch (err) {
|
|
180
|
+
process.stderr.write(`Warning: Skipping unsafe orphan path: ${err.message}\n`);
|
|
181
|
+
continue;
|
|
182
|
+
}
|
|
183
|
+
try {
|
|
184
|
+
unlinkSync(absPath);
|
|
185
|
+
orphans.push(relPath);
|
|
186
|
+
orphanParentDirs.add(dirname(absPath));
|
|
187
|
+
} catch {
|
|
188
|
+
// Already missing — skip
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Clean up empty directories bottom-up after orphan deletion
|
|
193
|
+
const resolvedTarget = resolve(targetDir);
|
|
194
|
+
const sortedOrphanDirs = [...orphanParentDirs].sort((a, b) => {
|
|
195
|
+
return b.split(/[/\\]/).length - a.split(/[/\\]/).length;
|
|
196
|
+
});
|
|
197
|
+
for (const dir of sortedOrphanDirs) {
|
|
198
|
+
if (isEmptyDir(dir)) {
|
|
199
|
+
try {
|
|
200
|
+
rmdirSync(dir);
|
|
201
|
+
let current = dirname(dir);
|
|
202
|
+
let prev = dir;
|
|
203
|
+
while (current !== prev && isEmptyDir(current)) {
|
|
204
|
+
const resolvedCurrent = resolve(current);
|
|
205
|
+
if (resolvedCurrent === resolvedTarget || !resolvedCurrent.startsWith(resolvedTarget + sep)) {
|
|
206
|
+
break;
|
|
207
|
+
}
|
|
208
|
+
try {
|
|
209
|
+
rmdirSync(current);
|
|
210
|
+
} catch {
|
|
211
|
+
break;
|
|
212
|
+
}
|
|
213
|
+
prev = current;
|
|
214
|
+
current = dirname(current);
|
|
215
|
+
}
|
|
216
|
+
} catch {
|
|
217
|
+
// Non-empty or permission error — skip
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
170
222
|
// Update manifest with new file map.
|
|
171
223
|
// Use explicitVersion when provided (e.g. release.version from updateAction);
|
|
172
224
|
// fall back to pkg.version for direct runUpdate calls or main-branch fallback downloads.
|
|
@@ -178,10 +230,24 @@ export async function runUpdate(params = {}) {
|
|
|
178
230
|
removed: diff.removed,
|
|
179
231
|
conflicts: skippedConflicts,
|
|
180
232
|
unchanged: diff.unchanged,
|
|
233
|
+
orphans,
|
|
181
234
|
upToDate: false
|
|
182
235
|
};
|
|
183
236
|
}
|
|
184
237
|
|
|
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
|
+
|
|
185
251
|
/**
|
|
186
252
|
* CLI action handler for 'mk update'.
|
|
187
253
|
* Checks GitHub Releases for a newer version, prompts the user, then downloads
|
|
@@ -305,6 +371,15 @@ export async function updateAction(options = {}, deps = {}) {
|
|
|
305
371
|
}
|
|
306
372
|
if (result.removed.length > 0) {
|
|
307
373
|
process.stdout.write(chalk.yellow(`Removed: ${result.removed.length} files\n`));
|
|
374
|
+
for (const f of result.removed) {
|
|
375
|
+
process.stdout.write(` Removed: ${f}\n`);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
if (result.orphans && result.orphans.length > 0) {
|
|
379
|
+
process.stdout.write(chalk.yellow(`Cleaned: ${result.orphans.length} orphan files\n`));
|
|
380
|
+
for (const f of result.orphans) {
|
|
381
|
+
process.stdout.write(` Cleaned: ${f}\n`);
|
|
382
|
+
}
|
|
308
383
|
}
|
|
309
384
|
if (result.conflicts.length > 0) {
|
|
310
385
|
process.stdout.write(
|
package/src/lib/constants.js
CHANGED
package/src/lib/copy.js
CHANGED
|
@@ -52,6 +52,31 @@ function collectFiles(dir) {
|
|
|
52
52
|
return results;
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
+
/**
|
|
56
|
+
* Collect all kit-managed files currently on disk under targetDir (.claude/).
|
|
57
|
+
* Only walks KIT_SUBDIRS (agents/, skills/, workflows/).
|
|
58
|
+
* Returns relative paths in the form `.claude/agents/foo.md`.
|
|
59
|
+
* Applies shouldFilter to exclude filtered patterns.
|
|
60
|
+
*
|
|
61
|
+
* @param {string} targetDir - Absolute path to target .claude/
|
|
62
|
+
* @returns {string[]} relative paths (relative to project root, e.g. `.claude/agents/foo.md`)
|
|
63
|
+
*/
|
|
64
|
+
export function collectDiskFiles(targetDir) {
|
|
65
|
+
const results = [];
|
|
66
|
+
for (const subdir of KIT_SUBDIRS) {
|
|
67
|
+
const subdirAbs = join(targetDir, subdir);
|
|
68
|
+
if (!existsSync(subdirAbs)) continue;
|
|
69
|
+
const files = collectFiles(subdirAbs);
|
|
70
|
+
for (const absPath of files) {
|
|
71
|
+
if (shouldFilter(absPath)) continue;
|
|
72
|
+
const relFromSubdir = relative(subdirAbs, absPath);
|
|
73
|
+
const relPath = join('.claude', subdir, relFromSubdir).replace(/\\/g, '/');
|
|
74
|
+
results.push(relPath);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return results;
|
|
78
|
+
}
|
|
79
|
+
|
|
55
80
|
/**
|
|
56
81
|
* Copy kit files from sourceDir (.claude/) to targetDir (.claude/).
|
|
57
82
|
* Only copies KIT_SUBDIRS (agents/, skills/, workflows/).
|