opencode-agent-kit 1.0.19 → 1.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.
- package/LICENSE +21 -0
- package/bin/commands/doctor.mjs +164 -0
- package/bin/commands/init.mjs +96 -95
- package/bin/commands/uninstall.mjs +79 -0
- package/bin/commands/upgrade.mjs +65 -0
- package/bin/init.mjs +33 -10
- package/package.json +15 -2
- package/template/opencode.example.json +29 -33
- package/template/opencode.json +14 -14
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024-2025 defuj
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { existsSync, readFileSync, readdirSync } from 'fs';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
import { execSync } from 'child_process';
|
|
4
|
+
|
|
5
|
+
const PKG_NAME = 'opencode-agent-kit';
|
|
6
|
+
|
|
7
|
+
function check(condition, passMsg, failMsg) {
|
|
8
|
+
if (condition) {
|
|
9
|
+
console.log(` ✓ ${passMsg}`);
|
|
10
|
+
return true;
|
|
11
|
+
}
|
|
12
|
+
console.log(` ✗ ${failMsg}`);
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function warn(msg) {
|
|
17
|
+
console.log(` ⚠ ${msg}`);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export async function doctor(options) {
|
|
21
|
+
const targetDir = options.dir || process.cwd();
|
|
22
|
+
const { fix } = options;
|
|
23
|
+
|
|
24
|
+
console.log(`\n ${PKG_NAME} doctor`);
|
|
25
|
+
console.log(` ${'─'.repeat(50)}`);
|
|
26
|
+
console.log(` Target: ${targetDir}\n`);
|
|
27
|
+
|
|
28
|
+
let allGood = true;
|
|
29
|
+
|
|
30
|
+
// 1. Check Node.js version
|
|
31
|
+
const nodeVersion = process.version;
|
|
32
|
+
const major = parseInt(nodeVersion.slice(1).split('.')[0], 10);
|
|
33
|
+
allGood &= check(
|
|
34
|
+
major >= 18,
|
|
35
|
+
`Node.js ${nodeVersion} (>= 18)`,
|
|
36
|
+
`Node.js ${nodeVersion} — need >= 18`,
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
// 2. Check package.json exists
|
|
40
|
+
const pkgPath = join(targetDir, 'package.json');
|
|
41
|
+
allGood &= check(
|
|
42
|
+
existsSync(pkgPath),
|
|
43
|
+
'package.json found',
|
|
44
|
+
'package.json not found',
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
// 3. Check opencode.json
|
|
48
|
+
const configPath = join(targetDir, 'opencode.json');
|
|
49
|
+
const hasConfig = existsSync(configPath);
|
|
50
|
+
allGood &= check(hasConfig, 'opencode.json found', 'opencode.json not found');
|
|
51
|
+
|
|
52
|
+
if (hasConfig) {
|
|
53
|
+
try {
|
|
54
|
+
JSON.parse(readFileSync(configPath, 'utf-8'));
|
|
55
|
+
check(true, 'opencode.json is valid JSON', '');
|
|
56
|
+
} catch {
|
|
57
|
+
allGood = false;
|
|
58
|
+
console.log(' ✗ opencode.json is not valid JSON');
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// 4. Check .opencode directory
|
|
63
|
+
const opencodeDir = join(targetDir, '.opencode');
|
|
64
|
+
const hasOpencode = existsSync(opencodeDir);
|
|
65
|
+
allGood &= check(hasOpencode, '.opencode/ directory found', '.opencode/ directory not found');
|
|
66
|
+
|
|
67
|
+
if (hasOpencode) {
|
|
68
|
+
// 4a. Check agents
|
|
69
|
+
const agentsDir = join(opencodeDir, 'agents');
|
|
70
|
+
check(
|
|
71
|
+
existsSync(agentsDir),
|
|
72
|
+
'.opencode/agents/ found',
|
|
73
|
+
'.opencode/agents/ missing',
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
// 4b. Check instructions
|
|
77
|
+
const instrDir = join(opencodeDir, 'instructions');
|
|
78
|
+
check(
|
|
79
|
+
existsSync(instrDir),
|
|
80
|
+
'.opencode/instructions/ found',
|
|
81
|
+
'.opencode/instructions/ missing',
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
// 4c. Check skills
|
|
85
|
+
const skillsDir = join(opencodeDir, 'skills');
|
|
86
|
+
check(
|
|
87
|
+
existsSync(skillsDir),
|
|
88
|
+
'.opencode/skills/ found',
|
|
89
|
+
'.opencode/skills/ missing',
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
// 4d. Count agents
|
|
93
|
+
if (existsSync(agentsDir)) {
|
|
94
|
+
const agents = readdirSync(agentsDir).filter(f => f.endsWith('.md'));
|
|
95
|
+
check(
|
|
96
|
+
agents.length >= 10,
|
|
97
|
+
`${agents.length} agent prompts found (expected 14)`,
|
|
98
|
+
`Only ${agents.length} agent prompts found (expected 14)`,
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// 4e. Check kit-version
|
|
103
|
+
const versionFile = join(opencodeDir, '.kit-version');
|
|
104
|
+
if (existsSync(versionFile)) {
|
|
105
|
+
const installedVersion = readFileSync(versionFile, 'utf-8').trim();
|
|
106
|
+
try {
|
|
107
|
+
const latest = execSync(`npm view ${PKG_NAME} version`, {
|
|
108
|
+
encoding: 'utf-8',
|
|
109
|
+
timeout: 5000,
|
|
110
|
+
}).trim();
|
|
111
|
+
if (installedVersion !== latest) {
|
|
112
|
+
warn(`Kit v${installedVersion} installed, v${latest} available`);
|
|
113
|
+
if (fix) {
|
|
114
|
+
console.log(' → Run `npx opencode-agent-kit upgrade` to update');
|
|
115
|
+
}
|
|
116
|
+
} else {
|
|
117
|
+
check(true, `Kit version v${installedVersion} (up to date)`, '');
|
|
118
|
+
}
|
|
119
|
+
} catch {
|
|
120
|
+
warn('Could not check latest version (npm registry unreachable)');
|
|
121
|
+
}
|
|
122
|
+
} else {
|
|
123
|
+
warn('.kit-version not found');
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// 5. Check .gitignore
|
|
128
|
+
const gitignorePath = join(targetDir, '.gitignore');
|
|
129
|
+
if (existsSync(gitignorePath)) {
|
|
130
|
+
const content = readFileSync(gitignorePath, 'utf-8');
|
|
131
|
+
check(
|
|
132
|
+
content.includes('.opencode') || content.includes('opencode.json'),
|
|
133
|
+
'.gitignore covers .opencode/ files',
|
|
134
|
+
'.gitignore may not cover .opencode/ files',
|
|
135
|
+
);
|
|
136
|
+
} else {
|
|
137
|
+
warn('.gitignore not found');
|
|
138
|
+
if (fix) {
|
|
139
|
+
console.log(' → Run `opencode-agent-kit init` to create one');
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// 6. Check global agentmemory
|
|
144
|
+
try {
|
|
145
|
+
execSync('agentmemory --version', { stdio: 'pipe', timeout: 3000 });
|
|
146
|
+
check(true, 'agentmemory (global) is installed', '');
|
|
147
|
+
} catch {
|
|
148
|
+
warn('agentmemory not installed globally');
|
|
149
|
+
if (fix) {
|
|
150
|
+
console.log(' → Run: npm install -g @agentmemory/agentmemory');
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Summary
|
|
155
|
+
console.log(`\n ${'─'.repeat(50)}`);
|
|
156
|
+
if (allGood) {
|
|
157
|
+
console.log(`\n ✅ All checks passed. Your setup looks good!\n`);
|
|
158
|
+
} else {
|
|
159
|
+
console.log(`\n ⚠ Some checks failed. Review the issues above.\n`);
|
|
160
|
+
if (!fix) {
|
|
161
|
+
console.log(` Tip: Run with --fix to enable actionable suggestions.\n`);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
package/bin/commands/init.mjs
CHANGED
|
@@ -6,15 +6,43 @@ import {
|
|
|
6
6
|
writeFileSync,
|
|
7
7
|
readdirSync,
|
|
8
8
|
appendFileSync,
|
|
9
|
-
} from
|
|
10
|
-
import { join, dirname } from
|
|
11
|
-
import { fileURLToPath } from
|
|
12
|
-
import { execSync } from
|
|
9
|
+
} from 'fs';
|
|
10
|
+
import { join, dirname } from 'path';
|
|
11
|
+
import { fileURLToPath } from 'url';
|
|
12
|
+
import { execSync } from 'child_process';
|
|
13
13
|
|
|
14
14
|
const __filename = fileURLToPath(import.meta.url);
|
|
15
15
|
const __dirname = dirname(__filename);
|
|
16
|
-
const PKG_ROOT = join(__dirname,
|
|
17
|
-
const TEMPLATE_DIR = join(PKG_ROOT,
|
|
16
|
+
const PKG_ROOT = join(__dirname, '..', '..');
|
|
17
|
+
const TEMPLATE_DIR = join(PKG_ROOT, 'template');
|
|
18
|
+
const PKG_NAME = 'opencode-agent-kit';
|
|
19
|
+
|
|
20
|
+
// ANSI colors
|
|
21
|
+
const C = {
|
|
22
|
+
reset: '\x1b[0m',
|
|
23
|
+
dim: '\x1b[2m',
|
|
24
|
+
green: '\x1b[32m',
|
|
25
|
+
yellow: '\x1b[33m',
|
|
26
|
+
red: '\x1b[31m',
|
|
27
|
+
cyan: '\x1b[36m',
|
|
28
|
+
bold: '\x1b[1m',
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
function info(msg) {
|
|
32
|
+
console.log(` ${C.cyan}→${C.reset} ${msg}`);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function success(msg) {
|
|
36
|
+
console.log(` ${C.green}✓${C.reset} ${msg}`);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function warn(msg) {
|
|
40
|
+
console.log(` ${C.yellow}⚠${C.reset} ${msg}`);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function error(msg) {
|
|
44
|
+
console.log(` ${C.red}✗${C.reset} ${msg}`);
|
|
45
|
+
}
|
|
18
46
|
|
|
19
47
|
function copyRecursive(src, dest) {
|
|
20
48
|
if (!existsSync(src)) return;
|
|
@@ -146,157 +174,130 @@ export async function init(options) {
|
|
|
146
174
|
const force = options.force;
|
|
147
175
|
const skipInstall = options.skipInstall;
|
|
148
176
|
|
|
149
|
-
console.log(`\n
|
|
177
|
+
console.log(`\n ${C.bold}${PKG_NAME} init${C.reset}`);
|
|
178
|
+
console.log(` ${C.dim}${'─'.repeat(50)}${C.reset}`);
|
|
150
179
|
|
|
151
180
|
// 1. Validate target
|
|
152
181
|
if (!existsSync(targetDir)) {
|
|
153
182
|
console.error(` ✗ Target directory does not exist: ${targetDir}`);
|
|
183
|
+
error(`Target directory does not exist: ${targetDir}`);
|
|
154
184
|
process.exit(1);
|
|
155
185
|
}
|
|
156
186
|
|
|
157
187
|
// 2. Check if .opencode already exists
|
|
158
|
-
const opencodeDir = join(targetDir,
|
|
159
|
-
const userConfigPath = join(targetDir,
|
|
188
|
+
const opencodeDir = join(targetDir, '.opencode');
|
|
189
|
+
const userConfigPath = join(targetDir, 'opencode.json');
|
|
160
190
|
|
|
161
191
|
if (existsSync(opencodeDir) && !force) {
|
|
162
|
-
|
|
163
|
-
const rl = await import(
|
|
192
|
+
warn(`.opencode/ already exists in ${targetDir}`);
|
|
193
|
+
const rl = await import('readline/promises');
|
|
164
194
|
const readline = rl.createInterface({
|
|
165
195
|
input: process.stdin,
|
|
166
196
|
output: process.stdout,
|
|
167
197
|
});
|
|
168
|
-
const answer = await readline.question(
|
|
169
|
-
` ? Overwrite existing files? [y/N] `,
|
|
170
|
-
);
|
|
198
|
+
const answer = await readline.question(` ? Overwrite existing files? [y/N] `);
|
|
171
199
|
readline.close();
|
|
172
|
-
if (answer.toLowerCase() !==
|
|
173
|
-
|
|
200
|
+
if (answer.toLowerCase() !== 'y') {
|
|
201
|
+
error('Aborted.');
|
|
174
202
|
process.exit(0);
|
|
175
203
|
}
|
|
176
204
|
}
|
|
177
205
|
|
|
178
206
|
// 3. Validate template exists
|
|
179
207
|
if (!existsSync(TEMPLATE_DIR)) {
|
|
180
|
-
|
|
181
|
-
|
|
208
|
+
error(`Template directory not found at ${TEMPLATE_DIR}`);
|
|
209
|
+
error('This is a bug. Please reinstall the package.');
|
|
182
210
|
process.exit(1);
|
|
183
211
|
}
|
|
184
212
|
|
|
185
213
|
// 4. Copy .opencode/ from template
|
|
186
|
-
|
|
187
|
-
copyRecursive(join(TEMPLATE_DIR,
|
|
214
|
+
info('Copying .opencode/ configuration...');
|
|
215
|
+
copyRecursive(join(TEMPLATE_DIR, '.opencode'), opencodeDir);
|
|
188
216
|
|
|
189
217
|
// 5. Merge opencode.json
|
|
190
|
-
const templateConfigPath = join(TEMPLATE_DIR,
|
|
218
|
+
const templateConfigPath = join(TEMPLATE_DIR, 'opencode.json');
|
|
191
219
|
if (existsSync(templateConfigPath)) {
|
|
192
|
-
|
|
193
|
-
const merged = mergeOencodeConfig(
|
|
194
|
-
|
|
195
|
-
userConfigPath,
|
|
196
|
-
force,
|
|
197
|
-
);
|
|
198
|
-
writeFileSync(
|
|
199
|
-
userConfigPath,
|
|
200
|
-
JSON.stringify(merged, null, 2) + "\n",
|
|
201
|
-
"utf-8",
|
|
202
|
-
);
|
|
220
|
+
info('Merging opencode.json...');
|
|
221
|
+
const merged = mergeOencodeConfig(templateConfigPath, userConfigPath, force);
|
|
222
|
+
writeFileSync(userConfigPath, JSON.stringify(merged, null, 2) + '\n', 'utf-8');
|
|
203
223
|
}
|
|
204
224
|
|
|
205
225
|
// 6. Copy opencode.example.json
|
|
206
|
-
const exampleSrc = join(TEMPLATE_DIR,
|
|
207
|
-
const exampleDest = join(targetDir,
|
|
226
|
+
const exampleSrc = join(TEMPLATE_DIR, 'opencode.example.json');
|
|
227
|
+
const exampleDest = join(targetDir, 'opencode.example.json');
|
|
208
228
|
if (existsSync(exampleSrc)) {
|
|
209
|
-
|
|
229
|
+
info('Copying opencode.example.json...');
|
|
210
230
|
copyFileSync(exampleSrc, exampleDest);
|
|
211
231
|
}
|
|
212
232
|
|
|
213
233
|
// 7. Install dependencies
|
|
214
234
|
if (!skipInstall) {
|
|
215
235
|
const pm = detectPackageManager(opencodeDir);
|
|
216
|
-
|
|
236
|
+
info(`Installing .opencode/ dependencies with ${pm}...`);
|
|
217
237
|
try {
|
|
218
|
-
execSync(`${pm} install`, { cwd: opencodeDir, stdio:
|
|
238
|
+
execSync(`${pm} install`, { cwd: opencodeDir, stdio: 'pipe' });
|
|
239
|
+
success('.opencode/ dependencies installed');
|
|
219
240
|
} catch (err) {
|
|
220
|
-
|
|
221
|
-
|
|
241
|
+
warn(`Dependency install failed: ${err.message}`);
|
|
242
|
+
warn(`You can run "${pm} install" manually in .opencode/`);
|
|
222
243
|
}
|
|
223
244
|
}
|
|
224
245
|
|
|
225
|
-
//
|
|
246
|
+
// 8. Install agentmemory globally
|
|
226
247
|
if (!skipInstall) {
|
|
227
|
-
|
|
248
|
+
info('Setting up agentmemory (persistent memory)...');
|
|
228
249
|
try {
|
|
229
|
-
execSync(
|
|
230
|
-
|
|
250
|
+
execSync('agentmemory --version', { stdio: 'pipe' });
|
|
251
|
+
success('agentmemory already installed');
|
|
231
252
|
} catch {
|
|
232
253
|
try {
|
|
233
|
-
execSync(
|
|
234
|
-
stdio:
|
|
254
|
+
execSync('npm install -g @agentmemory/agentmemory', {
|
|
255
|
+
stdio: 'pipe',
|
|
235
256
|
timeout: 60000,
|
|
236
257
|
});
|
|
237
|
-
|
|
258
|
+
success('agentmemory installed globally');
|
|
238
259
|
} catch (err) {
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
` Run "npm install -g @agentmemory/agentmemory" manually`,
|
|
242
|
-
);
|
|
260
|
+
warn(`agentmemory global install failed: ${err.message}`);
|
|
261
|
+
warn('Run "npm install -g @agentmemory/agentmemory" manually');
|
|
243
262
|
}
|
|
244
263
|
}
|
|
245
264
|
}
|
|
246
265
|
|
|
247
|
-
//
|
|
248
|
-
const gitignorePath = join(targetDir,
|
|
249
|
-
const gitignoreEntries = [
|
|
250
|
-
".opencode/*",
|
|
251
|
-
"opencode.json",
|
|
252
|
-
"opencode.example.json",
|
|
253
|
-
"data/",
|
|
254
|
-
];
|
|
266
|
+
// 9. Update .gitignore
|
|
267
|
+
const gitignorePath = join(targetDir, '.gitignore');
|
|
268
|
+
const gitignoreEntries = ['.opencode/*', 'opencode.json', 'opencode.example.json', 'data/'];
|
|
255
269
|
if (!existsSync(gitignorePath)) {
|
|
256
|
-
writeFileSync(gitignorePath, gitignoreEntries.join(
|
|
257
|
-
|
|
270
|
+
writeFileSync(gitignorePath, gitignoreEntries.join('\n') + '\n', 'utf-8');
|
|
271
|
+
success('Created .gitignore');
|
|
258
272
|
} else {
|
|
259
|
-
const gitignoreContent = readFileSync(gitignorePath,
|
|
273
|
+
const gitignoreContent = readFileSync(gitignorePath, 'utf-8');
|
|
260
274
|
let appended = false;
|
|
261
275
|
for (const entry of gitignoreEntries) {
|
|
262
276
|
if (!gitignoreContent.includes(entry)) {
|
|
263
|
-
appendFileSync(gitignorePath, entry +
|
|
277
|
+
appendFileSync(gitignorePath, entry + '\n', 'utf-8');
|
|
264
278
|
appended = true;
|
|
265
279
|
}
|
|
266
280
|
}
|
|
267
|
-
if (appended)
|
|
268
|
-
console.log(` 📄 Updated .gitignore...`);
|
|
269
|
-
}
|
|
281
|
+
if (appended) success('Updated .gitignore');
|
|
270
282
|
}
|
|
271
283
|
|
|
272
|
-
//
|
|
273
|
-
const pkgJson = JSON.parse(
|
|
274
|
-
|
|
275
|
-
);
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
console.log(
|
|
281
|
-
console.log(`
|
|
282
|
-
console.log(`
|
|
283
|
-
console.log(
|
|
284
|
-
|
|
285
|
-
);
|
|
286
|
-
console.log(
|
|
287
|
-
|
|
288
|
-
);
|
|
289
|
-
console.log(`
|
|
290
|
-
console.log(
|
|
291
|
-
console.log(` • .opencode/commands/ — 35+ slash commands`);
|
|
292
|
-
console.log(` • .opencode/rules/ — Scoped coding rules`);
|
|
293
|
-
console.log(` • .opencode/contexts/ — Dev/review/research contexts`);
|
|
294
|
-
console.log(` • .opencode/docs/ — Agent documentation`);
|
|
295
|
-
console.log(` • .opencode/plugins/ — agentmemory capture plugin (22 hooks)`);
|
|
296
|
-
console.log(` • .opencode/hooks/ — agentmemory auto-start wrapper`);
|
|
297
|
-
console.log(` • agentmemory (global) — Persistent cross-session memory`);
|
|
298
|
-
console.log(`\n Next steps:`);
|
|
299
|
-
console.log(` cd ${targetDir}`);
|
|
300
|
-
console.log(` opencode # agentmemory auto-starts on first use`);
|
|
301
|
-
console.log(` # Viewer: http://localhost:3113`);
|
|
284
|
+
// 10. Write .kit-version for agent update checking
|
|
285
|
+
const pkgJson = JSON.parse(readFileSync(join(PKG_ROOT, 'package.json'), 'utf-8'));
|
|
286
|
+
const versionFile = join(opencodeDir, '.kit-version');
|
|
287
|
+
writeFileSync(versionFile, pkgJson.version + '\n', 'utf-8');
|
|
288
|
+
|
|
289
|
+
// 11. Done — summary
|
|
290
|
+
console.log(`\n ${C.bold}${C.green}✅ opencode-agent-kit v${pkgJson.version} installed!${C.reset}\n`);
|
|
291
|
+
console.log(` ${C.dim}Location:${C.reset} ${targetDir}`);
|
|
292
|
+
console.log(` ${C.dim}${'─'.repeat(30)}${C.reset}`);
|
|
293
|
+
console.log(` ${C.bold}What you got:${C.reset}`);
|
|
294
|
+
console.log(` • ${C.cyan}opencode.json${C.reset} — 13 agents + MCP servers`);
|
|
295
|
+
console.log(` • ${C.cyan}.opencode/agents/${C.reset} — 14 agent prompt files`);
|
|
296
|
+
console.log(` • ${C.cyan}.opencode/skills/${C.reset} — 60+ skill playbooks`);
|
|
297
|
+
console.log(` • ${C.cyan}.opencode/commands/${C.reset} — 35+ slash commands`);
|
|
298
|
+
console.log(` • ${C.cyan}.opencode/rules/${C.reset} — Scoped coding rules`);
|
|
299
|
+
console.log(` • ${C.cyan}.opencode/hooks/${C.reset} — Automation hooks`);
|
|
300
|
+
console.log(` • ${C.cyan}.opencode/docs/${C.reset} — Agent documentation`);
|
|
301
|
+
console.log(` • ${C.cyan}agentmemory${C.reset} (global) — Persistent memory`);
|
|
302
|
+
console.log(`\n ${C.bold}${C.green}→${C.reset} Next step: run ${C.cyan}opencode${C.reset} to start\n`);
|
|
302
303
|
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { existsSync, readFileSync, unlinkSync, rmSync } from 'fs';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
import { createInterface } from 'readline/promises';
|
|
4
|
+
|
|
5
|
+
const PKG_NAME = 'opencode-agent-kit';
|
|
6
|
+
|
|
7
|
+
export async function uninstall(options) {
|
|
8
|
+
const targetDir = options.dir || process.cwd();
|
|
9
|
+
const force = options.force;
|
|
10
|
+
|
|
11
|
+
console.log(`\n ${PKG_NAME} uninstall`);
|
|
12
|
+
console.log(` ${'─'.repeat(50)}`);
|
|
13
|
+
console.log(` Target: ${targetDir}\n`);
|
|
14
|
+
|
|
15
|
+
if (!force) {
|
|
16
|
+
const readline = createInterface({ input: process.stdin, output: process.stdout });
|
|
17
|
+
const answer = await readline.question(
|
|
18
|
+
` ⚠ This will remove .opencode/ and opencode.json from\n ${targetDir}\n\n ? Continue? [y/N] `,
|
|
19
|
+
);
|
|
20
|
+
readline.close();
|
|
21
|
+
if (answer.toLowerCase() !== 'y') {
|
|
22
|
+
console.log(` ✗ Aborted.\n`);
|
|
23
|
+
process.exit(0);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Remove .opencode/
|
|
28
|
+
const opencodeDir = join(targetDir, '.opencode');
|
|
29
|
+
if (existsSync(opencodeDir)) {
|
|
30
|
+
console.log(` Removing .opencode/ ...`);
|
|
31
|
+
rmSync(opencodeDir, { recursive: true, force: true });
|
|
32
|
+
console.log(` ✓ .opencode/ removed`);
|
|
33
|
+
} else {
|
|
34
|
+
console.log(` - .opencode/ not found, skipping`);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Remove opencode.json
|
|
38
|
+
const configPath = join(targetDir, 'opencode.json');
|
|
39
|
+
if (existsSync(configPath)) {
|
|
40
|
+
console.log(` Removing opencode.json ...`);
|
|
41
|
+
unlinkSync(configPath);
|
|
42
|
+
console.log(` ✓ opencode.json removed`);
|
|
43
|
+
} else {
|
|
44
|
+
console.log(` - opencode.json not found, skipping`);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Remove opencode.example.json
|
|
48
|
+
const examplePath = join(targetDir, 'opencode.example.json');
|
|
49
|
+
if (existsSync(examplePath)) {
|
|
50
|
+
console.log(` Removing opencode.example.json ...`);
|
|
51
|
+
unlinkSync(examplePath);
|
|
52
|
+
console.log(` ✓ opencode.example.json removed`);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Clean up .gitignore entries (remove lines containing these patterns)
|
|
56
|
+
const gitignorePath = join(targetDir, '.gitignore');
|
|
57
|
+
if (existsSync(gitignorePath)) {
|
|
58
|
+
const entriesToRemove = ['.opencode/', 'opencode.json', 'opencode.example.json'];
|
|
59
|
+
const content = readFileSync(gitignorePath, 'utf-8');
|
|
60
|
+
const lines = content.split('\n').filter(line => {
|
|
61
|
+
return !entriesToRemove.some(e => line.trim().startsWith(e));
|
|
62
|
+
});
|
|
63
|
+
const newContent = lines.join('\n');
|
|
64
|
+
if (newContent !== content) {
|
|
65
|
+
// Write back without these entries
|
|
66
|
+
const { writeFileSync } = await import('fs');
|
|
67
|
+
writeFileSync(gitignorePath, newContent, 'utf-8');
|
|
68
|
+
console.log(` ✓ .gitignore cleaned`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Clean .kit-version
|
|
73
|
+
const versionFile = join(opencodeDir, '.kit-version');
|
|
74
|
+
if (existsSync(versionFile)) {
|
|
75
|
+
unlinkSync(versionFile);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
console.log(`\n ✅ opencode-agent-kit has been removed from ${targetDir}\n`);
|
|
79
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { execSync } from 'child_process';
|
|
2
|
+
import { readFileSync } from 'fs';
|
|
3
|
+
const PKG_NAME = 'opencode-agent-kit';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Get the currently installed version from package.json
|
|
7
|
+
*/
|
|
8
|
+
function getCurrentVersion() {
|
|
9
|
+
const pkgPath = new globalThis.URL('../../package.json', import.meta.url);
|
|
10
|
+
const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
|
|
11
|
+
return pkg.version;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Get the latest available version from npm
|
|
16
|
+
*/
|
|
17
|
+
function getLatestVersion() {
|
|
18
|
+
try {
|
|
19
|
+
return execSync(`npm view ${PKG_NAME} version`, {
|
|
20
|
+
encoding: 'utf-8',
|
|
21
|
+
timeout: 10000,
|
|
22
|
+
}).trim();
|
|
23
|
+
} catch {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export async function upgrade(options) {
|
|
29
|
+
const { verbose } = options;
|
|
30
|
+
|
|
31
|
+
console.log(`\n ${PKG_NAME} upgrade`);
|
|
32
|
+
console.log(` ${'─'.repeat(50)}\n`);
|
|
33
|
+
|
|
34
|
+
const current = getCurrentVersion();
|
|
35
|
+
console.log(` Current version: v${current}`);
|
|
36
|
+
|
|
37
|
+
console.log(` Checking npm registry...`);
|
|
38
|
+
const latest = getLatestVersion();
|
|
39
|
+
|
|
40
|
+
if (!latest) {
|
|
41
|
+
console.error(` \n ✗ Could not reach npm registry.`);
|
|
42
|
+
console.error(` Check your internet connection and try again.`);
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
console.log(` Latest version: v${latest}`);
|
|
47
|
+
|
|
48
|
+
if (current === latest) {
|
|
49
|
+
console.log(`\n ✓ You're up to date (v${current}).\n`);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
console.log(`\n → Upgrading from v${current} to v${latest}...`);
|
|
54
|
+
try {
|
|
55
|
+
execSync(`npm install -g ${PKG_NAME}@latest`, {
|
|
56
|
+
stdio: verbose ? 'inherit' : 'pipe',
|
|
57
|
+
timeout: 60000,
|
|
58
|
+
});
|
|
59
|
+
console.log(` ✓ Upgraded to v${latest}\n`);
|
|
60
|
+
} catch (err) {
|
|
61
|
+
console.error(` ✗ Upgrade failed: ${err.message}`);
|
|
62
|
+
console.error(` Try: npm install -g ${PKG_NAME}@latest`);
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
}
|
package/bin/init.mjs
CHANGED
|
@@ -1,21 +1,44 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import { Command } from
|
|
4
|
-
import { init } from
|
|
3
|
+
import { Command } from 'commander';
|
|
4
|
+
import { init } from './commands/init.mjs';
|
|
5
|
+
import { upgrade } from './commands/upgrade.mjs';
|
|
6
|
+
import { doctor } from './commands/doctor.mjs';
|
|
7
|
+
import { uninstall } from './commands/uninstall.mjs';
|
|
5
8
|
|
|
6
9
|
const program = new Command();
|
|
7
10
|
|
|
8
11
|
program
|
|
9
|
-
.name(
|
|
10
|
-
.description(
|
|
11
|
-
.version(
|
|
12
|
+
.name('opencode-agent-kit')
|
|
13
|
+
.description('Multi-stack OpenCode agent toolkit — 13 specialized AI agents, 60+ skills, 35+ commands')
|
|
14
|
+
.version('1.0.0');
|
|
12
15
|
|
|
13
16
|
program
|
|
14
|
-
.command(
|
|
15
|
-
.description(
|
|
16
|
-
.option(
|
|
17
|
-
.option(
|
|
18
|
-
.option(
|
|
17
|
+
.command('init')
|
|
18
|
+
.description('Initialize .opencode/ configuration in current project')
|
|
19
|
+
.option('-f, --force', 'Overwrite existing files without prompt')
|
|
20
|
+
.option('-d, --dir <path>', 'Target project directory', process.cwd())
|
|
21
|
+
.option('--skip-install', 'Skip npm/bun install step in .opencode/')
|
|
19
22
|
.action(init);
|
|
20
23
|
|
|
24
|
+
program
|
|
25
|
+
.command('upgrade')
|
|
26
|
+
.description('Check for and apply the latest version of opencode-agent-kit')
|
|
27
|
+
.option('-v, --verbose', 'Show detailed upgrade output')
|
|
28
|
+
.action(upgrade);
|
|
29
|
+
|
|
30
|
+
program
|
|
31
|
+
.command('doctor')
|
|
32
|
+
.description('Diagnose common setup issues in the target project')
|
|
33
|
+
.option('-d, --dir <path>', 'Target project directory', process.cwd())
|
|
34
|
+
.option('--fix', 'Show actionable fix suggestions')
|
|
35
|
+
.action(doctor);
|
|
36
|
+
|
|
37
|
+
program
|
|
38
|
+
.command('uninstall')
|
|
39
|
+
.description('Remove opencode-agent-kit configuration from the target project')
|
|
40
|
+
.option('-d, --dir <path>', 'Target project directory', process.cwd())
|
|
41
|
+
.option('-f, --force', 'Skip confirmation prompt')
|
|
42
|
+
.action(uninstall);
|
|
43
|
+
|
|
21
44
|
program.parse();
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-agent-kit",
|
|
3
|
-
"version": "1.0
|
|
4
|
-
"description": "Multi-stack OpenCode agent toolkit
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"description": "Multi-stack OpenCode agent toolkit \u2014 13 specialized AI agents (Nuxt, React, Node.js, Laravel, CI3, Android, Flutter, DevOps, SEO, SonarQube) with 62 skills, 37 commands, and 7 MCP servers",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"opencode-agent-kit": "./bin/init.mjs"
|
|
@@ -25,6 +25,13 @@
|
|
|
25
25
|
"engines": {
|
|
26
26
|
"node": ">=18"
|
|
27
27
|
},
|
|
28
|
+
"scripts": {
|
|
29
|
+
"lint": "eslint bin/ --ext .mjs,.js",
|
|
30
|
+
"format": "prettier --write 'bin/**/*.mjs' '*.md' '*.json'",
|
|
31
|
+
"format:check": "prettier --check 'bin/**/*.mjs' '*.md' '*.json'",
|
|
32
|
+
"generate-template": "bash scripts/generate-template.sh",
|
|
33
|
+
"prepare": "node -e \"try { require('husky').install() } catch {}\""
|
|
34
|
+
},
|
|
28
35
|
"keywords": [
|
|
29
36
|
"opencode",
|
|
30
37
|
"ai-agent",
|
|
@@ -56,5 +63,11 @@
|
|
|
56
63
|
"dependencies": {
|
|
57
64
|
"commander": "^13.0.0",
|
|
58
65
|
"fs-extra": "^11.0.0"
|
|
66
|
+
},
|
|
67
|
+
"devDependencies": {
|
|
68
|
+
"@eslint/js": "^10.0.1",
|
|
69
|
+
"eslint": "^9.0.0",
|
|
70
|
+
"eslint-config-prettier": "^9.1.0",
|
|
71
|
+
"prettier": "^3.4.0"
|
|
59
72
|
}
|
|
60
73
|
}
|
|
@@ -10,7 +10,6 @@
|
|
|
10
10
|
"*.env.*": "deny",
|
|
11
11
|
"*.env.example": "allow"
|
|
12
12
|
},
|
|
13
|
-
"edit": "allow",
|
|
14
13
|
"webfetch": "allow",
|
|
15
14
|
"skill": {
|
|
16
15
|
"*": "allow"
|
|
@@ -24,7 +23,7 @@
|
|
|
24
23
|
".opencode/instructions/INSTRUCTIONS.md",
|
|
25
24
|
".opencode/skills/coding-standards/SKILL.md",
|
|
26
25
|
".opencode/skills/security-review/SKILL.md",
|
|
27
|
-
".opencode/skills/
|
|
26
|
+
".opencode/skills/impeccable/SKILL.md"
|
|
28
27
|
],
|
|
29
28
|
"mcp": {
|
|
30
29
|
"nuxt": {
|
|
@@ -74,8 +73,15 @@
|
|
|
74
73
|
"Authorization": "Bearer ${SONARQUBE_TOKEN}",
|
|
75
74
|
"SONARQUBE_TOOLSETS": "analysis,issues,security-hotspots,quality-gates,rules,duplications,measures,dependency-risks,coverage,sources,languages,portfolios,system,webhooks"
|
|
76
75
|
}
|
|
76
|
+
},
|
|
77
|
+
"agentmemory": {
|
|
78
|
+
"type": "local",
|
|
79
|
+
"command": ["bash", ".opencode/hooks/agentmemory-start.sh"],
|
|
80
|
+
"enabled": true,
|
|
81
|
+
"description": "Persistent cross-session memory with 53 tools (save, recall, smart search, sessions, file history, lessons)"
|
|
77
82
|
}
|
|
78
83
|
},
|
|
84
|
+
"plugin": [".opencode/plugins/agentmemory-capture.ts"],
|
|
79
85
|
"agent": {
|
|
80
86
|
"leader": {
|
|
81
87
|
"description": "IT Leader & Technical Project Manager — analyzes requirements, designs architecture, decomposes tasks, delegates to subagents, and unifies outputs",
|
|
@@ -101,6 +107,7 @@
|
|
|
101
107
|
"figma_*": "ask",
|
|
102
108
|
"playwright_*": "allow",
|
|
103
109
|
"postman_*": "allow",
|
|
110
|
+
"agentmemory_*": "allow",
|
|
104
111
|
"task": { "*": "allow" }
|
|
105
112
|
}
|
|
106
113
|
},
|
|
@@ -126,7 +133,8 @@
|
|
|
126
133
|
"nuxt_*": "allow",
|
|
127
134
|
"nuxt-ui_*": "allow",
|
|
128
135
|
"figma_*": "ask",
|
|
129
|
-
"playwright_*": "allow"
|
|
136
|
+
"playwright_*": "allow",
|
|
137
|
+
"agentmemory_*": "allow"
|
|
130
138
|
}
|
|
131
139
|
},
|
|
132
140
|
"frontend-react": {
|
|
@@ -149,7 +157,8 @@
|
|
|
149
157
|
"npx playwright*": "allow"
|
|
150
158
|
},
|
|
151
159
|
"figma_*": "ask",
|
|
152
|
-
"playwright_*": "allow"
|
|
160
|
+
"playwright_*": "allow",
|
|
161
|
+
"agentmemory_*": "allow"
|
|
153
162
|
}
|
|
154
163
|
},
|
|
155
164
|
"backend": {
|
|
@@ -170,7 +179,8 @@
|
|
|
170
179
|
"bun *": "allow",
|
|
171
180
|
"yarn *": "allow"
|
|
172
181
|
},
|
|
173
|
-
"postman_*": "allow"
|
|
182
|
+
"postman_*": "allow",
|
|
183
|
+
"agentmemory_*": "allow"
|
|
174
184
|
}
|
|
175
185
|
},
|
|
176
186
|
"ci3": {
|
|
@@ -210,7 +220,8 @@
|
|
|
210
220
|
"git diff": "allow",
|
|
211
221
|
"git log*": "allow"
|
|
212
222
|
},
|
|
213
|
-
"postman_*": "allow"
|
|
223
|
+
"postman_*": "allow",
|
|
224
|
+
"agentmemory_*": "allow"
|
|
214
225
|
}
|
|
215
226
|
},
|
|
216
227
|
"designer": {
|
|
@@ -232,7 +243,8 @@
|
|
|
232
243
|
},
|
|
233
244
|
"stitch_*": "allow",
|
|
234
245
|
"figma_*": "ask",
|
|
235
|
-
"nuxt-ui_*": "allow"
|
|
246
|
+
"nuxt-ui_*": "allow",
|
|
247
|
+
"agentmemory_*": "allow"
|
|
236
248
|
}
|
|
237
249
|
},
|
|
238
250
|
"reviewer": {
|
|
@@ -254,7 +266,8 @@
|
|
|
254
266
|
"yarn *": "allow",
|
|
255
267
|
"npx playwright*": "allow"
|
|
256
268
|
},
|
|
257
|
-
"playwright_*": "allow"
|
|
269
|
+
"playwright_*": "allow",
|
|
270
|
+
"agentmemory_*": "allow"
|
|
258
271
|
}
|
|
259
272
|
},
|
|
260
273
|
"database": {
|
|
@@ -274,28 +287,8 @@
|
|
|
274
287
|
"pnpm *": "allow",
|
|
275
288
|
"bun *": "allow",
|
|
276
289
|
"yarn *": "allow"
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
},
|
|
280
|
-
"devops": {
|
|
281
|
-
"description": "DevOps Engineer specializing in CI/CD, deployment, Docker, monitoring, and infrastructure (subagent of IT Leader)",
|
|
282
|
-
"mode": "subagent",
|
|
283
|
-
"prompt": "{file:.opencode/agents/devops-specialist.md}",
|
|
284
|
-
"model": "opencode/claude-sonnet-4.5",
|
|
285
|
-
"temperature": 0.4,
|
|
286
|
-
"color": "#6366f1",
|
|
287
|
-
"permission": {
|
|
288
|
-
"edit": "allow",
|
|
289
|
-
"webfetch": "allow",
|
|
290
|
-
"skill": { "*": "allow" },
|
|
291
|
-
"bash": {
|
|
292
|
-
"*": "ask",
|
|
293
|
-
"npm *": "allow",
|
|
294
|
-
"pnpm *": "allow",
|
|
295
|
-
"bun *": "allow",
|
|
296
|
-
"yarn *": "allow",
|
|
297
|
-
"docker *": "allow"
|
|
298
|
-
}
|
|
290
|
+
},
|
|
291
|
+
"agentmemory_*": "allow"
|
|
299
292
|
}
|
|
300
293
|
},
|
|
301
294
|
"seo": {
|
|
@@ -315,7 +308,8 @@
|
|
|
315
308
|
"git diff": "allow",
|
|
316
309
|
"git log*": "allow"
|
|
317
310
|
},
|
|
318
|
-
"nuxt_*": "allow"
|
|
311
|
+
"nuxt_*": "allow",
|
|
312
|
+
"agentmemory_*": "allow"
|
|
319
313
|
}
|
|
320
314
|
},
|
|
321
315
|
"android": {
|
|
@@ -335,7 +329,8 @@
|
|
|
335
329
|
"gradle *": "allow"
|
|
336
330
|
},
|
|
337
331
|
"figma_*": "ask",
|
|
338
|
-
"playwright_*": "allow"
|
|
332
|
+
"playwright_*": "allow",
|
|
333
|
+
"agentmemory_*": "allow"
|
|
339
334
|
}
|
|
340
335
|
},
|
|
341
336
|
"flutter": {
|
|
@@ -355,7 +350,8 @@
|
|
|
355
350
|
"dart *": "allow"
|
|
356
351
|
},
|
|
357
352
|
"figma_*": "ask",
|
|
358
|
-
"playwright_*": "allow"
|
|
353
|
+
"playwright_*": "allow",
|
|
354
|
+
"agentmemory_*": "allow"
|
|
359
355
|
}
|
|
360
356
|
}
|
|
361
357
|
}
|
package/template/opencode.json
CHANGED
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
".opencode/instructions/INSTRUCTIONS.md",
|
|
23
23
|
".opencode/skills/coding-standards/SKILL.md",
|
|
24
24
|
".opencode/skills/security-review/SKILL.md",
|
|
25
|
-
".opencode/skills/
|
|
25
|
+
".opencode/skills/impeccable/SKILL.md"
|
|
26
26
|
],
|
|
27
27
|
"mcp": {
|
|
28
28
|
"nuxt": {
|
|
@@ -93,7 +93,7 @@
|
|
|
93
93
|
"webfetch": "allow",
|
|
94
94
|
"skill": { "*": "allow" },
|
|
95
95
|
"bash": {
|
|
96
|
-
"*": "
|
|
96
|
+
"*": "ask",
|
|
97
97
|
"npm *": "allow",
|
|
98
98
|
"pnpm *": "allow",
|
|
99
99
|
"bun *": "allow",
|
|
@@ -119,7 +119,7 @@
|
|
|
119
119
|
"webfetch": "allow",
|
|
120
120
|
"skill": { "*": "allow" },
|
|
121
121
|
"bash": {
|
|
122
|
-
"*": "
|
|
122
|
+
"*": "ask",
|
|
123
123
|
"npm *": "allow",
|
|
124
124
|
"pnpm *": "allow",
|
|
125
125
|
"bun *": "allow",
|
|
@@ -143,7 +143,7 @@
|
|
|
143
143
|
"webfetch": "allow",
|
|
144
144
|
"skill": { "*": "allow" },
|
|
145
145
|
"bash": {
|
|
146
|
-
"*": "
|
|
146
|
+
"*": "ask",
|
|
147
147
|
"npm *": "allow",
|
|
148
148
|
"pnpm *": "allow",
|
|
149
149
|
"bun *": "allow",
|
|
@@ -165,7 +165,7 @@
|
|
|
165
165
|
"webfetch": "allow",
|
|
166
166
|
"skill": { "*": "allow" },
|
|
167
167
|
"bash": {
|
|
168
|
-
"*": "
|
|
168
|
+
"*": "ask",
|
|
169
169
|
"npm *": "allow",
|
|
170
170
|
"pnpm *": "allow",
|
|
171
171
|
"bun *": "allow",
|
|
@@ -185,7 +185,7 @@
|
|
|
185
185
|
"webfetch": "allow",
|
|
186
186
|
"skill": { "*": "allow" },
|
|
187
187
|
"bash": {
|
|
188
|
-
"*": "
|
|
188
|
+
"*": "ask",
|
|
189
189
|
"git status": "allow",
|
|
190
190
|
"git diff": "allow",
|
|
191
191
|
"git log*": "allow"
|
|
@@ -204,7 +204,7 @@
|
|
|
204
204
|
"webfetch": "allow",
|
|
205
205
|
"skill": { "*": "allow" },
|
|
206
206
|
"bash": {
|
|
207
|
-
"*": "
|
|
207
|
+
"*": "ask",
|
|
208
208
|
"git status": "allow",
|
|
209
209
|
"git diff": "allow",
|
|
210
210
|
"git log*": "allow"
|
|
@@ -223,7 +223,7 @@
|
|
|
223
223
|
"webfetch": "allow",
|
|
224
224
|
"skill": { "*": "allow" },
|
|
225
225
|
"bash": {
|
|
226
|
-
"*": "
|
|
226
|
+
"*": "ask",
|
|
227
227
|
"git status": "allow",
|
|
228
228
|
"git diff": "allow",
|
|
229
229
|
"git log*": "allow"
|
|
@@ -244,7 +244,7 @@
|
|
|
244
244
|
"webfetch": "allow",
|
|
245
245
|
"skill": { "*": "allow" },
|
|
246
246
|
"bash": {
|
|
247
|
-
"*": "
|
|
247
|
+
"*": "ask",
|
|
248
248
|
"npm *": "allow",
|
|
249
249
|
"pnpm *": "allow",
|
|
250
250
|
"bun *": "allow",
|
|
@@ -265,7 +265,7 @@
|
|
|
265
265
|
"webfetch": "allow",
|
|
266
266
|
"skill": { "*": "allow" },
|
|
267
267
|
"bash": {
|
|
268
|
-
"*": "
|
|
268
|
+
"*": "ask",
|
|
269
269
|
"npm *": "allow",
|
|
270
270
|
"pnpm *": "allow",
|
|
271
271
|
"bun *": "allow",
|
|
@@ -284,7 +284,7 @@
|
|
|
284
284
|
"webfetch": "allow",
|
|
285
285
|
"skill": { "*": "allow" },
|
|
286
286
|
"bash": {
|
|
287
|
-
"*": "
|
|
287
|
+
"*": "ask",
|
|
288
288
|
"npm *": "allow",
|
|
289
289
|
"pnpm *": "allow",
|
|
290
290
|
"bun *": "allow",
|
|
@@ -304,7 +304,7 @@
|
|
|
304
304
|
"webfetch": "allow",
|
|
305
305
|
"skill": { "*": "allow" },
|
|
306
306
|
"bash": {
|
|
307
|
-
"*": "
|
|
307
|
+
"*": "ask",
|
|
308
308
|
"git status": "allow",
|
|
309
309
|
"git diff": "allow",
|
|
310
310
|
"git log*": "allow"
|
|
@@ -323,7 +323,7 @@
|
|
|
323
323
|
"webfetch": "allow",
|
|
324
324
|
"skill": { "*": "allow" },
|
|
325
325
|
"bash": {
|
|
326
|
-
"*": "
|
|
326
|
+
"*": "ask",
|
|
327
327
|
"./gradlew *": "allow",
|
|
328
328
|
"gradle *": "allow"
|
|
329
329
|
},
|
|
@@ -342,7 +342,7 @@
|
|
|
342
342
|
"webfetch": "allow",
|
|
343
343
|
"skill": { "*": "allow" },
|
|
344
344
|
"bash": {
|
|
345
|
-
"*": "
|
|
345
|
+
"*": "ask",
|
|
346
346
|
"flutter *": "allow",
|
|
347
347
|
"dart *": "allow"
|
|
348
348
|
},
|