@yoyo-bot/cli 0.1.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.
Files changed (58) hide show
  1. package/README.md +160 -0
  2. package/dist/commands/auth.d.ts +5 -0
  3. package/dist/commands/auth.d.ts.map +1 -0
  4. package/dist/commands/auth.js +26 -0
  5. package/dist/commands/auth.js.map +1 -0
  6. package/dist/commands/bind.d.ts +9 -0
  7. package/dist/commands/bind.d.ts.map +1 -0
  8. package/dist/commands/bind.js +132 -0
  9. package/dist/commands/bind.js.map +1 -0
  10. package/dist/commands/init.d.ts +5 -0
  11. package/dist/commands/init.d.ts.map +1 -0
  12. package/dist/commands/init.js +57 -0
  13. package/dist/commands/init.js.map +1 -0
  14. package/dist/commands/list.d.ts +6 -0
  15. package/dist/commands/list.d.ts.map +1 -0
  16. package/dist/commands/list.js +38 -0
  17. package/dist/commands/list.js.map +1 -0
  18. package/dist/commands/publish.d.ts +8 -0
  19. package/dist/commands/publish.d.ts.map +1 -0
  20. package/dist/commands/publish.js +96 -0
  21. package/dist/commands/publish.js.map +1 -0
  22. package/dist/commands/search.d.ts +5 -0
  23. package/dist/commands/search.d.ts.map +1 -0
  24. package/dist/commands/search.js +36 -0
  25. package/dist/commands/search.js.map +1 -0
  26. package/dist/commands/unbind.d.ts +7 -0
  27. package/dist/commands/unbind.d.ts.map +1 -0
  28. package/dist/commands/unbind.js +26 -0
  29. package/dist/commands/unbind.js.map +1 -0
  30. package/dist/commands/whoami.d.ts +4 -0
  31. package/dist/commands/whoami.d.ts.map +1 -0
  32. package/dist/commands/whoami.js +34 -0
  33. package/dist/commands/whoami.js.map +1 -0
  34. package/dist/index.d.ts +3 -0
  35. package/dist/index.d.ts.map +1 -0
  36. package/dist/index.js +67 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/lib/api.d.ts +60 -0
  39. package/dist/lib/api.d.ts.map +1 -0
  40. package/dist/lib/api.js +54 -0
  41. package/dist/lib/api.js.map +1 -0
  42. package/dist/lib/config.d.ts +11 -0
  43. package/dist/lib/config.d.ts.map +1 -0
  44. package/dist/lib/config.js +38 -0
  45. package/dist/lib/config.js.map +1 -0
  46. package/package.json +26 -0
  47. package/src/commands/auth.ts +30 -0
  48. package/src/commands/bind.ts +147 -0
  49. package/src/commands/init.ts +69 -0
  50. package/src/commands/list.ts +43 -0
  51. package/src/commands/publish.ts +117 -0
  52. package/src/commands/search.ts +40 -0
  53. package/src/commands/unbind.ts +34 -0
  54. package/src/commands/whoami.ts +34 -0
  55. package/src/index.ts +76 -0
  56. package/src/lib/api.ts +118 -0
  57. package/src/lib/config.ts +45 -0
  58. package/tsconfig.json +10 -0
package/README.md ADDED
@@ -0,0 +1,160 @@
1
+ # @yoyo-bot/cli
2
+
3
+ The command-line tool for [YoYo](https://yoyo.bot) — the universal binder registry for AI agents.
4
+
5
+ Search, install, fork, and publish binders from your terminal.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ npm install -g @yoyo-bot/cli
11
+ ```
12
+
13
+ ## Quick Start
14
+
15
+ ```bash
16
+ # Authenticate
17
+ yoyo auth
18
+
19
+ # Search for binders
20
+ yoyo search "knowledge base"
21
+
22
+ # Install a binder
23
+ yoyo bind personal-knowledge-wiki
24
+
25
+ # List your installed binders
26
+ yoyo list
27
+
28
+ # Create a new binder
29
+ yoyo init my-binder
30
+
31
+ # Publish your binder
32
+ yoyo publish
33
+ ```
34
+
35
+ ## Commands
36
+
37
+ ### `yoyo auth`
38
+
39
+ Authenticate with your YoYo API key. Get one at [yoyo.bot/settings](https://yoyo.bot/settings).
40
+
41
+ ```bash
42
+ yoyo auth
43
+ # Prompts for your API key and saves to ~/.yoyo/config.json
44
+
45
+ yoyo auth --key yoyo_your_key_here
46
+ # Set key directly
47
+ ```
48
+
49
+ ### `yoyo search <query>`
50
+
51
+ Search the binder registry.
52
+
53
+ ```bash
54
+ yoyo search "debugging"
55
+ yoyo search "rag" --category research
56
+ yoyo search --featured
57
+ ```
58
+
59
+ ### `yoyo bind <slug>`
60
+
61
+ Install a binder. Downloads the full recipe — instructions, code, config, and examples.
62
+
63
+ ```bash
64
+ yoyo bind personal-knowledge-wiki
65
+ yoyo bind knowledge-base-rag --org my-team
66
+ ```
67
+
68
+ ### `yoyo unbind <slug>`
69
+
70
+ Remove an installed binder.
71
+
72
+ ```bash
73
+ yoyo unbind personal-knowledge-wiki
74
+ ```
75
+
76
+ ### `yoyo list`
77
+
78
+ List your installed and published binders.
79
+
80
+ ```bash
81
+ yoyo list
82
+ yoyo list --org my-team
83
+ ```
84
+
85
+ ### `yoyo init <name>`
86
+
87
+ Scaffold a new binder with the standard directory structure.
88
+
89
+ ```bash
90
+ yoyo init my-binder
91
+ # Creates:
92
+ # my-binder/
93
+ # ├── binder.md
94
+ # ├── manifest.json
95
+ # ├── skills/
96
+ # ├── src/
97
+ # ├── config/.env.example
98
+ # └── examples/
99
+ ```
100
+
101
+ ### `yoyo publish`
102
+
103
+ Publish a binder to the YoYo registry.
104
+
105
+ ```bash
106
+ cd my-binder
107
+ yoyo publish
108
+ ```
109
+
110
+ ### `yoyo whoami`
111
+
112
+ Check your authentication status.
113
+
114
+ ```bash
115
+ yoyo whoami
116
+ # → Authenticated as: david (yoyo_38LG...pzf)
117
+ ```
118
+
119
+ ## What's a Binder?
120
+
121
+ A binder is a **complete recipe** for an AI agent — not just a prompt or a skill file, but the full package:
122
+
123
+ | Component | Purpose |
124
+ |-----------|---------|
125
+ | `binder.md` | The operating manual — architecture, workflows, conventions |
126
+ | `src/` | Runnable source code and scripts |
127
+ | `skills/` | Heuristic instruction files |
128
+ | `config/` | Parameters, env templates, schemas |
129
+ | `infrastructure/` | Dockerfiles, DAGs, Terraform, DB migrations |
130
+ | `examples/` | Worked demonstrations with expected output |
131
+
132
+ The agent is the chef. The binder is the recipe.
133
+
134
+ ## Configuration
135
+
136
+ Config is stored in `~/.yoyo/config.json`:
137
+
138
+ ```json
139
+ {
140
+ "apiKey": "yoyo_your_key_here",
141
+ "apiUrl": "https://api.yoyo.bot/v1"
142
+ }
143
+ ```
144
+
145
+ ## Also Available
146
+
147
+ - **MCP Server:** `npx @yoyo-bot/mcp` — native agent integration (14 tools)
148
+ - **Copy Prompt:** paste a one-liner into any agent to install a binder
149
+ - **Web:** [yoyo.bot/binders](https://yoyo.bot/binders) — browse and fork
150
+
151
+ ## Links
152
+
153
+ - **Website:** [yoyo.bot](https://yoyo.bot)
154
+ - **Binders:** [yoyo.bot/binders](https://yoyo.bot/binders)
155
+ - **MCP Server:** [@yoyo-bot/mcp](https://www.npmjs.com/package/@yoyo-bot/mcp)
156
+ - **GitHub:** [github.com/CG-Labs/YoYo](https://github.com/CG-Labs/YoYo)
157
+
158
+ ## License
159
+
160
+ MIT
@@ -0,0 +1,5 @@
1
+ export declare function authCommand(opts: {
2
+ key?: string;
3
+ url?: string;
4
+ }): Promise<void>;
5
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"AAKA,wBAAsB,WAAW,CAAC,IAAI,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAwBrF"}
@@ -0,0 +1,26 @@
1
+ import { createInterface } from "node:readline";
2
+ import pc from "picocolors";
3
+ import { loadConfig, saveConfig } from "../lib/config.js";
4
+ export async function authCommand(opts) {
5
+ let apiKey = opts.key;
6
+ if (!apiKey) {
7
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
8
+ apiKey = await new Promise((resolve) => {
9
+ rl.question(pc.dim("Enter your Yoyo API key: "), (ans) => {
10
+ rl.close();
11
+ resolve(ans.trim());
12
+ });
13
+ });
14
+ }
15
+ if (!apiKey) {
16
+ console.error(pc.red("No API key provided."));
17
+ process.exit(1);
18
+ }
19
+ const cfg = await loadConfig();
20
+ cfg.apiKey = apiKey;
21
+ if (opts.url)
22
+ cfg.apiUrl = opts.url;
23
+ await saveConfig(cfg);
24
+ console.log(pc.green("API key saved to ~/.yoyo/config.json"));
25
+ }
26
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,EAAE,UAAU,EAAE,UAAU,EAAa,MAAM,kBAAkB,CAAC;AAGrE,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,IAAoC;IACpE,IAAI,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC;IAEtB,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,EAAE,GAAG,eAAe,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;QAC7E,MAAM,GAAG,MAAM,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,EAAE;YAC7C,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,GAAG,CAAC,2BAA2B,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE;gBACvD,EAAE,CAAC,KAAK,EAAE,CAAC;gBACX,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;YACtB,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;IAED,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC,CAAC;QAC9C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,GAAG,GAAG,MAAM,UAAU,EAAE,CAAC;IAC/B,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC;IACpB,IAAI,IAAI,CAAC,GAAG;QAAE,GAAG,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC;IACpC,MAAM,UAAU,CAAC,GAAG,CAAC,CAAC;IAEtB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAC,CAAC;AAChE,CAAC"}
@@ -0,0 +1,9 @@
1
+ interface BindOptions {
2
+ version?: string;
3
+ dir?: string;
4
+ json?: boolean;
5
+ dryRun?: boolean;
6
+ }
7
+ export declare function bindCommand(ref: string, opts: BindOptions): Promise<void>;
8
+ export {};
9
+ //# sourceMappingURL=bind.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bind.d.ts","sourceRoot":"","sources":["../../src/commands/bind.ts"],"names":[],"mappings":"AAQA,UAAU,WAAW;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAoBD,wBAAsB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAiH/E"}
@@ -0,0 +1,132 @@
1
+ import { writeFile, mkdir } from "node:fs/promises";
2
+ import { join, resolve } from "node:path";
3
+ import { homedir } from "node:os";
4
+ import { createHash } from "node:crypto";
5
+ import { unlink } from "node:fs/promises";
6
+ import pc from "picocolors";
7
+ import { api, ApiError } from "../lib/api.js";
8
+ function defaultBindRoot() {
9
+ return join(homedir(), ".yoyo", "binders");
10
+ }
11
+ function parseRef(ref) {
12
+ const parts = ref.split("/");
13
+ if (parts.length !== 2 || !parts[0] || !parts[1]) {
14
+ throw new Error(`Invalid binder ref "${ref}". Expected <owner>/<slug>`);
15
+ }
16
+ return { owner: parts[0], slug: parts[1] };
17
+ }
18
+ function formatBytes(n) {
19
+ if (n < 1024)
20
+ return `${n} B`;
21
+ if (n < 1024 * 1024)
22
+ return `${(n / 1024).toFixed(1)} KB`;
23
+ return `${(n / (1024 * 1024)).toFixed(1)} MB`;
24
+ }
25
+ export async function bindCommand(ref, opts) {
26
+ let owner, slug;
27
+ try {
28
+ ({ owner, slug } = parseRef(ref));
29
+ }
30
+ catch (err) {
31
+ console.error(pc.red(String(err)));
32
+ process.exit(1);
33
+ }
34
+ if (!opts.json)
35
+ process.stdout.write(pc.dim(`Fetching ${ref}…\n`));
36
+ let binder;
37
+ try {
38
+ binder = await api.getBinder(owner, slug);
39
+ }
40
+ catch (err) {
41
+ if (err instanceof ApiError && err.status === 404) {
42
+ console.error(pc.red(`Binder not found: ${ref}`));
43
+ }
44
+ else {
45
+ console.error(pc.red(`API error: ${String(err)}`));
46
+ }
47
+ process.exit(1);
48
+ }
49
+ const spine = binder.latestVersion;
50
+ if (!spine) {
51
+ console.error(pc.red(`Binder ${ref} has no published versions.`));
52
+ process.exit(1);
53
+ }
54
+ const bindDir = join(opts.dir ? resolve(opts.dir) : defaultBindRoot(), owner, slug);
55
+ if (opts.json) {
56
+ console.log(JSON.stringify({ ref, bindDir, dryRun: opts.dryRun ?? false, binder }, null, 2));
57
+ return;
58
+ }
59
+ const badge = binder.verification === "official"
60
+ ? pc.yellow(" ✦ Official")
61
+ : binder.verification === "verified"
62
+ ? pc.green(" ✓ Verified")
63
+ : "";
64
+ console.log(`\n${pc.bold(binder.displayName ?? ref)}${badge} ${pc.dim(`v${spine.version}`)}`);
65
+ if (binder.description)
66
+ console.log(pc.dim(binder.description.slice(0, 80)));
67
+ console.log(pc.dim("─".repeat(50)));
68
+ console.log(` ${pc.dim("Bind to")} ${pc.dim(bindDir)}`);
69
+ console.log();
70
+ if (opts.dryRun) {
71
+ console.log(pc.yellow("Dry run — nothing written."));
72
+ return;
73
+ }
74
+ await mkdir(bindDir, { recursive: true });
75
+ // Write manifest
76
+ const manifest = {
77
+ name: slug,
78
+ owner,
79
+ fullName: `${owner}/${slug}`,
80
+ version: spine.version,
81
+ description: binder.description,
82
+ tab: binder.tab,
83
+ tags: binder.tags ?? [],
84
+ boundAt: new Date().toISOString(),
85
+ tarballUrl: spine.tarballUrl,
86
+ tarballSha256: spine.tarballSha256,
87
+ };
88
+ await writeFile(join(bindDir, "binder.json"), JSON.stringify(manifest, null, 2) + "\n", "utf8");
89
+ console.log(` ${pc.green("✓")} binder.json`);
90
+ // Download tarball with SHA256 verification
91
+ if (spine.tarballUrl) {
92
+ const tarPath = join(bindDir, `${slug}-${spine.version}.tar.gz`);
93
+ process.stdout.write(` ${pc.dim("↓ tarball…")}`);
94
+ try {
95
+ const res = await fetch(spine.tarballUrl);
96
+ if (res.ok && res.body) {
97
+ const reader = res.body.getReader();
98
+ const chunks = [];
99
+ let total = 0;
100
+ for (;;) {
101
+ const { done, value } = await reader.read();
102
+ if (done)
103
+ break;
104
+ chunks.push(value);
105
+ total += value.byteLength;
106
+ }
107
+ const buf = Buffer.concat(chunks, total);
108
+ if (spine.tarballSha256) {
109
+ const actual = createHash("sha256").update(buf).digest("hex");
110
+ if (actual !== spine.tarballSha256) {
111
+ process.stdout.write(`\r ${pc.red("✗")} tarball SHA256 mismatch — aborting\n`);
112
+ console.error(pc.dim(` expected: ${spine.tarballSha256}\n got: ${actual}`));
113
+ await unlink(tarPath).catch(() => { });
114
+ process.exit(1);
115
+ }
116
+ }
117
+ await writeFile(tarPath, buf);
118
+ process.stdout.write(`\r ${pc.green("✓")} tarball (${pc.dim(formatBytes(total))})\n`);
119
+ }
120
+ else {
121
+ process.stdout.write(`\r ${pc.dim("~ tarball skipped")}\n`);
122
+ }
123
+ }
124
+ catch {
125
+ process.stdout.write(`\r ${pc.dim("~ tarball unavailable")}\n`);
126
+ }
127
+ }
128
+ console.log();
129
+ console.log(pc.green(`Bound ${ref}@${spine.version}`));
130
+ console.log(pc.dim(`Location: ${bindDir}`));
131
+ }
132
+ //# sourceMappingURL=bind.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bind.js","sourceRoot":"","sources":["../../src/commands/bind.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export declare function initCommand(opts: {
2
+ dir?: string;
3
+ yes?: boolean;
4
+ }): Promise<void>;
5
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAUA,wBAAsB,WAAW,CAAC,IAAI,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA0DtF"}
@@ -0,0 +1,57 @@
1
+ import { writeFile, mkdir } from "node:fs/promises";
2
+ import { join, resolve } from "node:path";
3
+ import { existsSync } from "node:fs";
4
+ import { createInterface } from "node:readline";
5
+ import pc from "picocolors";
6
+ async function prompt(rl, question) {
7
+ return new Promise((res) => rl.question(question, (a) => res(a.trim())));
8
+ }
9
+ export async function initCommand(opts) {
10
+ const cwd = opts.dir ? resolve(opts.dir) : process.cwd();
11
+ const manifestPath = join(cwd, "binder.json");
12
+ if (existsSync(manifestPath) && !opts.yes) {
13
+ console.error(pc.yellow("binder.json already exists. Use --yes to overwrite."));
14
+ process.exit(1);
15
+ }
16
+ let slug = "", displayName = "", description = "";
17
+ if (opts.yes) {
18
+ const dirName = cwd.split("/").pop() ?? "my-binder";
19
+ slug = dirName.toLowerCase().replace(/[^a-z0-9-]/g, "-");
20
+ displayName = dirName;
21
+ }
22
+ else {
23
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
24
+ slug = await prompt(rl, pc.dim("Binder slug (e.g. my-tools): "));
25
+ displayName = await prompt(rl, pc.dim("Display name: "));
26
+ description = await prompt(rl, pc.dim("Description: "));
27
+ rl.close();
28
+ }
29
+ if (!slug) {
30
+ console.error(pc.red("Slug is required."));
31
+ process.exit(1);
32
+ }
33
+ const manifest = {
34
+ slug,
35
+ displayName: displayName || slug,
36
+ description: description || "",
37
+ version: "0.1.0",
38
+ tab: "tools",
39
+ tags: [],
40
+ platforms: [],
41
+ license: "MIT",
42
+ dependencies: {},
43
+ };
44
+ await mkdir(cwd, { recursive: true });
45
+ await writeFile(manifestPath, JSON.stringify(manifest, null, 2) + "\n", "utf8");
46
+ // Scaffold a basic page.md if it doesn't exist
47
+ const pagePath = join(cwd, "page.md");
48
+ if (!existsSync(pagePath)) {
49
+ await writeFile(pagePath, `# ${manifest.displayName}\n\n${manifest.description || "Describe what this binder provides to AI agents."}\n`, "utf8");
50
+ }
51
+ console.log(pc.green(`\nInitialised binder in ${cwd}`));
52
+ console.log(` ${pc.dim("✓")} binder.json`);
53
+ console.log(` ${pc.dim("✓")} page.md`);
54
+ console.log();
55
+ console.log(pc.dim("Next: yoyo publish"));
56
+ }
57
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export declare function listCommand(opts: {
2
+ owner?: string;
3
+ page?: string;
4
+ json?: boolean;
5
+ }): Promise<void>;
6
+ //# sourceMappingURL=list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"AAGA,wBAAsB,WAAW,CAAC,IAAI,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAuCxG"}
@@ -0,0 +1,38 @@
1
+ import pc from "picocolors";
2
+ import { api } from "../lib/api.js";
3
+ export async function listCommand(opts) {
4
+ const page = Number(opts.page ?? 1);
5
+ const pageSize = 20;
6
+ let result;
7
+ try {
8
+ result = await api.listBinders(opts.owner, page, pageSize);
9
+ }
10
+ catch (err) {
11
+ console.error(pc.red(`Failed to list binders: ${String(err)}`));
12
+ process.exit(1);
13
+ }
14
+ if (opts.json) {
15
+ console.log(JSON.stringify(result, null, 2));
16
+ return;
17
+ }
18
+ if (result.items.length === 0) {
19
+ console.log(pc.dim("No binders found."));
20
+ return;
21
+ }
22
+ const title = opts.owner ? `Binders by ${opts.owner}` : "All binders";
23
+ console.log(pc.bold(`\n${title}`) + pc.dim(` (${result.total} total)\n`));
24
+ for (const b of result.items) {
25
+ const name = pc.cyan(`${b.owner}/${b.slug}`);
26
+ const ver = b.version ? pc.dim(`v${b.version}`) : "";
27
+ const badge = b.verification === "official" ? pc.yellow(" ✦") : b.verification === "verified" ? pc.green(" ✓") : "";
28
+ const dl = b.downloads != null ? pc.dim(` · ${b.downloads.toLocaleString()} downloads`) : "";
29
+ console.log(` ${name}${badge} ${ver}${dl}`);
30
+ if (b.description)
31
+ console.log(` ${pc.dim(b.description.slice(0, 80))}`);
32
+ console.log();
33
+ }
34
+ if (result.total > page * pageSize) {
35
+ console.log(pc.dim(`Page ${page} of ${Math.ceil(result.total / pageSize)} — use --page to navigate`));
36
+ }
37
+ }
38
+ //# sourceMappingURL=list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.js","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ interface PublishOptions {
2
+ dir?: string;
3
+ dryRun?: boolean;
4
+ json?: boolean;
5
+ }
6
+ export declare function publishCommand(opts: PublishOptions): Promise<void>;
7
+ export {};
8
+ //# sourceMappingURL=publish.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"publish.d.ts","sourceRoot":"","sources":["../../src/commands/publish.ts"],"names":[],"mappings":"AAOA,UAAU,cAAc;IACtB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAcD,wBAAsB,cAAc,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CA2FxE"}
@@ -0,0 +1,96 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { join, resolve } from "node:path";
3
+ import { existsSync } from "node:fs";
4
+ import pc from "picocolors";
5
+ import { api, ApiError } from "../lib/api.js";
6
+ import { getApiKey } from "../lib/config.js";
7
+ export async function publishCommand(opts) {
8
+ const cwd = opts.dir ? resolve(opts.dir) : process.cwd();
9
+ const manifestPath = join(cwd, "binder.json");
10
+ if (!existsSync(manifestPath)) {
11
+ console.error(pc.red("No binder.json found. Run: yoyo init"));
12
+ process.exit(1);
13
+ }
14
+ let manifest;
15
+ try {
16
+ const raw = await readFile(manifestPath, "utf8");
17
+ manifest = JSON.parse(raw);
18
+ }
19
+ catch {
20
+ console.error(pc.red("Failed to parse binder.json."));
21
+ process.exit(1);
22
+ }
23
+ if (!manifest.slug) {
24
+ console.error(pc.red("binder.json missing required field: slug"));
25
+ process.exit(1);
26
+ }
27
+ if (!manifest.version) {
28
+ console.error(pc.red("binder.json missing required field: version"));
29
+ process.exit(1);
30
+ }
31
+ const key = await getApiKey();
32
+ if (!key) {
33
+ console.error(pc.red("Not authenticated. Run: yoyo auth"));
34
+ process.exit(1);
35
+ }
36
+ // Read page.md as readme if present
37
+ let readme;
38
+ const pagePath = join(cwd, "page.md");
39
+ if (existsSync(pagePath)) {
40
+ readme = await readFile(pagePath, "utf8");
41
+ }
42
+ else {
43
+ const readmePath = join(cwd, "README.md");
44
+ if (existsSync(readmePath))
45
+ readme = await readFile(readmePath, "utf8");
46
+ }
47
+ if (opts.dryRun || opts.json) {
48
+ const payload = {
49
+ slug: manifest.slug,
50
+ displayName: manifest.displayName,
51
+ description: manifest.description,
52
+ version: manifest.version,
53
+ readme,
54
+ tags: manifest.tags ?? [],
55
+ tab: manifest.tab,
56
+ license: manifest.license,
57
+ platforms: manifest.platforms ?? [],
58
+ dependencies: manifest.dependencies ?? {},
59
+ };
60
+ if (opts.json) {
61
+ console.log(JSON.stringify({ dryRun: opts.dryRun ?? false, payload }, null, 2));
62
+ }
63
+ else {
64
+ console.log(pc.yellow("Dry run — would publish:"));
65
+ console.log(` ${manifest.slug}@${manifest.version}`);
66
+ }
67
+ return;
68
+ }
69
+ console.log(pc.dim(`Publishing ${manifest.slug}@${manifest.version}…`));
70
+ try {
71
+ const result = await api.publish({
72
+ slug: manifest.slug,
73
+ displayName: manifest.displayName,
74
+ description: manifest.description,
75
+ version: manifest.version,
76
+ readme,
77
+ tags: manifest.tags ?? [],
78
+ tab: manifest.tab,
79
+ license: manifest.license,
80
+ platforms: manifest.platforms ?? [],
81
+ dependencies: manifest.dependencies ?? {},
82
+ });
83
+ console.log(pc.green(`\nPublished ${result.slug}@${result.version}`));
84
+ console.log(pc.dim(`ID: ${result.id}`));
85
+ }
86
+ catch (err) {
87
+ if (err instanceof ApiError) {
88
+ console.error(pc.red(`Publish failed (${err.status}): ${err.message}`));
89
+ }
90
+ else {
91
+ console.error(pc.red(`Publish failed: ${String(err)}`));
92
+ }
93
+ process.exit(1);
94
+ }
95
+ }
96
+ //# sourceMappingURL=publish.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"publish.js","sourceRoot":"","sources":["../../src/commands/publish.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export declare function searchCommand(query: string, opts: {
2
+ limit?: string;
3
+ json?: boolean;
4
+ }): Promise<void>;
5
+ //# sourceMappingURL=search.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../src/commands/search.ts"],"names":[],"mappings":"AAGA,wBAAsB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAoC1G"}
@@ -0,0 +1,36 @@
1
+ import pc from "picocolors";
2
+ import { api } from "../lib/api.js";
3
+ export async function searchCommand(query, opts) {
4
+ const pageSize = Math.min(Number(opts.limit ?? 10), 50);
5
+ let result;
6
+ try {
7
+ result = await api.search(query, 1, pageSize);
8
+ }
9
+ catch (err) {
10
+ console.error(pc.red("Search failed: " + String(err)));
11
+ process.exit(1);
12
+ }
13
+ if (opts.json) {
14
+ console.log(JSON.stringify(result, null, 2));
15
+ return;
16
+ }
17
+ if (result.items.length === 0) {
18
+ console.log(pc.dim(`No results for "${query}"`));
19
+ return;
20
+ }
21
+ console.log(pc.bold(`\nSearch results for "${query}"`) + pc.dim(` (${result.total} total)\n`));
22
+ for (const b of result.items) {
23
+ const name = pc.cyan(`${b.owner}/${b.slug}`);
24
+ const ver = b.version ? pc.dim(`v${b.version}`) : "";
25
+ const badge = b.verification === "official" ? pc.yellow(" ✦") : b.verification === "verified" ? pc.green(" ✓") : "";
26
+ console.log(` ${name}${badge} ${ver}`);
27
+ if (b.description) {
28
+ console.log(` ${pc.dim(b.description.slice(0, 80))}`);
29
+ }
30
+ if (b.tags?.length) {
31
+ console.log(` ${pc.dim(b.tags.slice(0, 5).join(", "))}`);
32
+ }
33
+ console.log();
34
+ }
35
+ }
36
+ //# sourceMappingURL=search.js.map