@agentrules/cli 0.0.11 → 0.0.12
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 +24 -3
- package/dist/index.js +177 -46
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -34,7 +34,8 @@ agentrules add <preset> --platform <platform> [options]
|
|
|
34
34
|
| `-g, --global` | Install to global config directory |
|
|
35
35
|
| `--dir <path>` | Install to a custom directory |
|
|
36
36
|
| `-r, --registry <alias>` | Use a specific registry |
|
|
37
|
-
| `-f, --force` | Overwrite existing files |
|
|
37
|
+
| `-f, --force` | Overwrite existing files (backs up originals to `.bak`) |
|
|
38
|
+
| `--no-backup` | Don't backup files before overwriting (use with `--force`) |
|
|
38
39
|
| `--dry-run` | Preview changes without writing |
|
|
39
40
|
| `--skip-conflicts` | Skip files that already exist |
|
|
40
41
|
|
|
@@ -200,12 +201,32 @@ agentrules publish --dry-run
|
|
|
200
201
|
|
|
201
202
|
**Versioning:** Presets use `MAJOR.MINOR` versioning. You set the major version, and the registry auto-increments the minor version on each publish.
|
|
202
203
|
|
|
203
|
-
### `agentrules unpublish <
|
|
204
|
+
### `agentrules unpublish <preset>`
|
|
204
205
|
|
|
205
206
|
Remove a specific version of a preset from the registry. Requires authentication.
|
|
206
207
|
|
|
207
208
|
```bash
|
|
208
|
-
agentrules unpublish
|
|
209
|
+
agentrules unpublish <preset> [options]
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
**Options:**
|
|
213
|
+
|
|
214
|
+
| Option | Description |
|
|
215
|
+
|--------|-------------|
|
|
216
|
+
| `-p, --platform <platform>` | Target platform (if not in preset string) |
|
|
217
|
+
| `-V, --version <version>` | Version to unpublish (if not in preset string) |
|
|
218
|
+
|
|
219
|
+
**Examples:**
|
|
220
|
+
|
|
221
|
+
```bash
|
|
222
|
+
# Full format: slug.platform@version
|
|
223
|
+
agentrules unpublish my-preset.opencode@1.0
|
|
224
|
+
|
|
225
|
+
# With flags
|
|
226
|
+
agentrules unpublish my-preset --platform opencode --version 1.0
|
|
227
|
+
|
|
228
|
+
# Mixed: version in string, platform as flag
|
|
229
|
+
agentrules unpublish my-preset@1.0 --platform opencode
|
|
209
230
|
```
|
|
210
231
|
|
|
211
232
|
**Note:** Unpublished versions cannot be republished with the same version number.
|
package/dist/index.js
CHANGED
|
@@ -8,7 +8,7 @@ import { promisify } from "util";
|
|
|
8
8
|
import * as client from "openid-client";
|
|
9
9
|
import chalk from "chalk";
|
|
10
10
|
import { chmod, constants } from "fs";
|
|
11
|
-
import { access, constants as constants$1, mkdir, readFile, readdir, rm, stat, writeFile } from "fs/promises";
|
|
11
|
+
import { access, constants as constants$1, copyFile, mkdir, readFile, readdir, rm, stat, writeFile } from "fs/promises";
|
|
12
12
|
import { homedir } from "os";
|
|
13
13
|
import * as p from "@clack/prompts";
|
|
14
14
|
|
|
@@ -221,6 +221,14 @@ function fileStatus(status, filePath, options = {}) {
|
|
|
221
221
|
return `${config.style(config.symbol)} ${config.style(pad(label, 14))} ${filePath}`;
|
|
222
222
|
}
|
|
223
223
|
/**
|
|
224
|
+
* Format a backup status line
|
|
225
|
+
* e.g., "↪ backed up .opencode/AGENT_RULES.md → .opencode/AGENT_RULES.md.bak"
|
|
226
|
+
*/
|
|
227
|
+
function backupStatus(originalPath, backupPath, options = {}) {
|
|
228
|
+
const label = options.dryRun ? "would backup" : "backed up";
|
|
229
|
+
return `${theme.info("↪")} ${theme.info(pad(label, 14))} ${originalPath} ${symbols.arrow} ${backupPath}`;
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
224
232
|
* Step indicator for multi-step operations
|
|
225
233
|
* e.g., "[1/3] Fetching registry..."
|
|
226
234
|
*/
|
|
@@ -335,6 +343,7 @@ const ui = {
|
|
|
335
343
|
warning,
|
|
336
344
|
info: info$1,
|
|
337
345
|
fileStatus,
|
|
346
|
+
backupStatus,
|
|
338
347
|
step,
|
|
339
348
|
brand,
|
|
340
349
|
banner,
|
|
@@ -1209,6 +1218,7 @@ async function addPreset(options) {
|
|
|
1209
1218
|
const writeStats = await writeBundleFiles(bundle, target, {
|
|
1210
1219
|
force: Boolean(options.force),
|
|
1211
1220
|
skipConflicts: Boolean(options.skipConflicts),
|
|
1221
|
+
noBackup: Boolean(options.noBackup),
|
|
1212
1222
|
dryRun
|
|
1213
1223
|
});
|
|
1214
1224
|
return {
|
|
@@ -1216,6 +1226,7 @@ async function addPreset(options) {
|
|
|
1216
1226
|
bundle,
|
|
1217
1227
|
files: writeStats.files,
|
|
1218
1228
|
conflicts: writeStats.conflicts,
|
|
1229
|
+
backups: writeStats.backups,
|
|
1219
1230
|
targetRoot: target.root,
|
|
1220
1231
|
targetLabel: target.label,
|
|
1221
1232
|
registryAlias,
|
|
@@ -1298,6 +1309,7 @@ function resolveInstallTarget(platform, options) {
|
|
|
1298
1309
|
async function writeBundleFiles(bundle, target, behavior) {
|
|
1299
1310
|
const files = [];
|
|
1300
1311
|
const conflicts = [];
|
|
1312
|
+
const backups = [];
|
|
1301
1313
|
if (!behavior.dryRun) await mkdir(target.root, { recursive: true });
|
|
1302
1314
|
for (const file of bundle.files) {
|
|
1303
1315
|
const decoded = decodeBundledFile(file);
|
|
@@ -1326,6 +1338,16 @@ async function writeBundleFiles(bundle, target, behavior) {
|
|
|
1326
1338
|
continue;
|
|
1327
1339
|
}
|
|
1328
1340
|
if (behavior.force) {
|
|
1341
|
+
if (!behavior.noBackup) {
|
|
1342
|
+
const backupPath = `${destination}.bak`;
|
|
1343
|
+
const relativeBackupPath = `${relativePath}.bak`;
|
|
1344
|
+
if (!behavior.dryRun) await copyFile(destination, backupPath);
|
|
1345
|
+
backups.push({
|
|
1346
|
+
originalPath: relativePath,
|
|
1347
|
+
backupPath: relativeBackupPath
|
|
1348
|
+
});
|
|
1349
|
+
log.debug(`Backed up: ${relativePath} → ${relativeBackupPath}`);
|
|
1350
|
+
}
|
|
1329
1351
|
if (!behavior.dryRun) await writeFile(destination, data);
|
|
1330
1352
|
files.push({
|
|
1331
1353
|
path: relativePath,
|
|
@@ -1346,7 +1368,8 @@ async function writeBundleFiles(bundle, target, behavior) {
|
|
|
1346
1368
|
}
|
|
1347
1369
|
return {
|
|
1348
1370
|
files,
|
|
1349
|
-
conflicts
|
|
1371
|
+
conflicts,
|
|
1372
|
+
backups
|
|
1350
1373
|
};
|
|
1351
1374
|
}
|
|
1352
1375
|
/**
|
|
@@ -1621,6 +1644,66 @@ async function detectPlatforms(directory) {
|
|
|
1621
1644
|
return detected;
|
|
1622
1645
|
}
|
|
1623
1646
|
/**
|
|
1647
|
+
* Resolve the target platform directory for initialization.
|
|
1648
|
+
*
|
|
1649
|
+
* Detection order (deterministic):
|
|
1650
|
+
* 1. If targetDir itself is a platform directory (e.g., ".claude"), use it directly
|
|
1651
|
+
* 2. Otherwise, detect platform directories inside targetDir
|
|
1652
|
+
*
|
|
1653
|
+
* @param targetDir - The target directory (cwd or user-provided path)
|
|
1654
|
+
* @param platformOverride - Optional platform to use instead of detecting/inferring
|
|
1655
|
+
*/
|
|
1656
|
+
async function resolvePlatformDirectory(targetDir, platformOverride) {
|
|
1657
|
+
const targetDirName = basename(targetDir);
|
|
1658
|
+
const targetPlatform = getPlatformFromDir(targetDirName);
|
|
1659
|
+
if (targetPlatform) {
|
|
1660
|
+
const platform$1 = platformOverride ? normalizePlatform(platformOverride) : targetPlatform;
|
|
1661
|
+
return {
|
|
1662
|
+
platformDir: targetDir,
|
|
1663
|
+
platform: platform$1,
|
|
1664
|
+
isTargetPlatformDir: true,
|
|
1665
|
+
detected: []
|
|
1666
|
+
};
|
|
1667
|
+
}
|
|
1668
|
+
const detected = await detectPlatforms(targetDir);
|
|
1669
|
+
let platform;
|
|
1670
|
+
let platformDir;
|
|
1671
|
+
if (platformOverride) {
|
|
1672
|
+
platform = normalizePlatform(platformOverride);
|
|
1673
|
+
const detectedPath = detected.find((d) => d.id === platform)?.path;
|
|
1674
|
+
platformDir = detectedPath ? join(targetDir, detectedPath) : join(targetDir, PLATFORMS[platform].projectDir);
|
|
1675
|
+
} else if (detected.length > 0) {
|
|
1676
|
+
platform = detected[0].id;
|
|
1677
|
+
platformDir = join(targetDir, detected[0].path);
|
|
1678
|
+
} else {
|
|
1679
|
+
platform = "opencode";
|
|
1680
|
+
platformDir = join(targetDir, PLATFORMS.opencode.projectDir);
|
|
1681
|
+
}
|
|
1682
|
+
return {
|
|
1683
|
+
platformDir,
|
|
1684
|
+
platform,
|
|
1685
|
+
isTargetPlatformDir: false,
|
|
1686
|
+
detected
|
|
1687
|
+
};
|
|
1688
|
+
}
|
|
1689
|
+
/**
|
|
1690
|
+
* Check if --platform flag is required for non-interactive mode.
|
|
1691
|
+
* Returns the reason if required, so CLI can show appropriate error.
|
|
1692
|
+
*/
|
|
1693
|
+
function requiresPlatformFlag(resolved) {
|
|
1694
|
+
if (resolved.isTargetPlatformDir) return { required: false };
|
|
1695
|
+
if (resolved.detected.length === 0) return {
|
|
1696
|
+
required: true,
|
|
1697
|
+
reason: "no_platforms"
|
|
1698
|
+
};
|
|
1699
|
+
if (resolved.detected.length > 1) return {
|
|
1700
|
+
required: true,
|
|
1701
|
+
reason: "multiple_platforms",
|
|
1702
|
+
platforms: resolved.detected.map((d) => d.id)
|
|
1703
|
+
};
|
|
1704
|
+
return { required: false };
|
|
1705
|
+
}
|
|
1706
|
+
/**
|
|
1624
1707
|
* Initialize a preset in a platform directory.
|
|
1625
1708
|
*
|
|
1626
1709
|
* Structure:
|
|
@@ -1704,30 +1787,36 @@ async function initInteractive(options) {
|
|
|
1704
1787
|
let selectedPlatform;
|
|
1705
1788
|
if (explicitPlatformDir) {
|
|
1706
1789
|
targetPlatformDir = explicitPlatformDir;
|
|
1707
|
-
const dirName = explicitPlatformDir
|
|
1790
|
+
const dirName = basename(explicitPlatformDir);
|
|
1708
1791
|
selectedPlatform = platformOption ?? getPlatformFromDir(dirName) ?? "opencode";
|
|
1709
1792
|
} else {
|
|
1710
|
-
const
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1793
|
+
const resolved = await resolvePlatformDirectory(baseDir, platformOption);
|
|
1794
|
+
if (resolved.isTargetPlatformDir) {
|
|
1795
|
+
targetPlatformDir = resolved.platformDir;
|
|
1796
|
+
selectedPlatform = resolved.platform;
|
|
1797
|
+
p.note(`Detected platform directory: ${resolved.platform}`, "Using current directory");
|
|
1798
|
+
} else {
|
|
1799
|
+
const detectedMap = new Map(resolved.detected.map((d) => [d.id, d]));
|
|
1800
|
+
if (resolved.detected.length > 0) p.note(resolved.detected.map((d) => `${d.id} → ${d.path}`).join("\n"), "Detected platform directories");
|
|
1801
|
+
const platformChoice = await p.select({
|
|
1802
|
+
message: "Platform",
|
|
1803
|
+
options: PLATFORM_IDS.map((id) => ({
|
|
1804
|
+
value: id,
|
|
1805
|
+
label: detectedMap.has(id) ? `${id} (detected)` : id,
|
|
1806
|
+
hint: detectedMap.get(id)?.path
|
|
1807
|
+
})),
|
|
1808
|
+
initialValue: resolved.platform
|
|
1809
|
+
});
|
|
1810
|
+
if (p.isCancel(platformChoice)) {
|
|
1811
|
+
p.cancel("Cancelled");
|
|
1812
|
+
process.exit(0);
|
|
1813
|
+
}
|
|
1814
|
+
selectedPlatform = platformChoice;
|
|
1815
|
+
if (selectedPlatform !== resolved.platform) {
|
|
1816
|
+
const reResolved = await resolvePlatformDirectory(baseDir, selectedPlatform);
|
|
1817
|
+
targetPlatformDir = reResolved.platformDir;
|
|
1818
|
+
} else targetPlatformDir = resolved.platformDir;
|
|
1726
1819
|
}
|
|
1727
|
-
selectedPlatform = platformChoice;
|
|
1728
|
-
const detectedInfo = detectedMap.get(selectedPlatform);
|
|
1729
|
-
if (detectedInfo) targetPlatformDir = join(baseDir, detectedInfo.path);
|
|
1730
|
-
else targetPlatformDir = join(baseDir, PLATFORMS[selectedPlatform].projectDir);
|
|
1731
1820
|
}
|
|
1732
1821
|
const configPath = join(targetPlatformDir, PRESET_CONFIG_FILENAME);
|
|
1733
1822
|
if (!force && await fileExists(configPath)) {
|
|
@@ -2139,10 +2228,45 @@ async function discoverPresetDirs(inputDir) {
|
|
|
2139
2228
|
//#endregion
|
|
2140
2229
|
//#region src/commands/unpublish.ts
|
|
2141
2230
|
/**
|
|
2231
|
+
* Parses preset input to extract slug, platform, and version.
|
|
2232
|
+
* Supports formats:
|
|
2233
|
+
* - "my-preset.claude@1.0" (platform and version in string)
|
|
2234
|
+
* - "my-preset@1.0" (requires explicit platform)
|
|
2235
|
+
* - "my-preset.claude" (requires explicit version)
|
|
2236
|
+
*
|
|
2237
|
+
* Explicit --platform and --version flags take precedence.
|
|
2238
|
+
*/
|
|
2239
|
+
function parseUnpublishInput(input, explicitPlatform, explicitVersion) {
|
|
2240
|
+
let normalized = input.toLowerCase().trim();
|
|
2241
|
+
let parsedVersion;
|
|
2242
|
+
const atIndex = normalized.lastIndexOf("@");
|
|
2243
|
+
if (atIndex > 0) {
|
|
2244
|
+
parsedVersion = normalized.slice(atIndex + 1);
|
|
2245
|
+
normalized = normalized.slice(0, atIndex);
|
|
2246
|
+
}
|
|
2247
|
+
const version$1 = explicitVersion ?? parsedVersion;
|
|
2248
|
+
const parts = normalized.split(".");
|
|
2249
|
+
const maybePlatform = parts.at(-1);
|
|
2250
|
+
let slug;
|
|
2251
|
+
let platform;
|
|
2252
|
+
if (maybePlatform && isSupportedPlatform(maybePlatform)) {
|
|
2253
|
+
slug = parts.slice(0, -1).join(".");
|
|
2254
|
+
platform = explicitPlatform ?? maybePlatform;
|
|
2255
|
+
} else {
|
|
2256
|
+
slug = normalized;
|
|
2257
|
+
platform = explicitPlatform;
|
|
2258
|
+
}
|
|
2259
|
+
return {
|
|
2260
|
+
slug,
|
|
2261
|
+
platform,
|
|
2262
|
+
version: version$1
|
|
2263
|
+
};
|
|
2264
|
+
}
|
|
2265
|
+
/**
|
|
2142
2266
|
* Unpublishes a preset version from the registry
|
|
2143
2267
|
*/
|
|
2144
2268
|
async function unpublish(options) {
|
|
2145
|
-
const { slug, platform, version: version$1 } = options;
|
|
2269
|
+
const { slug, platform, version: version$1 } = parseUnpublishInput(options.preset, options.platform, options.version);
|
|
2146
2270
|
if (!slug) {
|
|
2147
2271
|
log.error("Preset slug is required");
|
|
2148
2272
|
return {
|
|
@@ -2151,14 +2275,14 @@ async function unpublish(options) {
|
|
|
2151
2275
|
};
|
|
2152
2276
|
}
|
|
2153
2277
|
if (!platform) {
|
|
2154
|
-
log.error("Platform is required");
|
|
2278
|
+
log.error("Platform is required. Use --platform or specify as <slug>.<platform>@<version>");
|
|
2155
2279
|
return {
|
|
2156
2280
|
success: false,
|
|
2157
2281
|
error: "Platform is required"
|
|
2158
2282
|
};
|
|
2159
2283
|
}
|
|
2160
2284
|
if (!version$1) {
|
|
2161
|
-
log.error("Version is required");
|
|
2285
|
+
log.error("Version is required. Use --version or specify as <slug>.<platform>@<version>");
|
|
2162
2286
|
return {
|
|
2163
2287
|
success: false,
|
|
2164
2288
|
error: "Version is required"
|
|
@@ -2217,7 +2341,7 @@ program.name("agentrules").description("The AI Agent Directory CLI").version(pac
|
|
|
2217
2341
|
log.debug(`Failed to init context: ${getErrorMessage(error$2)}`);
|
|
2218
2342
|
}
|
|
2219
2343
|
}).showHelpAfterError();
|
|
2220
|
-
program.command("add <preset>").description("Download and install a preset from the registry").option("-p, --platform <platform>", "Target platform (opencode, codex, claude, cursor)").option("-V, --version <version>", "Install a specific version").option("-r, --registry <alias>", "Use a specific registry alias").option("-g, --global", "Install to global directory").option("--dir <path>", "Install to a custom directory").option("-f, --force", "Overwrite existing files").option("-y, --yes", "Alias for --force").option("--dry-run", "Preview changes without writing").option("--skip-conflicts", "Skip conflicting files").action(handle(async (preset, options) => {
|
|
2344
|
+
program.command("add <preset>").description("Download and install a preset from the registry").option("-p, --platform <platform>", "Target platform (opencode, codex, claude, cursor)").option("-V, --version <version>", "Install a specific version").option("-r, --registry <alias>", "Use a specific registry alias").option("-g, --global", "Install to global directory").option("--dir <path>", "Install to a custom directory").option("-f, --force", "Overwrite existing files (backs up originals)").option("-y, --yes", "Alias for --force").option("--dry-run", "Preview changes without writing").option("--skip-conflicts", "Skip conflicting files").option("--no-backup", "Don't backup files before overwriting (use with --force)").action(handle(async (preset, options) => {
|
|
2221
2345
|
const platform = options.platform ? normalizePlatformInput(options.platform) : void 0;
|
|
2222
2346
|
const dryRun = Boolean(options.dryRun);
|
|
2223
2347
|
const spinner$1 = await log.spinner("Fetching preset...");
|
|
@@ -2231,7 +2355,8 @@ program.command("add <preset>").description("Download and install a preset from
|
|
|
2231
2355
|
directory: options.dir,
|
|
2232
2356
|
force: Boolean(options.force || options.yes),
|
|
2233
2357
|
dryRun,
|
|
2234
|
-
skipConflicts: Boolean(options.skipConflicts)
|
|
2358
|
+
skipConflicts: Boolean(options.skipConflicts),
|
|
2359
|
+
noBackup: options.backup === false
|
|
2235
2360
|
});
|
|
2236
2361
|
} catch (err) {
|
|
2237
2362
|
spinner$1.stop();
|
|
@@ -2241,16 +2366,23 @@ program.command("add <preset>").description("Download and install a preset from
|
|
|
2241
2366
|
const hasBlockingConflicts = result.conflicts.length > 0 && !options.skipConflicts && !dryRun;
|
|
2242
2367
|
if (hasBlockingConflicts) {
|
|
2243
2368
|
const count$1 = result.conflicts.length === 1 ? "1 file has" : `${result.conflicts.length} files have`;
|
|
2244
|
-
|
|
2369
|
+
const forceHint = `Use ${ui.command("--force")} to overwrite ${ui.muted("(--no-backup to skip backups)")}`;
|
|
2370
|
+
log.error(`${count$1} conflicts. ${forceHint}`);
|
|
2245
2371
|
log.print("");
|
|
2246
2372
|
for (const conflict of result.conflicts.slice(0, 3)) {
|
|
2247
2373
|
log.print(` ${ui.muted("•")} ${conflict.path}`);
|
|
2248
2374
|
if (conflict.diff) log.print(conflict.diff.split("\n").map((l) => ` ${l}`).join("\n"));
|
|
2249
2375
|
}
|
|
2250
2376
|
if (result.conflicts.length > 3) log.print(`\n ${ui.muted(`...and ${result.conflicts.length - 3} more`)}`);
|
|
2377
|
+
log.print("");
|
|
2378
|
+
log.print(forceHint);
|
|
2251
2379
|
process.exitCode = 1;
|
|
2252
2380
|
return;
|
|
2253
2381
|
}
|
|
2382
|
+
if (result.backups.length > 0) {
|
|
2383
|
+
log.print("");
|
|
2384
|
+
for (const backup of result.backups) log.print(ui.backupStatus(backup.originalPath, backup.backupPath, { dryRun }));
|
|
2385
|
+
}
|
|
2254
2386
|
log.print("");
|
|
2255
2387
|
for (const file of result.files) {
|
|
2256
2388
|
const status = file.status === "overwritten" ? "updated" : file.status;
|
|
@@ -2291,25 +2423,23 @@ program.command("init").description("Initialize a new preset").argument("[direct
|
|
|
2291
2423
|
log.print(ui.numberedList(nextSteps$1));
|
|
2292
2424
|
return;
|
|
2293
2425
|
}
|
|
2294
|
-
const
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
const detectedPath = detected.find((d) => d.id === platform)?.path;
|
|
2305
|
-
platformDir = detectedPath ? join(targetDir, detectedPath) : join(targetDir, PLATFORMS[platform].projectDir);
|
|
2426
|
+
const resolved = await resolvePlatformDirectory(targetDir, options.platform);
|
|
2427
|
+
if (!options.platform) {
|
|
2428
|
+
const check$1 = requiresPlatformFlag(resolved);
|
|
2429
|
+
if (check$1.required) {
|
|
2430
|
+
if (check$1.reason === "no_platforms") {
|
|
2431
|
+
const targetDirName = basename(targetDir);
|
|
2432
|
+
log.error(`No platform directory found in "${targetDirName}". Specify --platform (${PLATFORM_IDS.join(", ")}) or run from a platform directory.`);
|
|
2433
|
+
} else log.error(`Multiple platform directories found (${check$1.platforms.join(", ")}). Specify --platform to choose one.`);
|
|
2434
|
+
process.exit(1);
|
|
2435
|
+
}
|
|
2306
2436
|
}
|
|
2307
2437
|
const result = await initPreset({
|
|
2308
|
-
directory: platformDir,
|
|
2438
|
+
directory: resolved.platformDir,
|
|
2309
2439
|
name: options.name ?? defaultName,
|
|
2310
2440
|
title: options.title,
|
|
2311
2441
|
description: options.description,
|
|
2312
|
-
platform,
|
|
2442
|
+
platform: resolved.platform,
|
|
2313
2443
|
license: options.license,
|
|
2314
2444
|
force: options.force
|
|
2315
2445
|
});
|
|
@@ -2464,11 +2594,12 @@ program.command("publish").description("Publish a preset to the registry").argum
|
|
|
2464
2594
|
});
|
|
2465
2595
|
if (!result.success) process.exitCode = 1;
|
|
2466
2596
|
}));
|
|
2467
|
-
program.command("unpublish").description("Remove a preset version from the registry").argument("<
|
|
2597
|
+
program.command("unpublish").description("Remove a preset version from the registry").argument("<preset>", "Preset to unpublish (e.g., my-preset.claude@1.0 or my-preset@1.0)").option("-p, --platform <platform>", "Target platform (opencode, codex, claude, cursor)").option("-V, --version <version>", "Version to unpublish").action(handle(async (preset, options) => {
|
|
2598
|
+
const platform = options.platform ? normalizePlatformInput(options.platform) : void 0;
|
|
2468
2599
|
const result = await unpublish({
|
|
2469
|
-
|
|
2600
|
+
preset,
|
|
2470
2601
|
platform,
|
|
2471
|
-
version: version
|
|
2602
|
+
version: options.version
|
|
2472
2603
|
});
|
|
2473
2604
|
if (!result.success) process.exitCode = 1;
|
|
2474
2605
|
}));
|