chore: release 1.0.0
This commit is contained in:
1 parent
b80f31616a
commit
d48830353d
18 files changed
+107
-118
No files matched your search
@@ -28,7 +28,7 @@ concurrency:
|
||||
env:
|
||||
# npm trusted publishing requires Node 22.14.0+ and npm 11.5.1+.
|
||||
NODE_VERSION: "24"
|
||||
PACKAGE_NAME: "@xixu-me/skills-vault"
|
||||
PACKAGE_NAME: "skvlt"
|
||||
NPM_DIST_TAG: ${{ github.event_name == 'workflow_dispatch' && inputs.npm_dist_tag || 'latest' }}
|
||||
|
||||
jobs:
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
**_[汉语](./README.zh.md)_**
|
||||
|
||||
[](https://www.npmjs.com/package/@xixu-me/skills-vault)
|
||||
[](https://www.npmjs.com/package/skvlt)
|
||||
[](https://github.com/xixu-me/skills-vault/actions/workflows/ci.yml)
|
||||
[](https://bun.sh/)
|
||||
[](./LICENSE)
|
||||
@@ -28,32 +28,24 @@ 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
|
||||
skvlt backup
|
||||
bunx skvlt backup
|
||||
```
|
||||
|
||||
Preview what a restore would run:
|
||||
|
||||
```bash
|
||||
skvlt restore --dry-run
|
||||
bunx skvlt restore --dry-run
|
||||
```
|
||||
|
||||
Restore everything recorded in the manifest:
|
||||
|
||||
```bash
|
||||
skvlt restore --all
|
||||
bunx 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.
|
||||
@@ -85,10 +77,10 @@ sources:
|
||||
Snapshot installed skills into `skvlt.yaml`.
|
||||
|
||||
```bash
|
||||
skvlt backup
|
||||
skvlt backup --dry-run
|
||||
skvlt backup --output ./skvlt.yaml
|
||||
skvlt backup --project-scope --lock-file ./skills-lock.json
|
||||
bunx skvlt backup
|
||||
bunx skvlt backup --dry-run
|
||||
bunx skvlt backup --output ./skvlt.yaml
|
||||
bunx 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.
|
||||
@@ -101,10 +93,10 @@ skvlt backup --project-scope --lock-file ./skills-lock.json
|
||||
Install skills from a manifest.
|
||||
|
||||
```bash
|
||||
skvlt restore --all
|
||||
skvlt restore --only-source xixu-me/skills
|
||||
skvlt restore --project-scope
|
||||
skvlt restore --dry-run
|
||||
bunx skvlt restore --all
|
||||
bunx skvlt restore --only-source xixu-me/skills
|
||||
bunx skvlt restore --project-scope
|
||||
bunx 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.
|
||||
@@ -118,8 +110,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
|
||||
skvlt doctor
|
||||
skvlt doctor --manifest ./skvlt.yaml
|
||||
bunx skvlt doctor
|
||||
bunx skvlt doctor --manifest ./skvlt.yaml
|
||||
```
|
||||
|
||||
`doctor` checks:
|
||||
@@ -135,9 +127,9 @@ skvlt doctor --manifest ./skvlt.yaml
|
||||
Print shell completion scripts.
|
||||
|
||||
```bash
|
||||
skvlt completion bash
|
||||
skvlt completion zsh
|
||||
skvlt completion powershell
|
||||
bunx skvlt completion bash
|
||||
bunx skvlt completion zsh
|
||||
bunx skvlt completion powershell
|
||||
```
|
||||
|
||||
## JSON Output
|
||||
@@ -145,8 +137,8 @@ skvlt completion powershell
|
||||
All top-level commands support `--json` for structured output:
|
||||
|
||||
```bash
|
||||
skvlt --json doctor
|
||||
skvlt --json backup --dry-run
|
||||
bunx skvlt --json doctor
|
||||
bunx skvlt --json backup --dry-run
|
||||
```
|
||||
|
||||
Successful responses include `ok`, `command`, and `data`. Failures include `ok`, `command`, and a stable `error.code` plus message.
|
||||
@@ -197,7 +189,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 `skvlt doctor`.
|
||||
- If environment checks fail, start with `bunx 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).
|
||||
|
||||
+20
-28
@@ -2,7 +2,7 @@
|
||||
|
||||
**_[English](./README.md)_**
|
||||
|
||||
[](https://www.npmjs.com/package/@xixu-me/skills-vault)
|
||||
[](https://www.npmjs.com/package/skvlt)
|
||||
[](https://github.com/xixu-me/skills-vault/actions/workflows/ci.yml)
|
||||
[](https://bun.sh/)
|
||||
[](./LICENSE)
|
||||
@@ -28,32 +28,24 @@ Skills Vault 的存在,是为了补上 [vercel-labs/skills#729](https://github
|
||||
- 用 `doctor` 快速检查本地环境
|
||||
- 为 `bash`、`zsh` 和 `powershell` 生成补全脚本
|
||||
|
||||
## 安装
|
||||
|
||||
使用 Bun 全局安装 CLI:
|
||||
|
||||
```bash
|
||||
bun add -g @xixu-me/skills-vault
|
||||
```
|
||||
|
||||
## 快速开始
|
||||
|
||||
备份当前已安装的 skills:
|
||||
|
||||
```bash
|
||||
skvlt backup
|
||||
bunx skvlt backup
|
||||
```
|
||||
|
||||
预览一次 restore 将会执行什么:
|
||||
|
||||
```bash
|
||||
skvlt restore --dry-run
|
||||
bunx skvlt restore --dry-run
|
||||
```
|
||||
|
||||
恢复 manifest 中记录的全部内容:
|
||||
|
||||
```bash
|
||||
skvlt restore --all
|
||||
bunx skvlt restore --all
|
||||
```
|
||||
|
||||
如果你想直接使用一个精选好的 manifest,可以查看 [xixu-me/skvlt](https://github.com/xixu-me/skvlt),这是一个持续维护的 `skvlt.yaml` 集合。
|
||||
@@ -85,10 +77,10 @@ sources:
|
||||
把已安装的 skills 快照到 `skvlt.yaml`。
|
||||
|
||||
```bash
|
||||
skvlt backup
|
||||
skvlt backup --dry-run
|
||||
skvlt backup --output ./skvlt.yaml
|
||||
skvlt backup --project-scope --lock-file ./skills-lock.json
|
||||
bunx skvlt backup
|
||||
bunx skvlt backup --dry-run
|
||||
bunx skvlt backup --output ./skvlt.yaml
|
||||
bunx skvlt backup --project-scope --lock-file ./skills-lock.json
|
||||
```
|
||||
|
||||
`backup` 会先读取已安装的 skill 名称,再结合 lock file 元数据,最终按 source 分组写出 manifest。
|
||||
@@ -101,10 +93,10 @@ skvlt backup --project-scope --lock-file ./skills-lock.json
|
||||
从 manifest 安装 skills。
|
||||
|
||||
```bash
|
||||
skvlt restore --all
|
||||
skvlt restore --only-source xixu-me/skills
|
||||
skvlt restore --project-scope
|
||||
skvlt restore --dry-run
|
||||
bunx skvlt restore --all
|
||||
bunx skvlt restore --only-source xixu-me/skills
|
||||
bunx skvlt restore --project-scope
|
||||
bunx skvlt restore --dry-run
|
||||
```
|
||||
|
||||
默认情况下,`restore` 会遵循 manifest 中记录的 scope。如果希望即使 manifest 来自全局状态,也强制恢复到项目作用域,可以使用 `--project-scope`。
|
||||
@@ -118,8 +110,8 @@ skvlt restore --dry-run
|
||||
检查本地 Skills Vault 环境和全局 skill 状态。
|
||||
|
||||
```bash
|
||||
skvlt doctor
|
||||
skvlt doctor --manifest ./skvlt.yaml
|
||||
bunx skvlt doctor
|
||||
bunx skvlt doctor --manifest ./skvlt.yaml
|
||||
```
|
||||
|
||||
`doctor` 会检查:
|
||||
@@ -135,9 +127,9 @@ skvlt doctor --manifest ./skvlt.yaml
|
||||
输出 shell 补全脚本。
|
||||
|
||||
```bash
|
||||
skvlt completion bash
|
||||
skvlt completion zsh
|
||||
skvlt completion powershell
|
||||
bunx skvlt completion bash
|
||||
bunx skvlt completion zsh
|
||||
bunx skvlt completion powershell
|
||||
```
|
||||
|
||||
## JSON 输出
|
||||
@@ -145,8 +137,8 @@ skvlt completion powershell
|
||||
所有顶层命令都支持 `--json` 结构化输出:
|
||||
|
||||
```bash
|
||||
skvlt --json doctor
|
||||
skvlt --json backup --dry-run
|
||||
bunx skvlt --json doctor
|
||||
bunx skvlt --json backup --dry-run
|
||||
```
|
||||
|
||||
成功时会返回 `ok`、`command` 和 `data`。失败时会返回 `ok`、`command`,以及稳定的 `error.code` 和错误消息。
|
||||
@@ -197,7 +189,7 @@ npm publish --access public
|
||||
## 故障排查
|
||||
|
||||
- 如果 restore 报告全局状态不一致,请检查 `~/.agents/.skill-lock.json` 和 `~/.agents/skills`
|
||||
- 如果环境检查失败,先运行 `skvlt doctor`
|
||||
- 如果环境检查失败,先运行 `bunx skvlt doctor`
|
||||
- 如果打包检查失败,运行 `bun run check`,并检查 `npm pack --dry-run --json` 的输出
|
||||
|
||||
关于贡献、支持和安全策略,请参阅 [`CONTRIBUTING.md`](./CONTRIBUTING.md)、[`SUPPORT.md`](./SUPPORT.md) 和 [`SECURITY.md`](./SECURITY.md)。
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
|
||||
Security fixes are handled on a best-effort basis for:
|
||||
|
||||
- the latest published npm release of `@xixu-me/skills-vault`
|
||||
- the latest published npm release of `skvlt`
|
||||
- the current `main` branch in this repository
|
||||
|
||||
Older versions may receive guidance, but they should not be assumed to receive patches.
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"configVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "@xixu-me/skills-vault",
|
||||
"name": "skvlt",
|
||||
"devDependencies": {
|
||||
"prettier": "^3.8.1",
|
||||
},
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@xixu-me/skills-vault",
|
||||
"version": "1.1.2",
|
||||
"name": "skvlt",
|
||||
"version": "1.0.0",
|
||||
"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"),
|
||||
" skvlt <command> [options]",
|
||||
" bunx 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("skvlt backup --output ./skvlt.yaml"),
|
||||
helpExample("skvlt completion bash"),
|
||||
helpExample("skvlt doctor"),
|
||||
helpExample("skvlt restore --all"),
|
||||
helpExample("skvlt restore --only-source xixu-me/skills"),
|
||||
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"),
|
||||
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("skvlt backup", "Backup installed skills"),
|
||||
landingCommand("skvlt restore", "Restore from skvlt.yaml"),
|
||||
landingCommand("skvlt doctor", "Inspect local setup"),
|
||||
landingCommand("skvlt completion", "Print shell completions"),
|
||||
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"),
|
||||
"",
|
||||
`${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("skvlt --help")} for usage.`,
|
||||
`Unknown command: ${command}\nRun ${bold("bunx skvlt --help")} for usage.`,
|
||||
),
|
||||
errorCode: "UNKNOWN_COMMAND",
|
||||
};
|
||||
|
||||
@@ -48,7 +48,7 @@ function printHelp(): string {
|
||||
"Backup installed skills into skvlt.yaml.",
|
||||
"",
|
||||
helpHeading("Usage"),
|
||||
" skvlt backup [options]",
|
||||
" bunx 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("skvlt backup"),
|
||||
helpExample(`skvlt backup --output ${formatCliPath("./skvlt.yaml")}`),
|
||||
helpExample("bunx skvlt backup"),
|
||||
helpExample(`bunx skvlt backup --output ${formatCliPath("./skvlt.yaml")}`),
|
||||
helpExample(
|
||||
`skvlt backup --project-scope --lock-file ${formatCliPath("./skills-lock.json")}`,
|
||||
`bunx 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,
|
||||
"skvlt backup [options]",
|
||||
`skvlt backup --output ${formatCliPath("./skvlt.yaml")}`,
|
||||
"bunx skvlt backup [options]",
|
||||
`bunx skvlt backup --output ${formatCliPath("./skvlt.yaml")}`,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -21,18 +21,18 @@ export type CompletionRunResult = {
|
||||
|
||||
function printHelp(): string {
|
||||
return `\n${[
|
||||
"Print shell completion scripts for skvlt.",
|
||||
"Print shell completion scripts for bunx skvlt.",
|
||||
"",
|
||||
helpHeading("Usage"),
|
||||
" skvlt completion <bash|zsh|powershell>",
|
||||
" bunx skvlt completion <bash|zsh|powershell>",
|
||||
"",
|
||||
helpHeading("Options"),
|
||||
" --help Show this help",
|
||||
"",
|
||||
helpHeading("Examples"),
|
||||
helpExample("skvlt completion bash"),
|
||||
helpExample("skvlt completion zsh"),
|
||||
helpExample("skvlt completion powershell"),
|
||||
helpExample("bunx skvlt completion bash"),
|
||||
helpExample("bunx skvlt completion zsh"),
|
||||
helpExample("bunx 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,
|
||||
"skvlt completion <bash|zsh|powershell>",
|
||||
"skvlt completion bash",
|
||||
"bunx skvlt completion <bash|zsh|powershell>",
|
||||
"bunx skvlt completion bash",
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -59,15 +59,15 @@ function printHelp(): string {
|
||||
"Inspect the local Skills Vault environment and installation state.",
|
||||
"",
|
||||
helpHeading("Usage"),
|
||||
" skvlt doctor [options]",
|
||||
" bunx skvlt doctor [options]",
|
||||
"",
|
||||
helpHeading("Options"),
|
||||
" --manifest <path> Manifest path to inspect",
|
||||
" --help Show this help",
|
||||
"",
|
||||
helpHeading("Examples"),
|
||||
helpExample("skvlt doctor"),
|
||||
helpExample("skvlt doctor --manifest ./skvlt.yaml"),
|
||||
helpExample("bunx skvlt doctor"),
|
||||
helpExample("bunx 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,
|
||||
"skvlt doctor [options]",
|
||||
"skvlt doctor --manifest ./skvlt.yaml",
|
||||
"bunx skvlt doctor [options]",
|
||||
"bunx skvlt doctor --manifest ./skvlt.yaml",
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ function printHelp(): string {
|
||||
"Restore skills from skvlt.yaml.",
|
||||
"",
|
||||
helpHeading("Usage"),
|
||||
" skvlt restore [options]",
|
||||
" bunx 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("skvlt restore --only-source xixu-me/skills"),
|
||||
helpExample("skvlt restore --all"),
|
||||
helpExample("skvlt restore --project-scope --manifest ./skvlt.yaml"),
|
||||
helpExample("bunx skvlt restore --only-source xixu-me/skills"),
|
||||
helpExample("bunx skvlt restore --all"),
|
||||
helpExample("bunx 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,
|
||||
"skvlt restore [options]",
|
||||
"skvlt restore --all",
|
||||
"bunx skvlt restore [options]",
|
||||
"bunx skvlt restore --all",
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ export function buildManifest(
|
||||
lines.push("");
|
||||
lines.push("sources:");
|
||||
|
||||
for (const source of sortedSources) {
|
||||
for (const [index, source] of sortedSources.entries()) {
|
||||
const skills = [...(groups.get(source) ?? [])].sort((left, right) =>
|
||||
left.localeCompare(right),
|
||||
);
|
||||
@@ -67,7 +67,9 @@ export function buildManifest(
|
||||
for (const skill of skills) {
|
||||
lines.push(` - ${encodeDoubleQuotedYamlScalar(skill)}`);
|
||||
}
|
||||
lines.push("");
|
||||
if (index < sortedSources.length - 1) {
|
||||
lines.push("");
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
+5
-6
@@ -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("skvlt backup [options]");
|
||||
expect(plainStderr).toContain("bunx skvlt backup [options]");
|
||||
expect(plainStderr).toContain("Example:");
|
||||
expect(plainStderr).toContain("skvlt backup --output");
|
||||
expect(plainStderr).toContain("bunx skvlt backup --output");
|
||||
expect(plainStderr.endsWith("\n\n")).toBe(true);
|
||||
});
|
||||
|
||||
@@ -117,7 +117,6 @@ test("prints deterministic manifest YAML during backup dry-run", async () => {
|
||||
" skills:",
|
||||
' - "alpha"',
|
||||
' - "zulu"',
|
||||
"",
|
||||
].join("\n") + "\n",
|
||||
);
|
||||
});
|
||||
@@ -212,7 +211,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("skvlt backup --dry-run");
|
||||
expect(result.stdout).not.toContain("bunx skvlt backup --dry-run");
|
||||
expect(plainStdout).toContain(
|
||||
"\n\nExplore the open-source repo at https://github.com/xixu-me/skills-vault",
|
||||
);
|
||||
@@ -268,6 +267,7 @@ test("builds a grouped manifest with stable source and skill ordering", () => {
|
||||
|
||||
expect(manifest.totalSources).toBe(2);
|
||||
expect(manifest.totalSkills).toBe(3);
|
||||
expect(manifest.yaml.endsWith("\n\n")).toBe(false);
|
||||
expect(manifest.yaml).toBe(
|
||||
[
|
||||
"# Generated by Skills Vault: https://github.com/xixu-me/skills-vault",
|
||||
@@ -286,7 +286,6 @@ test("builds a grouped manifest with stable source and skill ordering", () => {
|
||||
" skills:",
|
||||
' - "alpha"',
|
||||
' - "zulu"',
|
||||
"",
|
||||
].join("\n") + "\n",
|
||||
);
|
||||
});
|
||||
@@ -299,6 +298,7 @@ test("builds double-quoted yaml scalars with escaped special characters", () =>
|
||||
},
|
||||
});
|
||||
|
||||
expect(manifest.yaml.endsWith("\n\n")).toBe(false);
|
||||
expect(manifest.yaml).toBe(
|
||||
[
|
||||
"# Generated by Skills Vault: https://github.com/xixu-me/skills-vault",
|
||||
@@ -316,7 +316,6 @@ test("builds double-quoted yaml scalars with escaped special characters", () =>
|
||||
" count: 1",
|
||||
" skills:",
|
||||
' - "path\\\\skill"',
|
||||
"",
|
||||
].join("\n") + "\n",
|
||||
);
|
||||
});
|
||||
|
||||
+8
-6
@@ -67,14 +67,16 @@ test("prints top-level help", async () => {
|
||||
"The CLI for backing up and restoring Agent Skills",
|
||||
);
|
||||
expect(result.stdout).toContain("Usage:");
|
||||
expect(result.stdout).toContain("skvlt <command> [options]");
|
||||
expect(result.stdout).toContain("bunx 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("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).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).not.toContain("anthropics/skills");
|
||||
expect(result.stdout).toContain("\x1b[1mUsage:\x1b[0m");
|
||||
expect(result.stdout).toContain("\x1b[1mExamples:\x1b[0m");
|
||||
@@ -126,10 +128,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 skvlt --help for usage.");
|
||||
expect(plainStderr).toContain("Run bunx skvlt --help for usage.");
|
||||
expect(plainStderr.endsWith("\n\n")).toBe(true);
|
||||
expect(result.stderr).toContain("Unknown command: sync");
|
||||
expect(result.stderr).toContain("\x1b[1mskvlt --help\x1b[0m");
|
||||
expect(result.stderr).toContain("\x1b[1mbunx skvlt --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("skvlt completion");
|
||||
expect(result.stdout).toContain("bunx 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("skvlt completion <bash|zsh|powershell>");
|
||||
expect(plainStderr).toContain("bunx skvlt completion <bash|zsh|powershell>");
|
||||
expect(plainStderr).toContain("Example:");
|
||||
expect(plainStderr).toContain("skvlt completion bash");
|
||||
expect(plainStderr).toContain("bunx 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("skvlt doctor");
|
||||
expect(result.stdout).toContain("bunx 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",
|
||||
|
||||
@@ -14,10 +14,12 @@ test("uses package scripts that point at the skvlt cli entrypoint", () => {
|
||||
) as {
|
||||
bin?: Record<string, string>;
|
||||
engines?: Record<string, string>;
|
||||
name?: string;
|
||||
publishConfig?: Record<string, string>;
|
||||
scripts?: Record<string, string>;
|
||||
};
|
||||
|
||||
expect(packageJson.name).toBe("skvlt");
|
||||
expect(normalizeBinTarget(packageJson.bin?.skvlt)).toBe("src/cli.ts");
|
||||
expect(packageJson.engines?.bun).toBe(">=1.3.11");
|
||||
expect(packageJson.publishConfig?.access).toBe("public");
|
||||
|
||||
@@ -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("skvlt restore");
|
||||
expect(result.stdout).not.toContain("skvlt restore --dry-run");
|
||||
expect(result.stdout).toContain("bunx skvlt restore");
|
||||
expect(result.stdout).not.toContain("bunx 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("skvlt restore [options]");
|
||||
expect(plainStderr).toContain("bunx skvlt restore [options]");
|
||||
expect(plainStderr).toContain("Example:");
|
||||
expect(plainStderr).toContain("skvlt restore --all");
|
||||
expect(plainStderr).toContain("bunx skvlt restore --all");
|
||||
expect(plainStderr.endsWith("\n\n")).toBe(true);
|
||||
});
|
||||
Reference in new issue
Block a user