fix(cli): correct skvlt command usage
This commit is contained in:
1 parent
74c3cd5f99
commit
b80f31616a
13 files changed
+135
-95
No files matched your search
@@ -28,24 +28,32 @@ Skills Vault exists to fill the gap described in [vercel-labs/skills#729](https:
|
||||
- Check local setup quickly with `doctor`.
|
||||
- Generate completion scripts for `bash`, `zsh`, and `powershell`.
|
||||
|
||||
## Install
|
||||
|
||||
Install the CLI globally with Bun:
|
||||
|
||||
```bash
|
||||
bun add -g @xixu-me/skills-vault
|
||||
```
|
||||
|
||||
## Quick Start
|
||||
|
||||
Back up your current skills:
|
||||
|
||||
```bash
|
||||
bunx skvlt backup
|
||||
skvlt backup
|
||||
```
|
||||
|
||||
Preview what a restore would run:
|
||||
|
||||
```bash
|
||||
bunx skvlt restore --dry-run
|
||||
skvlt restore --dry-run
|
||||
```
|
||||
|
||||
Restore everything recorded in the manifest:
|
||||
|
||||
```bash
|
||||
bunx skvlt restore --all
|
||||
skvlt restore --all
|
||||
```
|
||||
|
||||
If you want a curated, ready-to-use manifest, see [xixu-me/skvlt](https://github.com/xixu-me/skvlt), a maintained collection of `skvlt.yaml` snapshots.
|
||||
@@ -77,10 +85,10 @@ sources:
|
||||
Snapshot installed skills into `skvlt.yaml`.
|
||||
|
||||
```bash
|
||||
bunx skvlt backup
|
||||
bunx skvlt backup --dry-run
|
||||
bunx skvlt backup --output ./skvlt.yaml
|
||||
bunx skvlt backup --project-scope --lock-file ./skills-lock.json
|
||||
skvlt backup
|
||||
skvlt backup --dry-run
|
||||
skvlt backup --output ./skvlt.yaml
|
||||
skvlt backup --project-scope --lock-file ./skills-lock.json
|
||||
```
|
||||
|
||||
`backup` reads installed skill names, joins them with lock-file metadata, and writes a grouped manifest keyed by source.
|
||||
@@ -93,10 +101,10 @@ bunx skvlt backup --project-scope --lock-file ./skills-lock.json
|
||||
Install skills from a manifest.
|
||||
|
||||
```bash
|
||||
bunx skvlt restore --all
|
||||
bunx skvlt restore --only-source xixu-me/skills
|
||||
bunx skvlt restore --project-scope
|
||||
bunx skvlt restore --dry-run
|
||||
skvlt restore --all
|
||||
skvlt restore --only-source xixu-me/skills
|
||||
skvlt restore --project-scope
|
||||
skvlt restore --dry-run
|
||||
```
|
||||
|
||||
By default, restore respects the scope recorded in the manifest. Use `--project-scope` to force a project install even when the manifest was created from global state.
|
||||
@@ -110,8 +118,8 @@ For a curated manifest source, you can start from [xixu-me/skvlt](https://github
|
||||
Inspect the local Skills Vault environment and global skill state.
|
||||
|
||||
```bash
|
||||
bunx skvlt doctor
|
||||
bunx skvlt doctor --manifest ./skvlt.yaml
|
||||
skvlt doctor
|
||||
skvlt doctor --manifest ./skvlt.yaml
|
||||
```
|
||||
|
||||
`doctor` checks:
|
||||
@@ -127,9 +135,9 @@ bunx skvlt doctor --manifest ./skvlt.yaml
|
||||
Print shell completion scripts.
|
||||
|
||||
```bash
|
||||
bunx skvlt completion bash
|
||||
bunx skvlt completion zsh
|
||||
bunx skvlt completion powershell
|
||||
skvlt completion bash
|
||||
skvlt completion zsh
|
||||
skvlt completion powershell
|
||||
```
|
||||
|
||||
## JSON Output
|
||||
@@ -137,8 +145,8 @@ bunx skvlt completion powershell
|
||||
All top-level commands support `--json` for structured output:
|
||||
|
||||
```bash
|
||||
bunx skvlt --json doctor
|
||||
bunx skvlt --json backup --dry-run
|
||||
skvlt --json doctor
|
||||
skvlt --json backup --dry-run
|
||||
```
|
||||
|
||||
Successful responses include `ok`, `command`, and `data`. Failures include `ok`, `command`, and a stable `error.code` plus message.
|
||||
@@ -189,7 +197,7 @@ npm publish --access public
|
||||
## Troubleshooting
|
||||
|
||||
- If restore reports a global state mismatch, inspect `~/.agents/.skill-lock.json` and `~/.agents/skills`.
|
||||
- If environment checks fail, start with `bunx skvlt doctor`.
|
||||
- If environment checks fail, start with `skvlt doctor`.
|
||||
- If packaging checks fail, run `bun run check` and review the tarball output from `npm pack --dry-run --json`.
|
||||
|
||||
For contribution, support, and security policy details, see [`CONTRIBUTING.md`](./CONTRIBUTING.md), [`SUPPORT.md`](./SUPPORT.md), and [`SECURITY.md`](./SECURITY.md).
|
||||
|
||||
+27
-19
@@ -28,24 +28,32 @@ Skills Vault 的存在,是为了补上 [vercel-labs/skills#729](https://github
|
||||
- 用 `doctor` 快速检查本地环境
|
||||
- 为 `bash`、`zsh` 和 `powershell` 生成补全脚本
|
||||
|
||||
## 安装
|
||||
|
||||
使用 Bun 全局安装 CLI:
|
||||
|
||||
```bash
|
||||
bun add -g @xixu-me/skills-vault
|
||||
```
|
||||
|
||||
## 快速开始
|
||||
|
||||
备份当前已安装的 skills:
|
||||
|
||||
```bash
|
||||
bunx skvlt backup
|
||||
skvlt backup
|
||||
```
|
||||
|
||||
预览一次 restore 将会执行什么:
|
||||
|
||||
```bash
|
||||
bunx skvlt restore --dry-run
|
||||
skvlt restore --dry-run
|
||||
```
|
||||
|
||||
恢复 manifest 中记录的全部内容:
|
||||
|
||||
```bash
|
||||
bunx skvlt restore --all
|
||||
skvlt restore --all
|
||||
```
|
||||
|
||||
如果你想直接使用一个精选好的 manifest,可以查看 [xixu-me/skvlt](https://github.com/xixu-me/skvlt),这是一个持续维护的 `skvlt.yaml` 集合。
|
||||
@@ -77,10 +85,10 @@ sources:
|
||||
把已安装的 skills 快照到 `skvlt.yaml`。
|
||||
|
||||
```bash
|
||||
bunx skvlt backup
|
||||
bunx skvlt backup --dry-run
|
||||
bunx skvlt backup --output ./skvlt.yaml
|
||||
bunx skvlt backup --project-scope --lock-file ./skills-lock.json
|
||||
skvlt backup
|
||||
skvlt backup --dry-run
|
||||
skvlt backup --output ./skvlt.yaml
|
||||
skvlt backup --project-scope --lock-file ./skills-lock.json
|
||||
```
|
||||
|
||||
`backup` 会先读取已安装的 skill 名称,再结合 lock file 元数据,最终按 source 分组写出 manifest。
|
||||
@@ -93,10 +101,10 @@ bunx skvlt backup --project-scope --lock-file ./skills-lock.json
|
||||
从 manifest 安装 skills。
|
||||
|
||||
```bash
|
||||
bunx skvlt restore --all
|
||||
bunx skvlt restore --only-source xixu-me/skills
|
||||
bunx skvlt restore --project-scope
|
||||
bunx skvlt restore --dry-run
|
||||
skvlt restore --all
|
||||
skvlt restore --only-source xixu-me/skills
|
||||
skvlt restore --project-scope
|
||||
skvlt restore --dry-run
|
||||
```
|
||||
|
||||
默认情况下,`restore` 会遵循 manifest 中记录的 scope。如果希望即使 manifest 来自全局状态,也强制恢复到项目作用域,可以使用 `--project-scope`。
|
||||
@@ -110,8 +118,8 @@ bunx skvlt restore --dry-run
|
||||
检查本地 Skills Vault 环境和全局 skill 状态。
|
||||
|
||||
```bash
|
||||
bunx skvlt doctor
|
||||
bunx skvlt doctor --manifest ./skvlt.yaml
|
||||
skvlt doctor
|
||||
skvlt doctor --manifest ./skvlt.yaml
|
||||
```
|
||||
|
||||
`doctor` 会检查:
|
||||
@@ -127,9 +135,9 @@ bunx skvlt doctor --manifest ./skvlt.yaml
|
||||
输出 shell 补全脚本。
|
||||
|
||||
```bash
|
||||
bunx skvlt completion bash
|
||||
bunx skvlt completion zsh
|
||||
bunx skvlt completion powershell
|
||||
skvlt completion bash
|
||||
skvlt completion zsh
|
||||
skvlt completion powershell
|
||||
```
|
||||
|
||||
## JSON 输出
|
||||
@@ -137,8 +145,8 @@ bunx skvlt completion powershell
|
||||
所有顶层命令都支持 `--json` 结构化输出:
|
||||
|
||||
```bash
|
||||
bunx skvlt --json doctor
|
||||
bunx skvlt --json backup --dry-run
|
||||
skvlt --json doctor
|
||||
skvlt --json backup --dry-run
|
||||
```
|
||||
|
||||
成功时会返回 `ok`、`command` 和 `data`。失败时会返回 `ok`、`command`,以及稳定的 `error.code` 和错误消息。
|
||||
@@ -189,7 +197,7 @@ npm publish --access public
|
||||
## 故障排查
|
||||
|
||||
- 如果 restore 报告全局状态不一致,请检查 `~/.agents/.skill-lock.json` 和 `~/.agents/skills`
|
||||
- 如果环境检查失败,先运行 `bunx skvlt doctor`
|
||||
- 如果环境检查失败,先运行 `skvlt doctor`
|
||||
- 如果打包检查失败,运行 `bun run check`,并检查 `npm pack --dry-run --json` 的输出
|
||||
|
||||
关于贡献、支持和安全策略,请参阅 [`CONTRIBUTING.md`](./CONTRIBUTING.md)、[`SUPPORT.md`](./SUPPORT.md) 和 [`SECURITY.md`](./SECURITY.md)。
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@xixu-me/skills-vault",
|
||||
"version": "1.1.1",
|
||||
"version": "1.1.2",
|
||||
"description": "The CLI for backing up and restoring Agent Skills",
|
||||
"author": "Xi Xu",
|
||||
"bin": {
|
||||
|
||||
+11
-11
@@ -34,7 +34,7 @@ function printHelp(): string {
|
||||
"The CLI for backing up and restoring Agent Skills",
|
||||
"",
|
||||
helpHeading("Usage"),
|
||||
" bunx skvlt <command> [options]",
|
||||
" skvlt <command> [options]",
|
||||
"",
|
||||
helpHeading("Commands"),
|
||||
" backup Backup installed skills into a manifest",
|
||||
@@ -48,11 +48,11 @@ function printHelp(): string {
|
||||
" -v, --version Print the installed package version",
|
||||
"",
|
||||
helpHeading("Examples"),
|
||||
helpExample("bunx skvlt backup --output ./skvlt.yaml"),
|
||||
helpExample("bunx skvlt completion bash"),
|
||||
helpExample("bunx skvlt doctor"),
|
||||
helpExample("bunx skvlt restore --all"),
|
||||
helpExample("bunx skvlt restore --only-source xixu-me/skills"),
|
||||
helpExample("skvlt backup --output ./skvlt.yaml"),
|
||||
helpExample("skvlt completion bash"),
|
||||
helpExample("skvlt doctor"),
|
||||
helpExample("skvlt restore --all"),
|
||||
helpExample("skvlt restore --only-source xixu-me/skills"),
|
||||
helpFooter("https://github.com/xixu-me/skills-vault"),
|
||||
].join("\n")}`;
|
||||
}
|
||||
@@ -65,10 +65,10 @@ function printLanding(): string {
|
||||
return `\n${[
|
||||
dimGray("The CLI for backing up and restoring Agent Skills"),
|
||||
"",
|
||||
landingCommand("bunx skvlt backup", "Backup installed skills"),
|
||||
landingCommand("bunx skvlt restore", "Restore from skvlt.yaml"),
|
||||
landingCommand("bunx skvlt doctor", "Inspect local setup"),
|
||||
landingCommand("bunx skvlt completion", "Print shell completions"),
|
||||
landingCommand("skvlt backup", "Backup installed skills"),
|
||||
landingCommand("skvlt restore", "Restore from skvlt.yaml"),
|
||||
landingCommand("skvlt doctor", "Inspect local setup"),
|
||||
landingCommand("skvlt completion", "Print shell completions"),
|
||||
"",
|
||||
`${dimGray("Explore the open-source repo at")} ${textGray("https://github.com/xixu-me/skills-vault")}\n`,
|
||||
].join("\n")}`;
|
||||
@@ -177,7 +177,7 @@ export async function runCli(
|
||||
exitCode: 1,
|
||||
stdout: "",
|
||||
stderr: page(
|
||||
`Unknown command: ${command}\nRun ${bold("bunx skvlt --help")} for usage.`,
|
||||
`Unknown command: ${command}\nRun ${bold("skvlt --help")} for usage.`,
|
||||
),
|
||||
errorCode: "UNKNOWN_COMMAND",
|
||||
};
|
||||
|
||||
+10
-7
@@ -48,7 +48,7 @@ function printHelp(): string {
|
||||
"Backup installed skills into skvlt.yaml.",
|
||||
"",
|
||||
helpHeading("Usage"),
|
||||
" bunx skvlt backup [options]",
|
||||
" skvlt backup [options]",
|
||||
"",
|
||||
helpHeading("Options"),
|
||||
" --output <path> Output path for skvlt.yaml",
|
||||
@@ -63,10 +63,10 @@ function printHelp(): string {
|
||||
" - Project scope currently requires --lock-file because the Skills CLI does not expose a discoverable project lock path here.",
|
||||
"",
|
||||
helpHeading("Examples"),
|
||||
helpExample("bunx skvlt backup"),
|
||||
helpExample(`bunx skvlt backup --output ${formatCliPath("./skvlt.yaml")}`),
|
||||
helpExample("skvlt backup"),
|
||||
helpExample(`skvlt backup --output ${formatCliPath("./skvlt.yaml")}`),
|
||||
helpExample(
|
||||
`bunx skvlt backup --project-scope --lock-file ${formatCliPath("./skills-lock.json")}`,
|
||||
`skvlt backup --project-scope --lock-file ${formatCliPath("./skills-lock.json")}`,
|
||||
),
|
||||
helpFooter("https://github.com/xixu-me/skills-vault"),
|
||||
].join("\n")}`;
|
||||
@@ -108,8 +108,8 @@ function formatBackupError(message: string, errorCode: string): string {
|
||||
if (errorCode === "INVALID_ARGUMENT") {
|
||||
return commandErrorPage(
|
||||
message,
|
||||
"bunx skvlt backup [options]",
|
||||
`bunx skvlt backup --output ${formatCliPath("./skvlt.yaml")}`,
|
||||
"skvlt backup [options]",
|
||||
`skvlt backup --output ${formatCliPath("./skvlt.yaml")}`,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -184,7 +184,10 @@ export async function runBackup(
|
||||
}
|
||||
|
||||
appendLine(`Writing manifest to ${formatCliPath(options.outputPath)}...`);
|
||||
mkdirSync(dirname(resolve(options.outputPath)), { recursive: true });
|
||||
const outputDirectoryPath = dirname(resolve(options.outputPath));
|
||||
if (!existsSync(outputDirectoryPath)) {
|
||||
mkdirSync(outputDirectoryPath, { recursive: true });
|
||||
}
|
||||
writeManifestImpl(options.outputPath, manifest.yaml);
|
||||
appendLine(
|
||||
`Backup summary: ${manifest.totalSkills} skill(s) across ${manifest.totalSources} source(s) written to ${formatCliPath(options.outputPath)}`,
|
||||
|
||||
@@ -21,18 +21,18 @@ export type CompletionRunResult = {
|
||||
|
||||
function printHelp(): string {
|
||||
return `\n${[
|
||||
"Print shell completion scripts for bunx skvlt.",
|
||||
"Print shell completion scripts for skvlt.",
|
||||
"",
|
||||
helpHeading("Usage"),
|
||||
" bunx skvlt completion <bash|zsh|powershell>",
|
||||
" skvlt completion <bash|zsh|powershell>",
|
||||
"",
|
||||
helpHeading("Options"),
|
||||
" --help Show this help",
|
||||
"",
|
||||
helpHeading("Examples"),
|
||||
helpExample("bunx skvlt completion bash"),
|
||||
helpExample("bunx skvlt completion zsh"),
|
||||
helpExample("bunx skvlt completion powershell"),
|
||||
helpExample("skvlt completion bash"),
|
||||
helpExample("skvlt completion zsh"),
|
||||
helpExample("skvlt completion powershell"),
|
||||
helpFooter("https://github.com/xixu-me/skills-vault"),
|
||||
].join("\n")}`;
|
||||
}
|
||||
@@ -154,8 +154,8 @@ function formatCompletionError(message: string, errorCode: string): string {
|
||||
if (errorCode === "INVALID_ARGUMENT") {
|
||||
return commandErrorPage(
|
||||
message,
|
||||
"bunx skvlt completion <bash|zsh|powershell>",
|
||||
"bunx skvlt completion bash",
|
||||
"skvlt completion <bash|zsh|powershell>",
|
||||
"skvlt completion bash",
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -59,15 +59,15 @@ function printHelp(): string {
|
||||
"Inspect the local Skills Vault environment and installation state.",
|
||||
"",
|
||||
helpHeading("Usage"),
|
||||
" bunx skvlt doctor [options]",
|
||||
" skvlt doctor [options]",
|
||||
"",
|
||||
helpHeading("Options"),
|
||||
" --manifest <path> Manifest path to inspect",
|
||||
" --help Show this help",
|
||||
"",
|
||||
helpHeading("Examples"),
|
||||
helpExample("bunx skvlt doctor"),
|
||||
helpExample("bunx skvlt doctor --manifest ./skvlt.yaml"),
|
||||
helpExample("skvlt doctor"),
|
||||
helpExample("skvlt doctor --manifest ./skvlt.yaml"),
|
||||
helpFooter("https://github.com/xixu-me/skills-vault"),
|
||||
].join("\n")}`;
|
||||
}
|
||||
@@ -110,8 +110,8 @@ function formatDoctorError(message: string): string {
|
||||
) {
|
||||
return commandErrorPage(
|
||||
message,
|
||||
"bunx skvlt doctor [options]",
|
||||
"bunx skvlt doctor --manifest ./skvlt.yaml",
|
||||
"skvlt doctor [options]",
|
||||
"skvlt doctor --manifest ./skvlt.yaml",
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ function printHelp(): string {
|
||||
"Restore skills from skvlt.yaml.",
|
||||
"",
|
||||
helpHeading("Usage"),
|
||||
" bunx skvlt restore [options]",
|
||||
" skvlt restore [options]",
|
||||
"",
|
||||
helpHeading("Options"),
|
||||
" --manifest <path> Path to skvlt.yaml",
|
||||
@@ -98,9 +98,9 @@ function printHelp(): string {
|
||||
` - Global restore verifies ${formatCliPath(defaultGlobalSkillsPath)} against ${formatCliPath(defaultGlobalLockFilePath)}`,
|
||||
"",
|
||||
helpHeading("Examples"),
|
||||
helpExample("bunx skvlt restore --only-source xixu-me/skills"),
|
||||
helpExample("bunx skvlt restore --all"),
|
||||
helpExample("bunx skvlt restore --project-scope --manifest ./skvlt.yaml"),
|
||||
helpExample("skvlt restore --only-source xixu-me/skills"),
|
||||
helpExample("skvlt restore --all"),
|
||||
helpExample("skvlt restore --project-scope --manifest ./skvlt.yaml"),
|
||||
helpFooter("https://github.com/xixu-me/skills-vault"),
|
||||
].join("\n")}`;
|
||||
}
|
||||
@@ -143,8 +143,8 @@ function formatRestoreError(message: string, errorCode: string): string {
|
||||
if (errorCode === "INVALID_ARGUMENT") {
|
||||
return commandErrorPage(
|
||||
message,
|
||||
"bunx skvlt restore [options]",
|
||||
"bunx skvlt restore --all",
|
||||
"skvlt restore [options]",
|
||||
"skvlt restore --all",
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
+27
-4
@@ -1,6 +1,6 @@
|
||||
import { expect, test } from "bun:test";
|
||||
import { existsSync, mkdtempSync, readFileSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
import { join, parse } from "node:path";
|
||||
import { tmpdir } from "node:os";
|
||||
import { runBackup } from "../src/commands/backup";
|
||||
import { parseBackupArgs } from "../src/internal/args/parse-backup-args";
|
||||
@@ -26,9 +26,9 @@ test("renders backup argument errors as a usage page", async () => {
|
||||
expect(plainStderr).toContain("ERROR");
|
||||
expect(plainStderr).toContain("--output requires a path");
|
||||
expect(plainStderr).toContain("Usage:");
|
||||
expect(plainStderr).toContain("bunx skvlt backup [options]");
|
||||
expect(plainStderr).toContain("skvlt backup [options]");
|
||||
expect(plainStderr).toContain("Example:");
|
||||
expect(plainStderr).toContain("bunx skvlt backup --output");
|
||||
expect(plainStderr).toContain("skvlt backup --output");
|
||||
expect(plainStderr.endsWith("\n\n")).toBe(true);
|
||||
});
|
||||
|
||||
@@ -180,6 +180,29 @@ test("formats backup paths for the host platform in user-facing output", async (
|
||||
}
|
||||
});
|
||||
|
||||
test("does not try to recreate the filesystem root for root-level output paths", async () => {
|
||||
const rootPath = parse(process.cwd()).root;
|
||||
const outputPath = join(rootPath, "skvlt.yaml");
|
||||
let writtenManifest: { outputPath: string; manifest: string } | undefined;
|
||||
|
||||
const result = await runBackup(["--output", outputPath], {
|
||||
getInstalledSkillNames: async () => ["alpha"],
|
||||
readLockFile: () => ({
|
||||
skills: {
|
||||
alpha: { source: "owner/skills" },
|
||||
},
|
||||
}),
|
||||
writeManifest: (path, manifest) => {
|
||||
writtenManifest = { outputPath: path, manifest };
|
||||
},
|
||||
});
|
||||
|
||||
expect(result.exitCode).toBe(0);
|
||||
expect(writtenManifest).toBeDefined();
|
||||
expect(writtenManifest?.outputPath).toBe(outputPath);
|
||||
expect(writtenManifest?.manifest).toContain(' "owner/skills":');
|
||||
});
|
||||
|
||||
test("shows help before project-scope validation", async () => {
|
||||
const result = await runBackup(["--help", "--project-scope"]);
|
||||
const plainStdout = result.stdout.replace(/\x1b\[[0-9;]*m/g, "");
|
||||
@@ -189,7 +212,7 @@ test("shows help before project-scope validation", async () => {
|
||||
expect(result.stdout).toContain("\x1b[1mUsage:\x1b[0m");
|
||||
expect(result.stdout).toContain("\x1b[1mExamples:\x1b[0m");
|
||||
expect(result.stdout).toContain("\x1b[38;5;102m$\x1b[0m");
|
||||
expect(result.stdout).not.toContain("bunx skvlt backup --dry-run");
|
||||
expect(result.stdout).not.toContain("skvlt backup --dry-run");
|
||||
expect(plainStdout).toContain(
|
||||
"\n\nExplore the open-source repo at https://github.com/xixu-me/skills-vault",
|
||||
);
|
||||
|
||||
+6
-8
@@ -67,16 +67,14 @@ test("prints top-level help", async () => {
|
||||
"The CLI for backing up and restoring Agent Skills",
|
||||
);
|
||||
expect(result.stdout).toContain("Usage:");
|
||||
expect(result.stdout).toContain("bunx skvlt <command> [options]");
|
||||
expect(result.stdout).toContain("skvlt <command> [options]");
|
||||
expect(result.stdout).toContain("backup");
|
||||
expect(result.stdout).toContain("completion");
|
||||
expect(result.stdout).toContain("doctor");
|
||||
expect(result.stdout).toContain("restore");
|
||||
expect(result.stdout).toContain(
|
||||
"bunx skvlt restore --only-source xixu-me/skills",
|
||||
);
|
||||
expect(result.stdout).not.toContain("bunx skvlt backup --dry-run");
|
||||
expect(result.stdout).not.toContain("bunx skvlt restore --dry-run");
|
||||
expect(result.stdout).toContain("skvlt restore --only-source xixu-me/skills");
|
||||
expect(result.stdout).not.toContain("skvlt backup --dry-run");
|
||||
expect(result.stdout).not.toContain("skvlt restore --dry-run");
|
||||
expect(result.stdout).not.toContain("anthropics/skills");
|
||||
expect(result.stdout).toContain("\x1b[1mUsage:\x1b[0m");
|
||||
expect(result.stdout).toContain("\x1b[1mExamples:\x1b[0m");
|
||||
@@ -128,10 +126,10 @@ test("rejects unknown commands with guidance", async () => {
|
||||
expect(result.stdout).toBe("");
|
||||
expect(plainStderr.startsWith("\n")).toBe(true);
|
||||
expect(plainStderr).toContain("Unknown command: sync");
|
||||
expect(plainStderr).toContain("Run bunx skvlt --help for usage.");
|
||||
expect(plainStderr).toContain("Run skvlt --help for usage.");
|
||||
expect(plainStderr.endsWith("\n\n")).toBe(true);
|
||||
expect(result.stderr).toContain("Unknown command: sync");
|
||||
expect(result.stderr).toContain("\x1b[1mbunx skvlt --help\x1b[0m");
|
||||
expect(result.stderr).toContain("\x1b[1mskvlt --help\x1b[0m");
|
||||
});
|
||||
|
||||
test("returns JSON errors for unknown commands", async () => {
|
||||
|
||||
@@ -12,7 +12,7 @@ test("shows completion help text", async () => {
|
||||
expect(result.exitCode).toBe(0);
|
||||
expect(plainStdout.startsWith("\n")).toBe(true);
|
||||
expect(result.stdout).toContain("Usage:");
|
||||
expect(result.stdout).toContain("bunx skvlt completion");
|
||||
expect(result.stdout).toContain("skvlt completion");
|
||||
expect(result.stdout).toContain("\x1b[1mUsage:\x1b[0m");
|
||||
expect(plainStdout).toContain(
|
||||
"\n\nExplore the open-source repo at https://github.com/xixu-me/skills-vault",
|
||||
@@ -50,9 +50,9 @@ test("rejects unsupported shells with a stable error code", async () => {
|
||||
expect(plainStderr).toContain("ERROR");
|
||||
expect(plainStderr).toContain("Unsupported shell: fish");
|
||||
expect(plainStderr).toContain("Usage:");
|
||||
expect(plainStderr).toContain("bunx skvlt completion <bash|zsh|powershell>");
|
||||
expect(plainStderr).toContain("skvlt completion <bash|zsh|powershell>");
|
||||
expect(plainStderr).toContain("Example:");
|
||||
expect(plainStderr).toContain("bunx skvlt completion bash");
|
||||
expect(plainStderr).toContain("skvlt completion bash");
|
||||
expect(plainStderr.endsWith("\n\n")).toBe(true);
|
||||
expect(result.stderr).toContain("\x1b[");
|
||||
expect(result.stderr).toContain("ERROR");
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ test("shows doctor help text", async () => {
|
||||
expect(result.exitCode).toBe(0);
|
||||
expect(plainStdout.startsWith("\n")).toBe(true);
|
||||
expect(result.stdout).toContain("Usage:");
|
||||
expect(result.stdout).toContain("bunx skvlt doctor");
|
||||
expect(result.stdout).toContain("skvlt doctor");
|
||||
expect(result.stdout).toContain("\x1b[1mUsage:\x1b[0m");
|
||||
expect(plainStdout).toContain(
|
||||
"\n\nExplore the open-source repo at https://github.com/xixu-me/skills-vault",
|
||||
|
||||
@@ -30,8 +30,8 @@ test("shows restore help text", async () => {
|
||||
expect(result.exitCode).toBe(0);
|
||||
expect(plainStdout.startsWith("\n")).toBe(true);
|
||||
expect(result.stdout).toContain("Usage:");
|
||||
expect(result.stdout).toContain("bunx skvlt restore");
|
||||
expect(result.stdout).not.toContain("bunx skvlt restore --dry-run");
|
||||
expect(result.stdout).toContain("skvlt restore");
|
||||
expect(result.stdout).not.toContain("skvlt restore --dry-run");
|
||||
expect(plainStdout).toContain(
|
||||
"\n\nExplore the open-source repo at https://github.com/xixu-me/skills-vault",
|
||||
);
|
||||
@@ -505,8 +505,8 @@ test("renders restore argument errors as a usage page", async () => {
|
||||
expect(plainStderr).toContain("ERROR");
|
||||
expect(plainStderr).toContain("--concurrency requires a value");
|
||||
expect(plainStderr).toContain("Usage:");
|
||||
expect(plainStderr).toContain("bunx skvlt restore [options]");
|
||||
expect(plainStderr).toContain("skvlt restore [options]");
|
||||
expect(plainStderr).toContain("Example:");
|
||||
expect(plainStderr).toContain("bunx skvlt restore --all");
|
||||
expect(plainStderr).toContain("skvlt restore --all");
|
||||
expect(plainStderr.endsWith("\n\n")).toBe(true);
|
||||
});
|
||||
Reference in new issue
Block a user