@botdocs/cli 0.6.0 → 0.8.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/README.md +80 -8
- package/dist/commands/delete.d.ts +23 -0
- package/dist/commands/delete.js +106 -0
- package/dist/commands/ingest.d.ts +58 -0
- package/dist/commands/ingest.js +352 -27
- package/dist/commands/install.js +11 -0
- package/dist/commands/publish.d.ts +29 -1
- package/dist/commands/publish.js +85 -1
- package/dist/commands/unpublish.d.ts +16 -0
- package/dist/commands/unpublish.js +53 -0
- package/dist/commands/views/ingest-discover-app.d.ts +6 -1
- package/dist/commands/views/ingest-discover-app.js +70 -14
- package/dist/index.js +18 -1
- package/dist/lib/auto-detect.js +19 -0
- package/dist/lib/ingest-discover.d.ts +35 -2
- package/dist/lib/ingest-discover.js +70 -6
- package/dist/lib/ref.d.ts +42 -0
- package/dist/lib/ref.js +60 -0
- package/package.json +1 -1
- package/templates/agents.md +2 -1
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse a BotDoc ref like `@user/slug` or `user/slug` into its parts.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors the inline `parseRef` already in `commands/install.ts` and
|
|
5
|
+
* `commands/edit.ts` — kept here for reuse by `publish`/`unpublish`.
|
|
6
|
+
* The existing duplicates can be folded into this helper in a future
|
|
7
|
+
* refactor without behavior change.
|
|
8
|
+
*
|
|
9
|
+
* Throws on a malformed input so callers can surface a clear message
|
|
10
|
+
* instead of silently dispatching a malformed API request.
|
|
11
|
+
*/
|
|
12
|
+
export declare function parseRef(raw: string): {
|
|
13
|
+
username: string;
|
|
14
|
+
slug: string;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* True when `source` looks like a BotDoc ref (e.g. `@me/my-skill` or
|
|
18
|
+
* `me/my-skill`), false when it looks like a local filesystem path.
|
|
19
|
+
*
|
|
20
|
+
* Used by `botdocs publish <source>` to overload one verb by argument
|
|
21
|
+
* shape — ref-form dispatches to the publish-toggle API, anything else
|
|
22
|
+
* goes through the existing file/dir/zip upload flow.
|
|
23
|
+
*
|
|
24
|
+
* Heuristic (lean toward "is a ref" only when unambiguous):
|
|
25
|
+
*
|
|
26
|
+
* - `@…` → ref. The leading `@` is unambiguous; no filesystem path
|
|
27
|
+
* starts with `@`.
|
|
28
|
+
* - Starts with `./`, `..`, or `/` → path. Absolute and explicit
|
|
29
|
+
* relative paths are never refs.
|
|
30
|
+
* - Contains a `.` (e.g. `foo.md`, `foo.zip`, `dir/file.md`) → path.
|
|
31
|
+
* File extensions are the strongest signal we're looking at a file.
|
|
32
|
+
* - Contains exactly one `/` with non-empty parts on either side → ref.
|
|
33
|
+
* `user/slug` and `org/repo`-style.
|
|
34
|
+
* - Otherwise → path. Bare names like `my-skill` resolve as directory
|
|
35
|
+
* paths under the existing upload flow.
|
|
36
|
+
*
|
|
37
|
+
* False positives (a real directory named `user/slug` with no `.`) will
|
|
38
|
+
* surface as a clean "BotDoc not found" 404 from the API — not silent
|
|
39
|
+
* data loss, just a clearer error than letting the upload flow choke
|
|
40
|
+
* on a non-existent path.
|
|
41
|
+
*/
|
|
42
|
+
export declare function isRefForm(source: string): boolean;
|
package/dist/lib/ref.js
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse a BotDoc ref like `@user/slug` or `user/slug` into its parts.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors the inline `parseRef` already in `commands/install.ts` and
|
|
5
|
+
* `commands/edit.ts` — kept here for reuse by `publish`/`unpublish`.
|
|
6
|
+
* The existing duplicates can be folded into this helper in a future
|
|
7
|
+
* refactor without behavior change.
|
|
8
|
+
*
|
|
9
|
+
* Throws on a malformed input so callers can surface a clear message
|
|
10
|
+
* instead of silently dispatching a malformed API request.
|
|
11
|
+
*/
|
|
12
|
+
export function parseRef(raw) {
|
|
13
|
+
const cleaned = raw.startsWith('@') ? raw.slice(1) : raw;
|
|
14
|
+
const parts = cleaned.split('/');
|
|
15
|
+
if (parts.length !== 2 || !parts[0] || !parts[1]) {
|
|
16
|
+
throw new Error(`Invalid ref: ${raw} (expected @user/slug)`);
|
|
17
|
+
}
|
|
18
|
+
return { username: parts[0], slug: parts[1] };
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* True when `source` looks like a BotDoc ref (e.g. `@me/my-skill` or
|
|
22
|
+
* `me/my-skill`), false when it looks like a local filesystem path.
|
|
23
|
+
*
|
|
24
|
+
* Used by `botdocs publish <source>` to overload one verb by argument
|
|
25
|
+
* shape — ref-form dispatches to the publish-toggle API, anything else
|
|
26
|
+
* goes through the existing file/dir/zip upload flow.
|
|
27
|
+
*
|
|
28
|
+
* Heuristic (lean toward "is a ref" only when unambiguous):
|
|
29
|
+
*
|
|
30
|
+
* - `@…` → ref. The leading `@` is unambiguous; no filesystem path
|
|
31
|
+
* starts with `@`.
|
|
32
|
+
* - Starts with `./`, `..`, or `/` → path. Absolute and explicit
|
|
33
|
+
* relative paths are never refs.
|
|
34
|
+
* - Contains a `.` (e.g. `foo.md`, `foo.zip`, `dir/file.md`) → path.
|
|
35
|
+
* File extensions are the strongest signal we're looking at a file.
|
|
36
|
+
* - Contains exactly one `/` with non-empty parts on either side → ref.
|
|
37
|
+
* `user/slug` and `org/repo`-style.
|
|
38
|
+
* - Otherwise → path. Bare names like `my-skill` resolve as directory
|
|
39
|
+
* paths under the existing upload flow.
|
|
40
|
+
*
|
|
41
|
+
* False positives (a real directory named `user/slug` with no `.`) will
|
|
42
|
+
* surface as a clean "BotDoc not found" 404 from the API — not silent
|
|
43
|
+
* data loss, just a clearer error than letting the upload flow choke
|
|
44
|
+
* on a non-existent path.
|
|
45
|
+
*/
|
|
46
|
+
export function isRefForm(source) {
|
|
47
|
+
if (!source)
|
|
48
|
+
return false;
|
|
49
|
+
if (source.startsWith('@'))
|
|
50
|
+
return true;
|
|
51
|
+
if (source.startsWith('./') || source.startsWith('../') || source.startsWith('/')) {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
if (source.includes('.'))
|
|
55
|
+
return false;
|
|
56
|
+
const parts = source.split('/');
|
|
57
|
+
if (parts.length !== 2)
|
|
58
|
+
return false;
|
|
59
|
+
return Boolean(parts[0] && parts[1]);
|
|
60
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@botdocs/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "CLI for BotDocs — author, publish, install, and sync agent skills across Claude, Claude Code, Cursor, Codex, ChatGPT, Windsurf, Copilot, Gemini, Antigravity, and OpenCode.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"botdocs",
|
package/templates/agents.md
CHANGED
|
@@ -119,7 +119,8 @@ the user and recommend they set one.
|
|
|
119
119
|
| `init [name]` | Scaffold a new skill directory. |
|
|
120
120
|
| `validate <source>` | Pre-publish structural check. |
|
|
121
121
|
| `search <query>` | Search the registry. |
|
|
122
|
-
| `publish <source>` | Publish from a file, directory, or zip. |
|
|
122
|
+
| `publish <source>` | Publish from a file, directory, or zip — or pass `@user/slug` to mark an existing draft live. |
|
|
123
|
+
| `unpublish <ref>` | Hide a published BotDoc from `/explore` (sets the `draft` flag back; prompts unless `--yes`). |
|
|
123
124
|
| `install <ref>` | Install a skill or bundle (auto-detects destinations). |
|
|
124
125
|
| `sync [ref]` | Apply available updates to installed skills. |
|
|
125
126
|
| `uninstall <ref>` | Remove an installed skill or bundle. |
|