gitea-cli-skill 0.3.0 → 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
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>`
|
|
@@ -83,8 +84,10 @@ Destructive ops: always `list`/`get` first, then `--force`. Deleted resources ca
|
|
|
83
84
|
|
|
84
85
|
## On-Demand Reference
|
|
85
86
|
|
|
86
|
-
For full command flags and detailed workflow steps, read
|
|
87
|
+
For full command flags and detailed workflow steps, read:
|
|
87
88
|
|
|
88
89
|
```
|
|
89
|
-
|
|
90
|
+
references/command-reference.md
|
|
90
91
|
```
|
|
92
|
+
|
|
93
|
+
Located in the same skill directory as this file.
|
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
|
|
|
@@ -12,6 +13,7 @@ const GITEA_HOST = 'https://x.xgit.pro';
|
|
|
12
13
|
const GITEA_OWNER = 'chenqi';
|
|
13
14
|
const GITEA_REPO = 'git-cli';
|
|
14
15
|
const SKILL_NAME = 'gitea-cli';
|
|
16
|
+
const PKG_VERSION = require(path.resolve(__dirname, '..', 'package.json')).version;
|
|
15
17
|
|
|
16
18
|
// ── Platform definitions ────────────────────────────────────────────────────
|
|
17
19
|
|
|
@@ -61,7 +63,6 @@ function resolveSkillDir(platformName, targetPath) {
|
|
|
61
63
|
if (platformName && PLATFORMS[platformName]) {
|
|
62
64
|
return path.join(os.homedir(), PLATFORMS[platformName].dir, SKILL_NAME);
|
|
63
65
|
}
|
|
64
|
-
// Default: claude
|
|
65
66
|
return path.join(os.homedir(), PLATFORMS.claude.dir, SKILL_NAME);
|
|
66
67
|
}
|
|
67
68
|
|
|
@@ -74,38 +75,34 @@ function findGiteaCliBin(platformName, targetPath) {
|
|
|
74
75
|
return path.join(skillDir, 'scripts', `${osArch.os}-${osArch.arch}`, binaryName);
|
|
75
76
|
}
|
|
76
77
|
|
|
77
|
-
// ── HTTP via curl (
|
|
78
|
+
// ── HTTP via curl (execFileSync — no shell injection) ────────────────────────
|
|
78
79
|
|
|
79
|
-
function curlGet(url, token) {
|
|
80
|
-
const args = ['-sS', '-f', '-
|
|
81
|
-
if (
|
|
82
|
-
|
|
83
|
-
}
|
|
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}`);
|
|
84
84
|
args.push(url);
|
|
85
|
-
return
|
|
85
|
+
return execFileSync('curl', args, { encoding: 'utf-8', timeout: 30000 });
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
-
function curlDownload(url, destPath, token) {
|
|
89
|
-
const args = ['-sS', '-f', '-
|
|
90
|
-
if (
|
|
91
|
-
|
|
92
|
-
}
|
|
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}`);
|
|
93
92
|
args.push(url);
|
|
94
|
-
|
|
93
|
+
execFileSync('curl', args, { encoding: 'utf-8', timeout: 120000 });
|
|
95
94
|
}
|
|
96
95
|
|
|
97
96
|
// ── Gitea API ────────────────────────────────────────────────────────────────
|
|
98
97
|
|
|
99
|
-
function getLatestRelease(host, owner, repo, token) {
|
|
100
|
-
// Try /latest first
|
|
98
|
+
function getLatestRelease(host, owner, repo, token, insecure) {
|
|
101
99
|
try {
|
|
102
|
-
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);
|
|
103
101
|
const release = JSON.parse(data);
|
|
104
102
|
if (release.assets && release.assets.length > 0) return release;
|
|
105
103
|
} catch { /* fall through */ }
|
|
106
104
|
|
|
107
|
-
|
|
108
|
-
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);
|
|
109
106
|
const releases = JSON.parse(data);
|
|
110
107
|
for (const r of releases) {
|
|
111
108
|
if (r.assets && r.assets.length > 0) return r;
|
|
@@ -119,14 +116,41 @@ function findAsset(release, osArch) {
|
|
|
119
116
|
return release.assets.find((a) => a.name.endsWith(pattern) && !a.name.includes('checksum'));
|
|
120
117
|
}
|
|
121
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
|
+
|
|
122
144
|
// ── Archive extraction ──────────────────────────────────────────────────────
|
|
123
145
|
|
|
124
146
|
function extractArchive(archivePath, destDir, osArch) {
|
|
125
147
|
fs.mkdirSync(destDir, { recursive: true });
|
|
126
148
|
if (osArch.os === 'windows') {
|
|
127
|
-
|
|
149
|
+
execFileSync('powershell', [
|
|
150
|
+
'-Command', 'Expand-Archive', '-Path', archivePath, '-DestinationPath', destDir, '-Force',
|
|
151
|
+
], { stdio: 'pipe' });
|
|
128
152
|
} else {
|
|
129
|
-
|
|
153
|
+
execFileSync('tar', ['-xzf', archivePath, '-C', destDir], { stdio: 'pipe' });
|
|
130
154
|
}
|
|
131
155
|
|
|
132
156
|
const binaryName = osArch.os === 'windows' ? 'gitea-cli.exe' : 'gitea-cli';
|
|
@@ -146,7 +170,6 @@ function extractArchive(archivePath, destDir, osArch) {
|
|
|
146
170
|
function configureContext({ giteaCliBin, host, token, contextName, defaultOwner, defaultRepo }) {
|
|
147
171
|
const ctxName = contextName || 'default';
|
|
148
172
|
const cmdArgs = [
|
|
149
|
-
`"${giteaCliBin}"`,
|
|
150
173
|
'config', 'set',
|
|
151
174
|
'--name', ctxName,
|
|
152
175
|
'--host', host.replace(/\/$/, ''),
|
|
@@ -155,13 +178,33 @@ function configureContext({ giteaCliBin, host, token, contextName, defaultOwner,
|
|
|
155
178
|
if (defaultOwner) cmdArgs.push('--default-owner', defaultOwner);
|
|
156
179
|
if (defaultRepo) cmdArgs.push('--default-repo', defaultRepo);
|
|
157
180
|
|
|
158
|
-
|
|
181
|
+
execFileSync(giteaCliBin, cmdArgs, {
|
|
182
|
+
stdio: 'inherit',
|
|
183
|
+
timeout: 10000,
|
|
184
|
+
env: { ...process.env }, // token passed via CLI flag, not env
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// ── Version consistency check ────────────────────────────────────────────────
|
|
189
|
+
|
|
190
|
+
function checkVersionConsistency(binaryPath) {
|
|
191
|
+
if (!fs.existsSync(binaryPath)) return;
|
|
192
|
+
try {
|
|
193
|
+
const raw = execFileSync(binaryPath, ['--version'], { encoding: 'utf-8', timeout: 5000 }).trim();
|
|
194
|
+
const match = raw.match(/(\d+\.\d+\.\d+)/);
|
|
195
|
+
if (!match) return;
|
|
196
|
+
const binVersion = match[1];
|
|
197
|
+
if (binVersion !== PKG_VERSION) {
|
|
198
|
+
console.warn(` ⚠ Version mismatch: npm=${PKG_VERSION}, binary=${binVersion}`);
|
|
199
|
+
console.warn(' Run `npx gitea-cli-skill@latest update` to sync.');
|
|
200
|
+
}
|
|
201
|
+
} catch { /* non-blocking */ }
|
|
159
202
|
}
|
|
160
203
|
|
|
161
204
|
// ── Install command ─────────────────────────────────────────────────────────
|
|
162
205
|
|
|
163
206
|
async function install(args) {
|
|
164
|
-
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;
|
|
165
208
|
const giteaHost = explicitHost || GITEA_HOST;
|
|
166
209
|
const token = explicitToken || process.env.GITEA_TOKEN || null;
|
|
167
210
|
const osArch = detectOSArch();
|
|
@@ -170,19 +213,8 @@ async function install(args) {
|
|
|
170
213
|
|
|
171
214
|
console.log(`Installing gitea-cli skill (${osArch.os}-${osArch.arch}) to ${skillDir}...`);
|
|
172
215
|
|
|
173
|
-
// 1. Copy SKILL.md and
|
|
174
|
-
|
|
175
|
-
const srcSkill = path.resolve(__dirname, '..', 'assets', 'SKILL.md');
|
|
176
|
-
const destSkill = path.join(skillDir, 'SKILL.md');
|
|
177
|
-
fs.copyFileSync(srcSkill, destSkill);
|
|
178
|
-
console.log(` SKILL.md -> ${destSkill}`);
|
|
179
|
-
|
|
180
|
-
const srcRef = path.resolve(__dirname, '..', 'assets', 'REFERENCE.md');
|
|
181
|
-
const destRef = path.join(skillDir, 'REFERENCE.md');
|
|
182
|
-
if (fs.existsSync(srcRef)) {
|
|
183
|
-
fs.copyFileSync(srcRef, destRef);
|
|
184
|
-
console.log(` REFERENCE.md -> ${destRef}`);
|
|
185
|
-
}
|
|
216
|
+
// 1. Copy SKILL.md and references/
|
|
217
|
+
copySkillFiles(skillDir);
|
|
186
218
|
|
|
187
219
|
// 2. Check existing binary
|
|
188
220
|
const binaryName = osArch.os === 'windows' ? 'gitea-cli.exe' : 'gitea-cli';
|
|
@@ -191,11 +223,9 @@ async function install(args) {
|
|
|
191
223
|
if (fs.existsSync(destBinary) && !force) {
|
|
192
224
|
console.log(` Binary already exists: ${destBinary} (use --force to overwrite)`);
|
|
193
225
|
} else if (localDir) {
|
|
194
|
-
// --local: copy from local directory
|
|
195
226
|
installFromLocal(localDir, scriptsDir, destBinary, osArch);
|
|
196
227
|
} else {
|
|
197
|
-
|
|
198
|
-
await installFromRelease(giteaHost, token, scriptsDir, destBinary, osArch);
|
|
228
|
+
await installFromRelease(giteaHost, token, scriptsDir, destBinary, osArch, insecure);
|
|
199
229
|
}
|
|
200
230
|
|
|
201
231
|
// 3. Configure context if token provided
|
|
@@ -214,29 +244,54 @@ async function install(args) {
|
|
|
214
244
|
}
|
|
215
245
|
}
|
|
216
246
|
|
|
247
|
+
// 4. Version consistency check
|
|
248
|
+
checkVersionConsistency(destBinary);
|
|
249
|
+
|
|
217
250
|
console.log(`\nDone!`);
|
|
218
251
|
}
|
|
219
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
|
+
|
|
220
279
|
// ── Install from local goreleaser dist ───────────────────────────────────────
|
|
221
280
|
|
|
222
281
|
function installFromLocal(localDir, scriptsDir, destBinary, osArch) {
|
|
223
|
-
// Goreleaser dist structure: dist/gitea-cli_<version>_<os>_<arch>/gitea-cli[.exe]
|
|
224
282
|
const ext = osArch.os === 'windows' ? 'zip' : 'tar.gz';
|
|
225
|
-
|
|
226
283
|
const resolvedDir = localDir.replace(/^~/, os.homedir());
|
|
227
284
|
|
|
228
|
-
// Try to find archive in dist/
|
|
229
285
|
const files = fs.readdirSync(resolvedDir);
|
|
230
286
|
const extRe = ext === 'tar.gz' ? 'tar\\.gz' : 'zip';
|
|
231
287
|
const pattern = new RegExp('gitea-cli_\\d+\\.\\d+\\.\\d+(-\\w+)?_' + osArch.os + '_' + osArch.arch + '\\.' + extRe + '$');
|
|
232
288
|
const match = files.find((f) => pattern.test(f));
|
|
233
289
|
if (!match) {
|
|
234
|
-
// Try finding extracted binary directly
|
|
235
290
|
const binaryName = osArch.os === 'windows' ? 'gitea-cli.exe' : 'gitea-cli';
|
|
236
291
|
const subDirs = files.filter((f) => f.includes(`${osArch.os}_${osArch.arch}`) && fs.statSync(path.join(resolvedDir, f)).isDirectory());
|
|
237
292
|
for (const d of subDirs) {
|
|
238
293
|
const candidate = path.join(resolvedDir, d, binaryName);
|
|
239
|
-
if (fs.existsSync(candidate)) {
|
|
294
|
+
if (fs.existsSync(candidate) && fs.statSync(candidate).isFile()) {
|
|
240
295
|
fs.mkdirSync(scriptsDir, { recursive: true });
|
|
241
296
|
fs.copyFileSync(candidate, destBinary);
|
|
242
297
|
if (osArch.os !== 'windows') fs.chmodSync(destBinary, 0o755);
|
|
@@ -263,12 +318,12 @@ function installFromLocal(localDir, scriptsDir, destBinary, osArch) {
|
|
|
263
318
|
|
|
264
319
|
// ── Install from Gitea release ───────────────────────────────────────────────
|
|
265
320
|
|
|
266
|
-
async function installFromRelease(giteaHost, token, scriptsDir, destBinary, osArch) {
|
|
321
|
+
async function installFromRelease(giteaHost, token, scriptsDir, destBinary, osArch, insecure) {
|
|
267
322
|
console.log(` Fetching latest release from ${giteaHost}...`);
|
|
268
323
|
|
|
269
324
|
let release;
|
|
270
325
|
try {
|
|
271
|
-
release = getLatestRelease(giteaHost, GITEA_OWNER, GITEA_REPO, token);
|
|
326
|
+
release = getLatestRelease(giteaHost, GITEA_OWNER, GITEA_REPO, token, insecure);
|
|
272
327
|
} catch (err) {
|
|
273
328
|
if (!token) {
|
|
274
329
|
console.error(` Failed to fetch release without token: ${err.message}`);
|
|
@@ -293,7 +348,21 @@ async function installFromRelease(giteaHost, token, scriptsDir, destBinary, osAr
|
|
|
293
348
|
const tmpArchive = path.join(tmpDir, asset.name);
|
|
294
349
|
|
|
295
350
|
try {
|
|
296
|
-
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
|
+
|
|
297
366
|
console.log(' Extracting...');
|
|
298
367
|
const binaryPath = extractArchive(tmpArchive, path.join(tmpDir, 'extracted'), osArch);
|
|
299
368
|
fs.mkdirSync(scriptsDir, { recursive: true });
|
|
@@ -334,29 +403,17 @@ async function addContext(args) {
|
|
|
334
403
|
// ── Update command ────────────────────────────────────────────────────────────
|
|
335
404
|
|
|
336
405
|
async function update(args) {
|
|
337
|
-
const { host: explicitHost, platform: platformName, target: targetPath, local: localDir } = args;
|
|
406
|
+
const { token: explicitToken, host: explicitHost, platform: platformName, target: targetPath, local: localDir, insecure } = args;
|
|
338
407
|
const giteaHost = explicitHost || GITEA_HOST;
|
|
408
|
+
const token = explicitToken || process.env.GITEA_TOKEN || null;
|
|
339
409
|
const osArch = detectOSArch();
|
|
340
410
|
const skillDir = resolveSkillDir(platformName, targetPath);
|
|
341
411
|
const scriptsDir = path.join(skillDir, 'scripts', `${osArch.os}-${osArch.arch}`);
|
|
342
412
|
|
|
343
413
|
console.log(`Updating gitea-cli skill (${osArch.os}-${osArch.arch}) at ${skillDir}...`);
|
|
344
414
|
|
|
345
|
-
// 1. Refresh SKILL.md and
|
|
346
|
-
|
|
347
|
-
const destSkill = path.join(skillDir, 'SKILL.md');
|
|
348
|
-
if (fs.existsSync(srcSkill)) {
|
|
349
|
-
fs.mkdirSync(skillDir, { recursive: true });
|
|
350
|
-
fs.copyFileSync(srcSkill, destSkill);
|
|
351
|
-
console.log(` SKILL.md -> ${destSkill}`);
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
const srcRef = path.resolve(__dirname, '..', 'assets', 'REFERENCE.md');
|
|
355
|
-
const destRef = path.join(skillDir, 'REFERENCE.md');
|
|
356
|
-
if (fs.existsSync(srcRef)) {
|
|
357
|
-
fs.copyFileSync(srcRef, destRef);
|
|
358
|
-
console.log(` REFERENCE.md -> ${destRef}`);
|
|
359
|
-
}
|
|
415
|
+
// 1. Refresh SKILL.md and references/
|
|
416
|
+
copySkillFiles(skillDir);
|
|
360
417
|
|
|
361
418
|
// 2. Re-download / re-copy binary (always overwrite)
|
|
362
419
|
const binaryName = osArch.os === 'windows' ? 'gitea-cli.exe' : 'gitea-cli';
|
|
@@ -365,21 +422,24 @@ async function update(args) {
|
|
|
365
422
|
if (localDir) {
|
|
366
423
|
installFromLocal(localDir, scriptsDir, destBinary, osArch);
|
|
367
424
|
} else {
|
|
368
|
-
|
|
369
|
-
await installFromRelease(giteaHost, token, scriptsDir, destBinary, osArch);
|
|
425
|
+
await installFromRelease(giteaHost, token, scriptsDir, destBinary, osArch, insecure);
|
|
370
426
|
}
|
|
371
427
|
|
|
428
|
+
// 3. Version consistency check
|
|
429
|
+
checkVersionConsistency(destBinary);
|
|
430
|
+
|
|
372
431
|
console.log('\nDone! Configuration preserved.');
|
|
373
432
|
}
|
|
374
433
|
|
|
375
434
|
// ── CLI ──────────────────────────────────────────────────────────────────────
|
|
376
435
|
|
|
377
436
|
function parseArgs(argv) {
|
|
378
|
-
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 };
|
|
379
438
|
|
|
380
439
|
for (let i = 2; i < argv.length; i++) {
|
|
381
440
|
const arg = argv[i];
|
|
382
|
-
if (arg === '--
|
|
441
|
+
if (arg === '--') break; // end of options
|
|
442
|
+
else if (arg === '--token' && i + 1 < argv.length) args.token = argv[++i];
|
|
383
443
|
else if (arg === '--host' && i + 1 < argv.length) args.host = argv[++i];
|
|
384
444
|
else if (arg === '--platform' && i + 1 < argv.length) args.platform = argv[++i];
|
|
385
445
|
else if (arg === '--target' && i + 1 < argv.length) args.target = argv[++i];
|
|
@@ -388,6 +448,8 @@ function parseArgs(argv) {
|
|
|
388
448
|
else if (arg === '--default-owner' && i + 1 < argv.length) args['default-owner'] = argv[++i];
|
|
389
449
|
else if (arg === '--default-repo' && i + 1 < argv.length) args['default-repo'] = argv[++i];
|
|
390
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); }
|
|
391
453
|
else if (arg === '--help' || arg === '-h') { printHelp(); process.exit(0); }
|
|
392
454
|
else if (!arg.startsWith('-') && !args.command) args.command = arg;
|
|
393
455
|
else if (!arg.startsWith('-') && args.command && !args.subcommand) args.subcommand = arg;
|
|
@@ -400,7 +462,7 @@ function printHelp() {
|
|
|
400
462
|
.map(([k, v]) => ` ${k.padEnd(10)} ${v.desc}`)
|
|
401
463
|
.join('\n');
|
|
402
464
|
|
|
403
|
-
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
|
|
404
466
|
|
|
405
467
|
Usage:
|
|
406
468
|
npx gitea-cli-skill init [flags] # Install + configure
|
|
@@ -409,7 +471,7 @@ Usage:
|
|
|
409
471
|
|
|
410
472
|
Commands:
|
|
411
473
|
init Install skill (binary + SKILL.md) and optionally configure context
|
|
412
|
-
update Refresh binary and SKILL.md/
|
|
474
|
+
update Refresh binary and SKILL.md/references/ (keeps config)
|
|
413
475
|
add context Add or update a Gitea API context (requires --token)
|
|
414
476
|
|
|
415
477
|
Flags (init):
|
|
@@ -424,6 +486,7 @@ Flags (init):
|
|
|
424
486
|
--force Overwrite existing binary
|
|
425
487
|
|
|
426
488
|
Flags (update):
|
|
489
|
+
--token <t> Gitea API token (overrides GITEA_TOKEN env var)
|
|
427
490
|
--host <url> Gitea host URL (default: ${GITEA_HOST})
|
|
428
491
|
--local <dir> Update from local goreleaser dist directory (skip download)
|
|
429
492
|
--platform <name> Target AI platform (default: claude)
|
|
@@ -439,6 +502,8 @@ Flags (add context):
|
|
|
439
502
|
|
|
440
503
|
Global:
|
|
441
504
|
-h, --help Show this help
|
|
505
|
+
-v, --version Show version
|
|
506
|
+
--insecure Skip SSL certificate verification (not recommended)
|
|
442
507
|
|
|
443
508
|
Platforms:
|
|
444
509
|
${platformList}
|
|
@@ -476,7 +541,6 @@ async function main() {
|
|
|
476
541
|
if (!args.command) { printHelp(); process.exit(0); }
|
|
477
542
|
|
|
478
543
|
if (args.command === 'init') {
|
|
479
|
-
// Validate platform name
|
|
480
544
|
if (args.platform && !PLATFORMS[args.platform] && !args.target) {
|
|
481
545
|
console.error(`Unknown platform: ${args.platform}`);
|
|
482
546
|
console.error(`Available: ${Object.keys(PLATFORMS).join(', ')}, or use --target for custom path.`);
|
|
File without changes
|