gitea-cli-skill 0.3.1 → 0.4.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/assets/SKILL.md +3 -2
- package/package.json +1 -1
- package/src/index.js +111 -87
package/assets/SKILL.md
CHANGED
|
@@ -15,7 +15,8 @@ Resolve `gitea-cli` to the platform binary in skill directory `~/.claude/skills/
|
|
|
15
15
|
# Linux / macOS
|
|
16
16
|
SKILL_DIR="$HOME/.claude/skills/gitea-cli"
|
|
17
17
|
OS="$(uname -s | tr '[:upper:]' '[:lower:]')"
|
|
18
|
-
ARCH="$(uname -m)"
|
|
18
|
+
ARCH="$(uname -m)"
|
|
19
|
+
case "$ARCH" in x86_64) ARCH="amd64" ;; aarch64|arm64) ARCH="arm64" ;; esac
|
|
19
20
|
GITEA_CLI="$SKILL_DIR/scripts/${OS}-${ARCH}/gitea-cli"
|
|
20
21
|
# Windows: %USERPROFILE%\.claude\skills\gitea-cli\scripts\windows-amd64\gitea-cli.exe
|
|
21
22
|
```
|
|
@@ -61,7 +62,7 @@ webhook list/get/create/update/delete/test — Webhooks
|
|
|
61
62
|
|
|
62
63
|
## Common Workflows
|
|
63
64
|
|
|
64
|
-
When performing a task, follow the matching workflow. Read `
|
|
65
|
+
When performing a task, follow the matching workflow. Read `references/command-reference.md` in the same skill directory for full command details and flags.
|
|
65
66
|
|
|
66
67
|
**Issue** — `issue list` → `issue get <n>` → `comment create <n>` → `issue close <n>`
|
|
67
68
|
**PR** — `branch create <name> --from <base>` → `pr create` → `actions run list` → `pr merge <idx>`
|
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
const fs = require('fs');
|
|
5
5
|
const path = require('path');
|
|
6
6
|
const os = require('os');
|
|
7
|
-
const
|
|
7
|
+
const crypto = require('crypto');
|
|
8
|
+
const { execFileSync, execSync } = require('child_process');
|
|
8
9
|
|
|
9
10
|
// ── Config ──────────────────────────────────────────────────────────────────
|
|
10
11
|
|
|
@@ -62,7 +63,6 @@ function resolveSkillDir(platformName, targetPath) {
|
|
|
62
63
|
if (platformName && PLATFORMS[platformName]) {
|
|
63
64
|
return path.join(os.homedir(), PLATFORMS[platformName].dir, SKILL_NAME);
|
|
64
65
|
}
|
|
65
|
-
// Default: claude
|
|
66
66
|
return path.join(os.homedir(), PLATFORMS.claude.dir, SKILL_NAME);
|
|
67
67
|
}
|
|
68
68
|
|
|
@@ -75,38 +75,34 @@ function findGiteaCliBin(platformName, targetPath) {
|
|
|
75
75
|
return path.join(skillDir, 'scripts', `${osArch.os}-${osArch.arch}`, binaryName);
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
-
// ── HTTP via curl (
|
|
78
|
+
// ── HTTP via curl (execFileSync — no shell injection) ────────────────────────
|
|
79
79
|
|
|
80
|
-
function curlGet(url, token) {
|
|
81
|
-
const args = ['-sS', '-f', '-
|
|
82
|
-
if (
|
|
83
|
-
|
|
84
|
-
}
|
|
80
|
+
function curlGet(url, token, insecure) {
|
|
81
|
+
const args = ['-sS', '-f', '-H', 'User-Agent: gitea-cli-skill-installer'];
|
|
82
|
+
if (insecure) args.push('-k');
|
|
83
|
+
if (token) args.push('-H', `Authorization: token ${token}`);
|
|
85
84
|
args.push(url);
|
|
86
|
-
return
|
|
85
|
+
return execFileSync('curl', args, { encoding: 'utf-8', timeout: 30000 });
|
|
87
86
|
}
|
|
88
87
|
|
|
89
|
-
function curlDownload(url, destPath, token) {
|
|
90
|
-
const args = ['-sS', '-f', '-
|
|
91
|
-
if (
|
|
92
|
-
|
|
93
|
-
}
|
|
88
|
+
function curlDownload(url, destPath, token, insecure) {
|
|
89
|
+
const args = ['-sS', '-f', '-L', '-o', destPath, '-H', 'User-Agent: gitea-cli-skill-installer'];
|
|
90
|
+
if (insecure) args.push('-k');
|
|
91
|
+
if (token) args.push('-H', `Authorization: token ${token}`);
|
|
94
92
|
args.push(url);
|
|
95
|
-
|
|
93
|
+
execFileSync('curl', args, { encoding: 'utf-8', timeout: 120000 });
|
|
96
94
|
}
|
|
97
95
|
|
|
98
96
|
// ── Gitea API ────────────────────────────────────────────────────────────────
|
|
99
97
|
|
|
100
|
-
function getLatestRelease(host, owner, repo, token) {
|
|
101
|
-
// Try /latest first
|
|
98
|
+
function getLatestRelease(host, owner, repo, token, insecure) {
|
|
102
99
|
try {
|
|
103
|
-
const data = curlGet(`${host}/api/v1/repos/${owner}/${repo}/releases/latest`, token);
|
|
100
|
+
const data = curlGet(`${host}/api/v1/repos/${owner}/${repo}/releases/latest`, token, insecure);
|
|
104
101
|
const release = JSON.parse(data);
|
|
105
102
|
if (release.assets && release.assets.length > 0) return release;
|
|
106
103
|
} catch { /* fall through */ }
|
|
107
104
|
|
|
108
|
-
|
|
109
|
-
const data = curlGet(`${host}/api/v1/repos/${owner}/${repo}/releases?limit=10`, token);
|
|
105
|
+
const data = curlGet(`${host}/api/v1/repos/${owner}/${repo}/releases?limit=10`, token, insecure);
|
|
110
106
|
const releases = JSON.parse(data);
|
|
111
107
|
for (const r of releases) {
|
|
112
108
|
if (r.assets && r.assets.length > 0) return r;
|
|
@@ -120,14 +116,41 @@ function findAsset(release, osArch) {
|
|
|
120
116
|
return release.assets.find((a) => a.name.endsWith(pattern) && !a.name.includes('checksum'));
|
|
121
117
|
}
|
|
122
118
|
|
|
119
|
+
function findChecksumAsset(release) {
|
|
120
|
+
return release.assets.find((a) => a.name.includes('checksums'));
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// ── Checksum verification ────────────────────────────────────────────────────
|
|
124
|
+
|
|
125
|
+
function verifyChecksum(archivePath, checksumContent, filename) {
|
|
126
|
+
for (const line of checksumContent.split('\n')) {
|
|
127
|
+
const trimmed = line.trim();
|
|
128
|
+
if (!trimmed) continue;
|
|
129
|
+
const parts = trimmed.split(/\s+/);
|
|
130
|
+
if (parts.length < 2) continue;
|
|
131
|
+
const [hash, name] = parts;
|
|
132
|
+
if (name === filename || path.basename(name) === filename) {
|
|
133
|
+
const actual = crypto.createHash('sha256').update(fs.readFileSync(archivePath)).digest('hex');
|
|
134
|
+
if (actual !== hash) {
|
|
135
|
+
throw new Error(`Checksum mismatch for ${filename}: expected ${hash}, got ${actual}`);
|
|
136
|
+
}
|
|
137
|
+
console.log(' Checksum verified (SHA256).');
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
console.warn(' ⚠ Checksum entry not found for ${filename}, skipping verification.');
|
|
142
|
+
}
|
|
143
|
+
|
|
123
144
|
// ── Archive extraction ──────────────────────────────────────────────────────
|
|
124
145
|
|
|
125
146
|
function extractArchive(archivePath, destDir, osArch) {
|
|
126
147
|
fs.mkdirSync(destDir, { recursive: true });
|
|
127
148
|
if (osArch.os === 'windows') {
|
|
128
|
-
|
|
149
|
+
execFileSync('powershell', [
|
|
150
|
+
'-Command', 'Expand-Archive', '-Path', archivePath, '-DestinationPath', destDir, '-Force',
|
|
151
|
+
], { stdio: 'pipe' });
|
|
129
152
|
} else {
|
|
130
|
-
|
|
153
|
+
execFileSync('tar', ['-xzf', archivePath, '-C', destDir], { stdio: 'pipe' });
|
|
131
154
|
}
|
|
132
155
|
|
|
133
156
|
const binaryName = osArch.os === 'windows' ? 'gitea-cli.exe' : 'gitea-cli';
|
|
@@ -147,7 +170,6 @@ function extractArchive(archivePath, destDir, osArch) {
|
|
|
147
170
|
function configureContext({ giteaCliBin, host, token, contextName, defaultOwner, defaultRepo }) {
|
|
148
171
|
const ctxName = contextName || 'default';
|
|
149
172
|
const cmdArgs = [
|
|
150
|
-
`"${giteaCliBin}"`,
|
|
151
173
|
'config', 'set',
|
|
152
174
|
'--name', ctxName,
|
|
153
175
|
'--host', host.replace(/\/$/, ''),
|
|
@@ -156,7 +178,11 @@ function configureContext({ giteaCliBin, host, token, contextName, defaultOwner,
|
|
|
156
178
|
if (defaultOwner) cmdArgs.push('--default-owner', defaultOwner);
|
|
157
179
|
if (defaultRepo) cmdArgs.push('--default-repo', defaultRepo);
|
|
158
180
|
|
|
159
|
-
|
|
181
|
+
execFileSync(giteaCliBin, cmdArgs, {
|
|
182
|
+
stdio: 'inherit',
|
|
183
|
+
timeout: 10000,
|
|
184
|
+
env: { ...process.env }, // token passed via CLI flag, not env
|
|
185
|
+
});
|
|
160
186
|
}
|
|
161
187
|
|
|
162
188
|
// ── Version consistency check ────────────────────────────────────────────────
|
|
@@ -164,8 +190,7 @@ function configureContext({ giteaCliBin, host, token, contextName, defaultOwner,
|
|
|
164
190
|
function checkVersionConsistency(binaryPath) {
|
|
165
191
|
if (!fs.existsSync(binaryPath)) return;
|
|
166
192
|
try {
|
|
167
|
-
const raw =
|
|
168
|
-
// Parse version from output like "gitea-cli version 0.3.0" or just "0.3.0"
|
|
193
|
+
const raw = execFileSync(binaryPath, ['--version'], { encoding: 'utf-8', timeout: 5000 }).trim();
|
|
169
194
|
const match = raw.match(/(\d+\.\d+\.\d+)/);
|
|
170
195
|
if (!match) return;
|
|
171
196
|
const binVersion = match[1];
|
|
@@ -179,7 +204,7 @@ function checkVersionConsistency(binaryPath) {
|
|
|
179
204
|
// ── Install command ─────────────────────────────────────────────────────────
|
|
180
205
|
|
|
181
206
|
async function install(args) {
|
|
182
|
-
const { token: explicitToken, host: explicitHost, platform: platformName, target: targetPath, local: localDir, force, name: contextName, 'default-owner': defaultOwner, 'default-repo': defaultRepo } = args;
|
|
207
|
+
const { token: explicitToken, host: explicitHost, platform: platformName, target: targetPath, local: localDir, force, name: contextName, 'default-owner': defaultOwner, 'default-repo': defaultRepo, insecure } = args;
|
|
183
208
|
const giteaHost = explicitHost || GITEA_HOST;
|
|
184
209
|
const token = explicitToken || process.env.GITEA_TOKEN || null;
|
|
185
210
|
const osArch = detectOSArch();
|
|
@@ -189,26 +214,7 @@ async function install(args) {
|
|
|
189
214
|
console.log(`Installing gitea-cli skill (${osArch.os}-${osArch.arch}) to ${skillDir}...`);
|
|
190
215
|
|
|
191
216
|
// 1. Copy SKILL.md and references/
|
|
192
|
-
|
|
193
|
-
const srcSkill = path.resolve(__dirname, '..', 'assets', 'SKILL.md');
|
|
194
|
-
const destSkill = path.join(skillDir, 'SKILL.md');
|
|
195
|
-
fs.copyFileSync(srcSkill, destSkill);
|
|
196
|
-
console.log(` SKILL.md -> ${destSkill}`);
|
|
197
|
-
|
|
198
|
-
const srcRef = path.resolve(__dirname, '..', 'assets', 'references', 'command-reference.md');
|
|
199
|
-
const destRef = path.join(skillDir, 'references', 'command-reference.md');
|
|
200
|
-
if (fs.existsSync(srcRef)) {
|
|
201
|
-
fs.mkdirSync(path.dirname(destRef), { recursive: true });
|
|
202
|
-
fs.copyFileSync(srcRef, destRef);
|
|
203
|
-
console.log(` references/command-reference.md -> ${destRef}`);
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
// Cleanup: remove legacy REFERENCE.md from old location
|
|
207
|
-
const legacyRef = path.join(skillDir, 'REFERENCE.md');
|
|
208
|
-
if (fs.existsSync(legacyRef)) {
|
|
209
|
-
fs.unlinkSync(legacyRef);
|
|
210
|
-
console.log(' Removed legacy REFERENCE.md');
|
|
211
|
-
}
|
|
217
|
+
copySkillFiles(skillDir);
|
|
212
218
|
|
|
213
219
|
// 2. Check existing binary
|
|
214
220
|
const binaryName = osArch.os === 'windows' ? 'gitea-cli.exe' : 'gitea-cli';
|
|
@@ -217,11 +223,9 @@ async function install(args) {
|
|
|
217
223
|
if (fs.existsSync(destBinary) && !force) {
|
|
218
224
|
console.log(` Binary already exists: ${destBinary} (use --force to overwrite)`);
|
|
219
225
|
} else if (localDir) {
|
|
220
|
-
// --local: copy from local directory
|
|
221
226
|
installFromLocal(localDir, scriptsDir, destBinary, osArch);
|
|
222
227
|
} else {
|
|
223
|
-
|
|
224
|
-
await installFromRelease(giteaHost, token, scriptsDir, destBinary, osArch);
|
|
228
|
+
await installFromRelease(giteaHost, token, scriptsDir, destBinary, osArch, insecure);
|
|
225
229
|
}
|
|
226
230
|
|
|
227
231
|
// 3. Configure context if token provided
|
|
@@ -246,26 +250,48 @@ async function install(args) {
|
|
|
246
250
|
console.log(`\nDone!`);
|
|
247
251
|
}
|
|
248
252
|
|
|
253
|
+
// ── Shared: copy SKILL.md + references + cleanup legacy ─────────────────────
|
|
254
|
+
|
|
255
|
+
function copySkillFiles(skillDir) {
|
|
256
|
+
fs.mkdirSync(skillDir, { recursive: true });
|
|
257
|
+
|
|
258
|
+
const srcSkill = path.resolve(__dirname, '..', 'assets', 'SKILL.md');
|
|
259
|
+
const destSkill = path.join(skillDir, 'SKILL.md');
|
|
260
|
+
fs.copyFileSync(srcSkill, destSkill);
|
|
261
|
+
console.log(` SKILL.md -> ${destSkill}`);
|
|
262
|
+
|
|
263
|
+
const srcRef = path.resolve(__dirname, '..', 'assets', 'references', 'command-reference.md');
|
|
264
|
+
const destRef = path.join(skillDir, 'references', 'command-reference.md');
|
|
265
|
+
if (fs.existsSync(srcRef)) {
|
|
266
|
+
fs.mkdirSync(path.dirname(destRef), { recursive: true });
|
|
267
|
+
fs.copyFileSync(srcRef, destRef);
|
|
268
|
+
console.log(` references/command-reference.md -> ${destRef}`);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// Cleanup legacy file
|
|
272
|
+
const legacyRef = path.join(skillDir, 'REFERENCE.md');
|
|
273
|
+
if (fs.existsSync(legacyRef)) {
|
|
274
|
+
fs.unlinkSync(legacyRef);
|
|
275
|
+
console.log(' Removed legacy REFERENCE.md');
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
249
279
|
// ── Install from local goreleaser dist ───────────────────────────────────────
|
|
250
280
|
|
|
251
281
|
function installFromLocal(localDir, scriptsDir, destBinary, osArch) {
|
|
252
|
-
// Goreleaser dist structure: dist/gitea-cli_<version>_<os>_<arch>/gitea-cli[.exe]
|
|
253
282
|
const ext = osArch.os === 'windows' ? 'zip' : 'tar.gz';
|
|
254
|
-
|
|
255
283
|
const resolvedDir = localDir.replace(/^~/, os.homedir());
|
|
256
284
|
|
|
257
|
-
// Try to find archive in dist/
|
|
258
285
|
const files = fs.readdirSync(resolvedDir);
|
|
259
286
|
const extRe = ext === 'tar.gz' ? 'tar\\.gz' : 'zip';
|
|
260
287
|
const pattern = new RegExp('gitea-cli_\\d+\\.\\d+\\.\\d+(-\\w+)?_' + osArch.os + '_' + osArch.arch + '\\.' + extRe + '$');
|
|
261
288
|
const match = files.find((f) => pattern.test(f));
|
|
262
289
|
if (!match) {
|
|
263
|
-
// Try finding extracted binary directly
|
|
264
290
|
const binaryName = osArch.os === 'windows' ? 'gitea-cli.exe' : 'gitea-cli';
|
|
265
291
|
const subDirs = files.filter((f) => f.includes(`${osArch.os}_${osArch.arch}`) && fs.statSync(path.join(resolvedDir, f)).isDirectory());
|
|
266
292
|
for (const d of subDirs) {
|
|
267
293
|
const candidate = path.join(resolvedDir, d, binaryName);
|
|
268
|
-
if (fs.existsSync(candidate)) {
|
|
294
|
+
if (fs.existsSync(candidate) && fs.statSync(candidate).isFile()) {
|
|
269
295
|
fs.mkdirSync(scriptsDir, { recursive: true });
|
|
270
296
|
fs.copyFileSync(candidate, destBinary);
|
|
271
297
|
if (osArch.os !== 'windows') fs.chmodSync(destBinary, 0o755);
|
|
@@ -292,12 +318,12 @@ function installFromLocal(localDir, scriptsDir, destBinary, osArch) {
|
|
|
292
318
|
|
|
293
319
|
// ── Install from Gitea release ───────────────────────────────────────────────
|
|
294
320
|
|
|
295
|
-
async function installFromRelease(giteaHost, token, scriptsDir, destBinary, osArch) {
|
|
321
|
+
async function installFromRelease(giteaHost, token, scriptsDir, destBinary, osArch, insecure) {
|
|
296
322
|
console.log(` Fetching latest release from ${giteaHost}...`);
|
|
297
323
|
|
|
298
324
|
let release;
|
|
299
325
|
try {
|
|
300
|
-
release = getLatestRelease(giteaHost, GITEA_OWNER, GITEA_REPO, token);
|
|
326
|
+
release = getLatestRelease(giteaHost, GITEA_OWNER, GITEA_REPO, token, insecure);
|
|
301
327
|
} catch (err) {
|
|
302
328
|
if (!token) {
|
|
303
329
|
console.error(` Failed to fetch release without token: ${err.message}`);
|
|
@@ -322,7 +348,21 @@ async function installFromRelease(giteaHost, token, scriptsDir, destBinary, osAr
|
|
|
322
348
|
const tmpArchive = path.join(tmpDir, asset.name);
|
|
323
349
|
|
|
324
350
|
try {
|
|
325
|
-
curlDownload(asset.browser_download_url, tmpArchive, token);
|
|
351
|
+
curlDownload(asset.browser_download_url, tmpArchive, token, insecure);
|
|
352
|
+
|
|
353
|
+
// Verify checksum if available
|
|
354
|
+
const checksumAsset = findChecksumAsset(release);
|
|
355
|
+
if (checksumAsset) {
|
|
356
|
+
try {
|
|
357
|
+
const tmpChecksum = path.join(tmpDir, checksumAsset.name);
|
|
358
|
+
curlDownload(checksumAsset.browser_download_url, tmpChecksum, token, insecure);
|
|
359
|
+
const checksumContent = fs.readFileSync(tmpChecksum, 'utf-8');
|
|
360
|
+
verifyChecksum(tmpArchive, checksumContent, asset.name);
|
|
361
|
+
} catch (err) {
|
|
362
|
+
console.warn(` ⚠ Checksum verification skipped: ${err.message}`);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
|
|
326
366
|
console.log(' Extracting...');
|
|
327
367
|
const binaryPath = extractArchive(tmpArchive, path.join(tmpDir, 'extracted'), osArch);
|
|
328
368
|
fs.mkdirSync(scriptsDir, { recursive: true });
|
|
@@ -363,8 +403,9 @@ async function addContext(args) {
|
|
|
363
403
|
// ── Update command ────────────────────────────────────────────────────────────
|
|
364
404
|
|
|
365
405
|
async function update(args) {
|
|
366
|
-
const { host: explicitHost, platform: platformName, target: targetPath, local: localDir } = args;
|
|
406
|
+
const { token: explicitToken, host: explicitHost, platform: platformName, target: targetPath, local: localDir, insecure } = args;
|
|
367
407
|
const giteaHost = explicitHost || GITEA_HOST;
|
|
408
|
+
const token = explicitToken || process.env.GITEA_TOKEN || null;
|
|
368
409
|
const osArch = detectOSArch();
|
|
369
410
|
const skillDir = resolveSkillDir(platformName, targetPath);
|
|
370
411
|
const scriptsDir = path.join(skillDir, 'scripts', `${osArch.os}-${osArch.arch}`);
|
|
@@ -372,28 +413,7 @@ async function update(args) {
|
|
|
372
413
|
console.log(`Updating gitea-cli skill (${osArch.os}-${osArch.arch}) at ${skillDir}...`);
|
|
373
414
|
|
|
374
415
|
// 1. Refresh SKILL.md and references/
|
|
375
|
-
|
|
376
|
-
const destSkill = path.join(skillDir, 'SKILL.md');
|
|
377
|
-
if (fs.existsSync(srcSkill)) {
|
|
378
|
-
fs.mkdirSync(skillDir, { recursive: true });
|
|
379
|
-
fs.copyFileSync(srcSkill, destSkill);
|
|
380
|
-
console.log(` SKILL.md -> ${destSkill}`);
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
const srcRef = path.resolve(__dirname, '..', 'assets', 'references', 'command-reference.md');
|
|
384
|
-
const destRef = path.join(skillDir, 'references', 'command-reference.md');
|
|
385
|
-
if (fs.existsSync(srcRef)) {
|
|
386
|
-
fs.mkdirSync(path.dirname(destRef), { recursive: true });
|
|
387
|
-
fs.copyFileSync(srcRef, destRef);
|
|
388
|
-
console.log(` references/command-reference.md -> ${destRef}`);
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
// Cleanup: remove legacy REFERENCE.md from old location
|
|
392
|
-
const legacyRef = path.join(skillDir, 'REFERENCE.md');
|
|
393
|
-
if (fs.existsSync(legacyRef)) {
|
|
394
|
-
fs.unlinkSync(legacyRef);
|
|
395
|
-
console.log(' Removed legacy REFERENCE.md');
|
|
396
|
-
}
|
|
416
|
+
copySkillFiles(skillDir);
|
|
397
417
|
|
|
398
418
|
// 2. Re-download / re-copy binary (always overwrite)
|
|
399
419
|
const binaryName = osArch.os === 'windows' ? 'gitea-cli.exe' : 'gitea-cli';
|
|
@@ -402,8 +422,7 @@ async function update(args) {
|
|
|
402
422
|
if (localDir) {
|
|
403
423
|
installFromLocal(localDir, scriptsDir, destBinary, osArch);
|
|
404
424
|
} else {
|
|
405
|
-
|
|
406
|
-
await installFromRelease(giteaHost, token, scriptsDir, destBinary, osArch);
|
|
425
|
+
await installFromRelease(giteaHost, token, scriptsDir, destBinary, osArch, insecure);
|
|
407
426
|
}
|
|
408
427
|
|
|
409
428
|
// 3. Version consistency check
|
|
@@ -415,11 +434,12 @@ async function update(args) {
|
|
|
415
434
|
// ── CLI ──────────────────────────────────────────────────────────────────────
|
|
416
435
|
|
|
417
436
|
function parseArgs(argv) {
|
|
418
|
-
const args = { token: null, host: null, platform: null, target: null, local: null, force: false, command: null, subcommand: null, name: null, 'default-owner': null, 'default-repo': null };
|
|
437
|
+
const args = { token: null, host: null, platform: null, target: null, local: null, force: false, insecure: false, command: null, subcommand: null, name: null, 'default-owner': null, 'default-repo': null };
|
|
419
438
|
|
|
420
439
|
for (let i = 2; i < argv.length; i++) {
|
|
421
440
|
const arg = argv[i];
|
|
422
|
-
if (arg === '--
|
|
441
|
+
if (arg === '--') break; // end of options
|
|
442
|
+
else if (arg === '--token' && i + 1 < argv.length) args.token = argv[++i];
|
|
423
443
|
else if (arg === '--host' && i + 1 < argv.length) args.host = argv[++i];
|
|
424
444
|
else if (arg === '--platform' && i + 1 < argv.length) args.platform = argv[++i];
|
|
425
445
|
else if (arg === '--target' && i + 1 < argv.length) args.target = argv[++i];
|
|
@@ -428,6 +448,8 @@ function parseArgs(argv) {
|
|
|
428
448
|
else if (arg === '--default-owner' && i + 1 < argv.length) args['default-owner'] = argv[++i];
|
|
429
449
|
else if (arg === '--default-repo' && i + 1 < argv.length) args['default-repo'] = argv[++i];
|
|
430
450
|
else if (arg === '--force' || arg === '-f') args.force = true;
|
|
451
|
+
else if (arg === '--insecure') args.insecure = true;
|
|
452
|
+
else if (arg === '--version' || arg === '-v') { console.log(`gitea-cli-skill v${PKG_VERSION}`); process.exit(0); }
|
|
431
453
|
else if (arg === '--help' || arg === '-h') { printHelp(); process.exit(0); }
|
|
432
454
|
else if (!arg.startsWith('-') && !args.command) args.command = arg;
|
|
433
455
|
else if (!arg.startsWith('-') && args.command && !args.subcommand) args.subcommand = arg;
|
|
@@ -440,7 +462,7 @@ function printHelp() {
|
|
|
440
462
|
.map(([k, v]) => ` ${k.padEnd(10)} ${v.desc}`)
|
|
441
463
|
.join('\n');
|
|
442
464
|
|
|
443
|
-
console.log(`gitea-cli-skill - Install gitea-cli as an AI agent skill
|
|
465
|
+
console.log(`gitea-cli-skill v${PKG_VERSION} - Install gitea-cli as an AI agent skill
|
|
444
466
|
|
|
445
467
|
Usage:
|
|
446
468
|
npx gitea-cli-skill init [flags] # Install + configure
|
|
@@ -464,6 +486,7 @@ Flags (init):
|
|
|
464
486
|
--force Overwrite existing binary
|
|
465
487
|
|
|
466
488
|
Flags (update):
|
|
489
|
+
--token <t> Gitea API token (overrides GITEA_TOKEN env var)
|
|
467
490
|
--host <url> Gitea host URL (default: ${GITEA_HOST})
|
|
468
491
|
--local <dir> Update from local goreleaser dist directory (skip download)
|
|
469
492
|
--platform <name> Target AI platform (default: claude)
|
|
@@ -479,6 +502,8 @@ Flags (add context):
|
|
|
479
502
|
|
|
480
503
|
Global:
|
|
481
504
|
-h, --help Show this help
|
|
505
|
+
-v, --version Show version
|
|
506
|
+
--insecure Skip SSL certificate verification (not recommended)
|
|
482
507
|
|
|
483
508
|
Platforms:
|
|
484
509
|
${platformList}
|
|
@@ -516,7 +541,6 @@ async function main() {
|
|
|
516
541
|
if (!args.command) { printHelp(); process.exit(0); }
|
|
517
542
|
|
|
518
543
|
if (args.command === 'init') {
|
|
519
|
-
// Validate platform name
|
|
520
544
|
if (args.platform && !PLATFORMS[args.platform] && !args.target) {
|
|
521
545
|
console.error(`Unknown platform: ${args.platform}`);
|
|
522
546
|
console.error(`Available: ${Object.keys(PLATFORMS).join(', ')}, or use --target for custom path.`);
|