@hd-agent-kit/cli 1.0.0 → 1.2.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.
- package/README.md +23 -14
- package/package.json +1 -1
- package/src/index.js +48 -22
- package/templates/{.agents/skills → skills}/analyze/SKILL.md +5 -0
- package/templates/{.agents/skills → skills}/commit/SKILL.md +5 -0
- package/templates/{.agents/skills → skills}/document/SKILL.md +5 -0
- package/templates/{.agents/skills → skills}/performance-check/SKILL.md +5 -0
- package/templates/{.agents/skills → skills}/refactor/SKILL.md +5 -0
- package/templates/{.agents/skills → skills}/security-scan/SKILL.md +5 -0
- package/templates/{.agents/skills → skills}/write-tests/SKILL.md +5 -0
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
AI agent configuration kit for Claude Code, Cursor, Windsurf, and OpenCode.
|
|
4
4
|
|
|
5
|
-
Sets up `AGENTS.md` and
|
|
5
|
+
Sets up `AGENTS.md` and skill files in your project so AI assistants follow consistent rules and have access to slash commands like `/commit`, `/analyze`, `/refactor`, etc.
|
|
6
6
|
|
|
7
7
|
## Installation
|
|
8
8
|
|
|
@@ -11,8 +11,9 @@ npx @hd-agent-kit/cli init
|
|
|
11
11
|
```
|
|
12
12
|
|
|
13
13
|
This will:
|
|
14
|
-
1. Copy `AGENTS.md`
|
|
15
|
-
2.
|
|
14
|
+
1. Copy `AGENTS.md` to your project root
|
|
15
|
+
2. Copy skill files to `.claude/skills/` (Claude Code) and `.opencode/skills/` (OpenCode)
|
|
16
|
+
3. Configure global gitignore so these files don't get pushed to your repo
|
|
16
17
|
|
|
17
18
|
## Commands
|
|
18
19
|
|
|
@@ -42,16 +43,23 @@ npx @hd-agent-kit/cli gitignore
|
|
|
42
43
|
|
|
43
44
|
```
|
|
44
45
|
your-project/
|
|
45
|
-
├── AGENTS.md
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
46
|
+
├── AGENTS.md ← Global AI rules (all tools read this)
|
|
47
|
+
├── .claude/skills/ ← Claude Code skills
|
|
48
|
+
│ ├── analyze/SKILL.md
|
|
49
|
+
│ ├── commit/SKILL.md
|
|
50
|
+
│ ├── document/SKILL.md
|
|
51
|
+
│ ├── performance-check/SKILL.md
|
|
52
|
+
│ ├── refactor/SKILL.md
|
|
53
|
+
│ ├── security-scan/SKILL.md
|
|
54
|
+
│ └── write-tests/SKILL.md
|
|
55
|
+
└── .opencode/skills/ ← OpenCode skills
|
|
56
|
+
├── analyze/SKILL.md
|
|
57
|
+
├── commit/SKILL.md
|
|
58
|
+
├── document/SKILL.md
|
|
59
|
+
├── performance-check/SKILL.md
|
|
60
|
+
├── refactor/SKILL.md
|
|
61
|
+
├── security-scan/SKILL.md
|
|
62
|
+
└── write-tests/SKILL.md
|
|
55
63
|
```
|
|
56
64
|
|
|
57
65
|
## Global Gitignore
|
|
@@ -60,7 +68,8 @@ The `init` and `gitignore` commands add these entries to your global gitignore:
|
|
|
60
68
|
|
|
61
69
|
```
|
|
62
70
|
AGENTS.md
|
|
63
|
-
.
|
|
71
|
+
.claude/
|
|
72
|
+
.opencode/
|
|
64
73
|
project-rules.md
|
|
65
74
|
```
|
|
66
75
|
|
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -4,7 +4,11 @@ const { execSync } = require('child_process');
|
|
|
4
4
|
const readline = require('readline');
|
|
5
5
|
|
|
6
6
|
const TEMPLATES_DIR = path.join(__dirname, '..', 'templates');
|
|
7
|
-
const
|
|
7
|
+
const SKILLS_DIR = path.join(TEMPLATES_DIR, 'skills');
|
|
8
|
+
const GITIGNORE_ENTRIES = ['AGENTS.md', '.claude/', '.opencode/', 'project-rules.md'];
|
|
9
|
+
|
|
10
|
+
// Skill directories for each supported tool
|
|
11
|
+
const SKILL_TARGETS = ['.claude/skills', '.opencode/skills'];
|
|
8
12
|
|
|
9
13
|
// ── Helpers ──────────────────────────────────────────────
|
|
10
14
|
|
|
@@ -32,6 +36,7 @@ function ask(question) {
|
|
|
32
36
|
|
|
33
37
|
function getAllFiles(dir, base = dir) {
|
|
34
38
|
const results = [];
|
|
39
|
+
if (!fs.existsSync(dir)) return results;
|
|
35
40
|
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
36
41
|
const fullPath = path.join(dir, entry.name);
|
|
37
42
|
if (entry.isDirectory()) {
|
|
@@ -53,11 +58,9 @@ async function setupGlobalGitignore() {
|
|
|
53
58
|
try {
|
|
54
59
|
gitignorePath = execSync('git config --global core.excludesFile', { encoding: 'utf-8' }).trim();
|
|
55
60
|
} catch {
|
|
56
|
-
// No global gitignore configured yet
|
|
57
61
|
gitignorePath = '';
|
|
58
62
|
}
|
|
59
63
|
|
|
60
|
-
// Resolve ~ to home directory
|
|
61
64
|
if (gitignorePath.startsWith('~')) {
|
|
62
65
|
gitignorePath = path.join(process.env.HOME || process.env.USERPROFILE, gitignorePath.slice(1));
|
|
63
66
|
}
|
|
@@ -70,7 +73,6 @@ async function setupGlobalGitignore() {
|
|
|
70
73
|
log(`Global gitignore created: ${gitignorePath}`);
|
|
71
74
|
}
|
|
72
75
|
|
|
73
|
-
// Read existing content or start fresh
|
|
74
76
|
let content = '';
|
|
75
77
|
if (fs.existsSync(gitignorePath)) {
|
|
76
78
|
content = fs.readFileSync(gitignorePath, 'utf-8');
|
|
@@ -98,28 +100,52 @@ async function setupGlobalGitignore() {
|
|
|
98
100
|
|
|
99
101
|
// ── Copy Files ───────────────────────────────────────────
|
|
100
102
|
|
|
101
|
-
|
|
103
|
+
function copyFile(src, dest, relLabel, force) {
|
|
104
|
+
const destDir = path.dirname(dest);
|
|
105
|
+
fs.mkdirSync(destDir, { recursive: true });
|
|
106
|
+
fs.copyFileSync(src, dest);
|
|
107
|
+
success(relLabel);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
async function copyAllFiles(targetDir, { force = false } = {}) {
|
|
111
|
+
// 1) Copy AGENTS.md to project root
|
|
102
112
|
console.log('\n \uD83D\uDCC1 Copying agent files...\n');
|
|
103
113
|
|
|
104
|
-
const
|
|
114
|
+
const agentsMdSrc = path.join(TEMPLATES_DIR, 'AGENTS.md');
|
|
115
|
+
const agentsMdDest = path.join(targetDir, 'AGENTS.md');
|
|
105
116
|
|
|
106
|
-
|
|
107
|
-
const
|
|
108
|
-
|
|
109
|
-
|
|
117
|
+
if (!force && fs.existsSync(agentsMdDest)) {
|
|
118
|
+
const overwrite = await ask('AGENTS.md already exists. Overwrite?');
|
|
119
|
+
if (!overwrite) {
|
|
120
|
+
warn('AGENTS.md skipped');
|
|
121
|
+
} else {
|
|
122
|
+
copyFile(agentsMdSrc, agentsMdDest, 'AGENTS.md', force);
|
|
123
|
+
}
|
|
124
|
+
} else {
|
|
125
|
+
copyFile(agentsMdSrc, agentsMdDest, 'AGENTS.md', force);
|
|
126
|
+
}
|
|
110
127
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
128
|
+
// 2) Copy skills to each tool's directory
|
|
129
|
+
const skillFiles = getAllFiles(SKILLS_DIR);
|
|
130
|
+
|
|
131
|
+
for (const skillTarget of SKILL_TARGETS) {
|
|
132
|
+
console.log(`\n \uD83D\uDCC2 ${skillTarget}/\n`);
|
|
133
|
+
|
|
134
|
+
for (const relPath of skillFiles) {
|
|
135
|
+
const src = path.join(SKILLS_DIR, relPath);
|
|
136
|
+
const dest = path.join(targetDir, skillTarget, relPath);
|
|
137
|
+
const label = path.join(skillTarget, relPath);
|
|
138
|
+
|
|
139
|
+
if (!force && fs.existsSync(dest)) {
|
|
140
|
+
const overwrite = await ask(`${label} already exists. Overwrite?`);
|
|
141
|
+
if (!overwrite) {
|
|
142
|
+
warn(`${label} skipped`);
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
117
145
|
}
|
|
118
|
-
}
|
|
119
146
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
success(relPath);
|
|
147
|
+
copyFile(src, dest, label, force);
|
|
148
|
+
}
|
|
123
149
|
}
|
|
124
150
|
|
|
125
151
|
console.log('');
|
|
@@ -132,7 +158,7 @@ async function init({ force = false } = {}) {
|
|
|
132
158
|
|
|
133
159
|
const targetDir = process.cwd();
|
|
134
160
|
|
|
135
|
-
await
|
|
161
|
+
await copyAllFiles(targetDir, { force });
|
|
136
162
|
await setupGlobalGitignore();
|
|
137
163
|
|
|
138
164
|
console.log(' \u2705 Setup complete!\n');
|
|
@@ -143,7 +169,7 @@ async function update() {
|
|
|
143
169
|
|
|
144
170
|
const targetDir = process.cwd();
|
|
145
171
|
|
|
146
|
-
await
|
|
172
|
+
await copyAllFiles(targetDir, { force: true });
|
|
147
173
|
|
|
148
174
|
console.log(' \u2705 Update complete!\n');
|
|
149
175
|
}
|