clawdhub 0.0.1

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 (79) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +57 -0
  3. package/bin/clawdhub.js +2 -0
  4. package/dist/browserAuth.d.ts +20 -0
  5. package/dist/browserAuth.js +156 -0
  6. package/dist/browserAuth.js.map +1 -0
  7. package/dist/browserAuth.test.d.ts +1 -0
  8. package/dist/browserAuth.test.js +39 -0
  9. package/dist/browserAuth.test.js.map +1 -0
  10. package/dist/cli/buildInfo.d.ts +3 -0
  11. package/dist/cli/buildInfo.js +103 -0
  12. package/dist/cli/buildInfo.js.map +1 -0
  13. package/dist/cli/commands/auth.d.ts +9 -0
  14. package/dist/cli/commands/auth.js +75 -0
  15. package/dist/cli/commands/auth.js.map +1 -0
  16. package/dist/cli/commands/publish.d.ts +8 -0
  17. package/dist/cli/commands/publish.js +91 -0
  18. package/dist/cli/commands/publish.js.map +1 -0
  19. package/dist/cli/commands/publish.test.d.ts +1 -0
  20. package/dist/cli/commands/publish.test.js +120 -0
  21. package/dist/cli/commands/publish.test.js.map +1 -0
  22. package/dist/cli/commands/skills.d.ts +9 -0
  23. package/dist/cli/commands/skills.js +195 -0
  24. package/dist/cli/commands/skills.js.map +1 -0
  25. package/dist/cli/commands/sync.d.ts +11 -0
  26. package/dist/cli/commands/sync.js +273 -0
  27. package/dist/cli/commands/sync.js.map +1 -0
  28. package/dist/cli/commands/sync.test.d.ts +1 -0
  29. package/dist/cli/commands/sync.test.js +106 -0
  30. package/dist/cli/commands/sync.test.js.map +1 -0
  31. package/dist/cli/helpStyle.d.ts +13 -0
  32. package/dist/cli/helpStyle.js +38 -0
  33. package/dist/cli/helpStyle.js.map +1 -0
  34. package/dist/cli/registry.d.ts +7 -0
  35. package/dist/cli/registry.js +27 -0
  36. package/dist/cli/registry.js.map +1 -0
  37. package/dist/cli/scanSkills.d.ts +7 -0
  38. package/dist/cli/scanSkills.js +75 -0
  39. package/dist/cli/scanSkills.js.map +1 -0
  40. package/dist/cli/scanSkills.test.d.ts +1 -0
  41. package/dist/cli/scanSkills.test.js +47 -0
  42. package/dist/cli/scanSkills.test.js.map +1 -0
  43. package/dist/cli/slug.d.ts +2 -0
  44. package/dist/cli/slug.js +16 -0
  45. package/dist/cli/slug.js.map +1 -0
  46. package/dist/cli/types.d.ts +14 -0
  47. package/dist/cli/types.js +2 -0
  48. package/dist/cli/types.js.map +1 -0
  49. package/dist/cli/ui.d.ts +7 -0
  50. package/dist/cli/ui.js +72 -0
  51. package/dist/cli/ui.js.map +1 -0
  52. package/dist/cli.d.ts +2 -0
  53. package/dist/cli.js +179 -0
  54. package/dist/cli.js.map +1 -0
  55. package/dist/config.d.ts +4 -0
  56. package/dist/config.js +38 -0
  57. package/dist/config.js.map +1 -0
  58. package/dist/discovery.d.ts +5 -0
  59. package/dist/discovery.js +21 -0
  60. package/dist/discovery.js.map +1 -0
  61. package/dist/discovery.test.d.ts +1 -0
  62. package/dist/discovery.test.js +24 -0
  63. package/dist/discovery.test.js.map +1 -0
  64. package/dist/http.d.ts +19 -0
  65. package/dist/http.js +46 -0
  66. package/dist/http.js.map +1 -0
  67. package/dist/http.test.d.ts +1 -0
  68. package/dist/http.test.js +70 -0
  69. package/dist/http.test.js.map +1 -0
  70. package/dist/skills.d.ts +34 -0
  71. package/dist/skills.js +135 -0
  72. package/dist/skills.js.map +1 -0
  73. package/dist/skills.test.d.ts +1 -0
  74. package/dist/skills.test.js +83 -0
  75. package/dist/skills.test.js.map +1 -0
  76. package/dist/types.d.ts +7 -0
  77. package/dist/types.js +2 -0
  78. package/dist/types.js.map +1 -0
  79. package/package.json +39 -0
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,106 @@
1
+ /* @vitest-environment node */
2
+ import { afterEach, describe, expect, it, vi } from 'vitest';
3
+ const mockIntro = vi.fn();
4
+ const mockOutro = vi.fn();
5
+ const mockNote = vi.fn();
6
+ vi.mock('@clack/prompts', () => ({
7
+ intro: (value) => mockIntro(value),
8
+ outro: (value) => mockOutro(value),
9
+ note: (message, body) => mockNote(message, body),
10
+ multiselect: vi.fn(async () => []),
11
+ text: vi.fn(async () => ''),
12
+ isCancel: () => false,
13
+ }));
14
+ vi.mock('../../config.js', () => ({
15
+ readGlobalConfig: vi.fn(async () => ({ registry: 'https://clawdhub.com', token: 'tkn' })),
16
+ }));
17
+ const mockGetRegistry = vi.fn(async () => 'https://clawdhub.com');
18
+ vi.mock('../registry.js', () => ({
19
+ getRegistry: () => mockGetRegistry(),
20
+ }));
21
+ const mockApiRequest = vi.fn();
22
+ vi.mock('../../http.js', () => ({
23
+ apiRequest: (registry, args, schema) => mockApiRequest(registry, args, schema),
24
+ }));
25
+ const mockFail = vi.fn((message) => {
26
+ throw new Error(message);
27
+ });
28
+ const mockSpinner = { succeed: vi.fn(), fail: vi.fn(), stop: vi.fn() };
29
+ vi.mock('../ui.js', () => ({
30
+ createSpinner: vi.fn(() => mockSpinner),
31
+ fail: (message) => mockFail(message),
32
+ formatError: (error) => (error instanceof Error ? error.message : String(error)),
33
+ isInteractive: () => false,
34
+ }));
35
+ vi.mock('../scanSkills.js', () => ({
36
+ findSkillFolders: vi.fn(async (root) => {
37
+ if (!root.endsWith('/scan'))
38
+ return [];
39
+ return [
40
+ { folder: '/scan/new-skill', slug: 'new-skill', displayName: 'New Skill' },
41
+ { folder: '/scan/synced-skill', slug: 'synced-skill', displayName: 'Synced Skill' },
42
+ { folder: '/scan/update-skill', slug: 'update-skill', displayName: 'Update Skill' },
43
+ ];
44
+ }),
45
+ getFallbackSkillRoots: vi.fn(() => []),
46
+ }));
47
+ vi.mock('../../skills.js', async () => {
48
+ const actual = await vi.importActual('../../skills.js');
49
+ return {
50
+ ...actual,
51
+ listTextFiles: vi.fn(async (folder) => [
52
+ { relPath: 'SKILL.md', bytes: new TextEncoder().encode(folder) },
53
+ ]),
54
+ };
55
+ });
56
+ const mockCmdPublish = vi.fn();
57
+ vi.mock('./publish.js', () => ({
58
+ cmdPublish: (...args) => mockCmdPublish(...args),
59
+ }));
60
+ const { cmdSync } = await import('./sync');
61
+ function makeOpts() {
62
+ return {
63
+ workdir: '/work',
64
+ dir: '/work/skills',
65
+ site: 'https://clawdhub.com',
66
+ registry: 'https://clawdhub.com',
67
+ };
68
+ }
69
+ afterEach(() => {
70
+ vi.clearAllMocks();
71
+ });
72
+ describe('cmdSync', () => {
73
+ it('classifies skills as new/update/synced (dry-run, mocked HTTP)', async () => {
74
+ mockApiRequest.mockImplementation(async (_registry, args) => {
75
+ if (args.path === '/api/cli/whoami')
76
+ return { user: { handle: 'steipete' } };
77
+ if (args.path.startsWith('/api/skill?slug=')) {
78
+ const slug = new URL(`https://x.test${args.path}`).searchParams.get('slug');
79
+ if (slug === 'new-skill')
80
+ return { latestVersion: undefined, skill: null };
81
+ if (slug === 'synced-skill')
82
+ return { latestVersion: { version: '1.2.3' }, skill: {} };
83
+ if (slug === 'update-skill')
84
+ return { latestVersion: { version: '1.0.0' }, skill: {} };
85
+ }
86
+ if (args.path.startsWith('/api/skill/resolve?')) {
87
+ const u = new URL(`https://x.test${args.path}`);
88
+ const slug = u.searchParams.get('slug');
89
+ if (slug === 'synced-skill') {
90
+ return { match: { version: '1.2.3' }, latestVersion: { version: '1.2.3' } };
91
+ }
92
+ if (slug === 'update-skill') {
93
+ return { match: null, latestVersion: { version: '1.0.0' } };
94
+ }
95
+ }
96
+ throw new Error(`Unexpected apiRequest: ${args.path}`);
97
+ });
98
+ await cmdSync(makeOpts(), { root: ['/scan'], all: true, dryRun: true }, true);
99
+ expect(mockCmdPublish).not.toHaveBeenCalled();
100
+ const alreadySyncedNote = mockNote.mock.calls.find((call) => call[0] === 'Already synced');
101
+ expect(alreadySyncedNote?.[1]).toMatch(/synced-skill/);
102
+ const dryRunOutro = mockOutro.mock.calls.at(-1)?.[0];
103
+ expect(String(dryRunOutro)).toMatch(/Dry run: would upload 2 skill/);
104
+ });
105
+ });
106
+ //# sourceMappingURL=sync.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync.test.js","sourceRoot":"","sources":["../../../src/cli/commands/sync.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ export declare function styleTitle(value: string): string;
2
+ export declare function configureCommanderHelp(program: {
3
+ configureHelp: (config: {
4
+ sectionTitle?: (title: string) => string;
5
+ optionTerm?: (option: {
6
+ flags: string;
7
+ }) => string;
8
+ commandTerm?: (cmd: {
9
+ name: () => string;
10
+ }) => string;
11
+ }) => unknown;
12
+ }): void;
13
+ export declare function styleEnvBlock(value: string): string;
@@ -0,0 +1,38 @@
1
+ function wrap(start, end = '\x1b[0m') {
2
+ return (value) => `${start}${value}${end}`;
3
+ }
4
+ const ansi = {
5
+ reset: '\x1b[0m',
6
+ bold: wrap('\x1b[1m'),
7
+ dim: wrap('\x1b[2m'),
8
+ cyan: wrap('\x1b[36m'),
9
+ green: wrap('\x1b[32m'),
10
+ yellow: wrap('\x1b[33m'),
11
+ };
12
+ function isColorEnabled() {
13
+ if (!process.stdout.isTTY)
14
+ return false;
15
+ if (process.env.NO_COLOR)
16
+ return false;
17
+ return true;
18
+ }
19
+ export function styleTitle(value) {
20
+ if (!isColorEnabled())
21
+ return value;
22
+ return `${ansi.bold(ansi.cyan(value))}${ansi.reset}`;
23
+ }
24
+ export function configureCommanderHelp(program) {
25
+ if (!isColorEnabled())
26
+ return;
27
+ program.configureHelp({
28
+ sectionTitle: (title) => ansi.bold(ansi.cyan(title)),
29
+ optionTerm: (option) => ansi.yellow(option.flags),
30
+ commandTerm: (cmd) => ansi.green(cmd.name()),
31
+ });
32
+ }
33
+ export function styleEnvBlock(value) {
34
+ if (!isColorEnabled())
35
+ return value;
36
+ return `${ansi.dim(value)}${ansi.reset}`;
37
+ }
38
+ //# sourceMappingURL=helpStyle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpStyle.js","sourceRoot":"","sources":["../../src/cli/helpStyle.ts"],"names":[],"mappings":"AAEA,SAAS,IAAI,CAAC,KAAa,EAAE,GAAG,GAAG,SAAS;IAC1C,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,KAAK,GAAG,KAAK,GAAG,GAAG,EAAE,CAAA;AAC5C,CAAC;AAED,MAAM,IAAI,GAAG;IACX,KAAK,EAAE,SAAS;IAChB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;IACrB,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC;IACpB,IAAI,EAAE,IAAI,CAAC,UAAU,CAAC;IACtB,KAAK,EAAE,IAAI,CAAC,UAAU,CAAC;IACvB,MAAM,EAAE,IAAI,CAAC,UAAU,CAAC;CACzB,CAAA;AAED,SAAS,cAAc;IACrB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK;QAAE,OAAO,KAAK,CAAA;IACvC,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ;QAAE,OAAO,KAAK,CAAA;IACtC,OAAO,IAAI,CAAA;AACb,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,KAAa;IACtC,IAAI,CAAC,cAAc,EAAE;QAAE,OAAO,KAAK,CAAA;IACnC,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,EAAE,CAAA;AACtD,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,OAMtC;IACC,IAAI,CAAC,cAAc,EAAE;QAAE,OAAM;IAC7B,OAAO,CAAC,aAAa,CAAC;QACpB,YAAY,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACpD,UAAU,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC;QACjD,WAAW,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;KAC7C,CAAC,CAAA;AACJ,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAAa;IACzC,IAAI,CAAC,cAAc,EAAE;QAAE,OAAO,KAAK,CAAA;IACnC,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,KAAK,EAAE,CAAA;AAC1C,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { GlobalOpts } from './types.js';
2
+ export declare const DEFAULT_SITE = "https://clawdhub.com";
3
+ export declare const DEFAULT_REGISTRY = "https://clawdhub.com";
4
+ export declare function resolveRegistry(opts: GlobalOpts): Promise<string>;
5
+ export declare function getRegistry(opts: GlobalOpts, params?: {
6
+ cache?: boolean;
7
+ }): Promise<string>;
@@ -0,0 +1,27 @@
1
+ import { readGlobalConfig, writeGlobalConfig } from '../config.js';
2
+ import { discoverRegistryFromSite } from '../discovery.js';
3
+ export const DEFAULT_SITE = 'https://clawdhub.com';
4
+ export const DEFAULT_REGISTRY = 'https://clawdhub.com';
5
+ export async function resolveRegistry(opts) {
6
+ const cfg = await readGlobalConfig();
7
+ if (cfg?.registry && cfg.registry !== DEFAULT_REGISTRY)
8
+ return cfg.registry;
9
+ const explicit = opts.registry.trim();
10
+ if (explicit && explicit !== DEFAULT_REGISTRY)
11
+ return explicit;
12
+ const discovery = await discoverRegistryFromSite(opts.site).catch(() => null);
13
+ const discovered = discovery?.apiBase?.trim();
14
+ return discovered || explicit || DEFAULT_REGISTRY;
15
+ }
16
+ export async function getRegistry(opts, params) {
17
+ const cache = params?.cache !== false;
18
+ const registry = await resolveRegistry(opts);
19
+ if (!cache)
20
+ return registry;
21
+ const cfg = await readGlobalConfig();
22
+ if (!cfg || !cfg.registry || cfg.registry === DEFAULT_REGISTRY) {
23
+ await writeGlobalConfig({ registry, token: cfg?.token });
24
+ }
25
+ return registry;
26
+ }
27
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/cli/registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AAClE,OAAO,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAA;AAG1D,MAAM,CAAC,MAAM,YAAY,GAAG,sBAAsB,CAAA;AAClD,MAAM,CAAC,MAAM,gBAAgB,GAAG,sBAAsB,CAAA;AAEtD,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,IAAgB;IACpD,MAAM,GAAG,GAAG,MAAM,gBAAgB,EAAE,CAAA;IACpC,IAAI,GAAG,EAAE,QAAQ,IAAI,GAAG,CAAC,QAAQ,KAAK,gBAAgB;QAAE,OAAO,GAAG,CAAC,QAAQ,CAAA;IAE3E,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAA;IACrC,IAAI,QAAQ,IAAI,QAAQ,KAAK,gBAAgB;QAAE,OAAO,QAAQ,CAAA;IAE9D,MAAM,SAAS,GAAG,MAAM,wBAAwB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAA;IAC7E,MAAM,UAAU,GAAG,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,CAAA;IAC7C,OAAO,UAAU,IAAI,QAAQ,IAAI,gBAAgB,CAAA;AACnD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,IAAgB,EAAE,MAA4B;IAC9E,MAAM,KAAK,GAAG,MAAM,EAAE,KAAK,KAAK,KAAK,CAAA;IACrC,MAAM,QAAQ,GAAG,MAAM,eAAe,CAAC,IAAI,CAAC,CAAA;IAC5C,IAAI,CAAC,KAAK;QAAE,OAAO,QAAQ,CAAA;IAC3B,MAAM,GAAG,GAAG,MAAM,gBAAgB,EAAE,CAAA;IACpC,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,QAAQ,KAAK,gBAAgB,EAAE,CAAC;QAC/D,MAAM,iBAAiB,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAA;IAC1D,CAAC;IACD,OAAO,QAAQ,CAAA;AACjB,CAAC"}
@@ -0,0 +1,7 @@
1
+ export type SkillFolder = {
2
+ folder: string;
3
+ slug: string;
4
+ displayName: string;
5
+ };
6
+ export declare function findSkillFolders(root: string): Promise<SkillFolder[]>;
7
+ export declare function getFallbackSkillRoots(workdir: string): string[];
@@ -0,0 +1,75 @@
1
+ import { readdir, stat } from 'node:fs/promises';
2
+ import { homedir } from 'node:os';
3
+ import { basename, join, resolve } from 'node:path';
4
+ import { sanitizeSlug, titleCase } from './slug.js';
5
+ export async function findSkillFolders(root) {
6
+ const absRoot = resolve(root);
7
+ const rootStat = await stat(absRoot).catch(() => null);
8
+ if (!rootStat || !rootStat.isDirectory())
9
+ return [];
10
+ const direct = await isSkillFolder(absRoot);
11
+ if (direct)
12
+ return [direct];
13
+ const entries = await readdir(absRoot, { withFileTypes: true }).catch(() => []);
14
+ const folders = entries
15
+ .filter((entry) => entry.isDirectory())
16
+ .map((entry) => join(absRoot, entry.name));
17
+ const results = [];
18
+ for (const folder of folders) {
19
+ const found = await isSkillFolder(folder);
20
+ if (found)
21
+ results.push(found);
22
+ }
23
+ return results.sort((a, b) => a.slug.localeCompare(b.slug));
24
+ }
25
+ export function getFallbackSkillRoots(workdir) {
26
+ const home = homedir();
27
+ const roots = [
28
+ // adjacent repo installs
29
+ resolve(workdir, '..', 'clawdis', 'skills'),
30
+ resolve(workdir, '..', 'clawdis', 'Skills'),
31
+ resolve(workdir, '..', 'clawdbot', 'skills'),
32
+ resolve(workdir, '..', 'clawdbot', 'Skills'),
33
+ // legacy locations
34
+ resolve(home, 'clawd', 'skills'),
35
+ resolve(home, 'clawd', 'Skills'),
36
+ resolve(home, '.clawd', 'skills'),
37
+ resolve(home, '.clawd', 'Skills'),
38
+ resolve(home, 'clawdbot', 'skills'),
39
+ resolve(home, 'clawdbot', 'Skills'),
40
+ resolve(home, '.clawdbot', 'skills'),
41
+ resolve(home, '.clawdbot', 'Skills'),
42
+ resolve(home, 'clawdis', 'skills'),
43
+ resolve(home, 'clawdis', 'Skills'),
44
+ resolve(home, '.clawdis', 'skills'),
45
+ resolve(home, '.clawdis', 'Skills'),
46
+ // macOS App Support legacy
47
+ resolve(home, 'Library', 'Application Support', 'clawdbot', 'skills'),
48
+ resolve(home, 'Library', 'Application Support', 'clawdbot', 'Skills'),
49
+ resolve(home, 'Library', 'Application Support', 'clawdis', 'skills'),
50
+ resolve(home, 'Library', 'Application Support', 'clawdis', 'Skills'),
51
+ ];
52
+ return Array.from(new Set(roots));
53
+ }
54
+ async function isSkillFolder(folder) {
55
+ const marker = await findSkillMarker(folder);
56
+ if (!marker)
57
+ return null;
58
+ const base = basename(folder);
59
+ const slug = sanitizeSlug(base);
60
+ if (!slug)
61
+ return null;
62
+ const displayName = titleCase(base);
63
+ return { folder, slug, displayName };
64
+ }
65
+ async function findSkillMarker(folder) {
66
+ const candidates = ['SKILL.md', 'skill.md', 'Skills.md', 'skills.md'];
67
+ for (const name of candidates) {
68
+ const path = join(folder, name);
69
+ const st = await stat(path).catch(() => null);
70
+ if (st?.isFile())
71
+ return path;
72
+ }
73
+ return null;
74
+ }
75
+ //# sourceMappingURL=scanSkills.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scanSkills.js","sourceRoot":"","sources":["../../src/cli/scanSkills.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,47 @@
1
+ /* @vitest-environment node */
2
+ import { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises';
3
+ import { tmpdir } from 'node:os';
4
+ import { join, resolve } from 'node:path';
5
+ import { describe, expect, it } from 'vitest';
6
+ import { findSkillFolders, getFallbackSkillRoots } from './scanSkills';
7
+ async function makeTmpDir() {
8
+ return mkdtemp(join(tmpdir(), 'clawdhub-scan-'));
9
+ }
10
+ describe('scanSkills', () => {
11
+ it('detects a single skill folder (root contains SKILL.md)', async () => {
12
+ const root = await makeTmpDir();
13
+ try {
14
+ await writeFile(join(root, 'SKILL.md'), '# Skill\n', 'utf8');
15
+ const found = await findSkillFolders(root);
16
+ expect(found).toHaveLength(1);
17
+ expect(found[0]?.folder).toBe(resolve(root));
18
+ expect(found[0]?.slug).toBeTruthy();
19
+ }
20
+ finally {
21
+ await rm(root, { recursive: true, force: true });
22
+ }
23
+ });
24
+ it('detects skills in a skills directory (subfolders)', async () => {
25
+ const root = await makeTmpDir();
26
+ try {
27
+ const skillsDir = join(root, 'skills');
28
+ const folder = join(skillsDir, 'cool-skill');
29
+ await mkdir(folder, { recursive: true });
30
+ await writeFile(join(folder, 'SKILL.md'), '# Skill\n', 'utf8');
31
+ const found = await findSkillFolders(skillsDir);
32
+ expect(found).toHaveLength(1);
33
+ expect(found[0]?.slug).toBe('cool-skill');
34
+ expect(found[0]?.folder).toBe(resolve(folder));
35
+ }
36
+ finally {
37
+ await rm(root, { recursive: true, force: true });
38
+ }
39
+ });
40
+ it('includes known legacy roots', () => {
41
+ const roots = getFallbackSkillRoots('/tmp/anywhere');
42
+ expect(roots.some((p) => p.endsWith('/clawdis/skills'))).toBe(true);
43
+ expect(roots.some((p) => p.endsWith('/clawd/skills'))).toBe(true);
44
+ expect(roots.some((p) => p.endsWith('/clawdbot/skills'))).toBe(true);
45
+ });
46
+ });
47
+ //# sourceMappingURL=scanSkills.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scanSkills.test.js","sourceRoot":"","sources":["../../src/cli/scanSkills.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function sanitizeSlug(value: string): string;
2
+ export declare function titleCase(value: string): string;
@@ -0,0 +1,16 @@
1
+ export function sanitizeSlug(value) {
2
+ const raw = value
3
+ .trim()
4
+ .toLowerCase()
5
+ .replace(/[^a-z0-9-]+/g, '-');
6
+ const cleaned = raw.replace(/^-+/, '').replace(/-+$/, '').replace(/--+/g, '-');
7
+ return cleaned;
8
+ }
9
+ export function titleCase(value) {
10
+ return value
11
+ .trim()
12
+ .replace(/[-_]+/g, ' ')
13
+ .replace(/\s+/g, ' ')
14
+ .replace(/\b\w/g, (char) => char.toUpperCase());
15
+ }
16
+ //# sourceMappingURL=slug.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slug.js","sourceRoot":"","sources":["../../src/cli/slug.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,YAAY,CAAC,KAAa;IACxC,MAAM,GAAG,GAAG,KAAK;SACd,IAAI,EAAE;SACN,WAAW,EAAE;SACb,OAAO,CAAC,cAAc,EAAE,GAAG,CAAC,CAAA;IAC/B,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAC9E,OAAO,OAAO,CAAA;AAChB,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,KAAa;IACrC,OAAO,KAAK;SACT,IAAI,EAAE;SACN,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC;SACtB,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;SACpB,OAAO,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAA;AACnD,CAAC"}
@@ -0,0 +1,14 @@
1
+ export type GlobalOpts = {
2
+ workdir: string;
3
+ dir: string;
4
+ site: string;
5
+ registry: string;
6
+ };
7
+ export type ResolveResult = {
8
+ match: {
9
+ version: string;
10
+ } | null;
11
+ latestVersion: {
12
+ version: string;
13
+ } | null;
14
+ };
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/cli/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,7 @@
1
+ export declare function promptHidden(prompt: string): Promise<string>;
2
+ export declare function promptConfirm(prompt: string): Promise<boolean>;
3
+ export declare function openInBrowser(url: string): void;
4
+ export declare function isInteractive(): boolean;
5
+ export declare function createSpinner(text: string): import("ora").Ora;
6
+ export declare function formatError(error: unknown): string;
7
+ export declare function fail(message: string): never;
package/dist/cli/ui.js ADDED
@@ -0,0 +1,72 @@
1
+ import { spawn } from 'node:child_process';
2
+ import { stdin } from 'node:process';
3
+ import { confirm, isCancel } from '@clack/prompts';
4
+ import ora from 'ora';
5
+ export async function promptHidden(prompt) {
6
+ if (!stdin.isTTY)
7
+ return '';
8
+ process.stdout.write(prompt);
9
+ const chunks = [];
10
+ stdin.setRawMode(true);
11
+ stdin.resume();
12
+ return new Promise((resolvePromise) => {
13
+ function onData(data) {
14
+ const text = data.toString('utf8');
15
+ if (text === '\r' || text === '\n') {
16
+ stdin.setRawMode(false);
17
+ stdin.pause();
18
+ stdin.off('data', onData);
19
+ process.stdout.write('\n');
20
+ resolvePromise(Buffer.concat(chunks).toString('utf8').trim());
21
+ return;
22
+ }
23
+ if (text === '\u0003') {
24
+ stdin.setRawMode(false);
25
+ stdin.pause();
26
+ stdin.off('data', onData);
27
+ process.stdout.write('\n');
28
+ fail('Canceled');
29
+ }
30
+ if (text === '\u007f') {
31
+ chunks.pop();
32
+ return;
33
+ }
34
+ chunks.push(data);
35
+ }
36
+ stdin.on('data', onData);
37
+ });
38
+ }
39
+ export async function promptConfirm(prompt) {
40
+ const answer = await confirm({ message: prompt });
41
+ if (isCancel(answer))
42
+ return false;
43
+ return Boolean(answer);
44
+ }
45
+ export function openInBrowser(url) {
46
+ const args = process.platform === 'darwin'
47
+ ? ['open', url]
48
+ : process.platform === 'win32'
49
+ ? ['cmd', '/c', 'start', '', url]
50
+ : ['xdg-open', url];
51
+ const [command, ...commandArgs] = args;
52
+ if (!command)
53
+ return;
54
+ const child = spawn(command, commandArgs, { stdio: 'ignore', detached: true });
55
+ child.unref();
56
+ }
57
+ export function isInteractive() {
58
+ return Boolean(process.stdout.isTTY && stdin.isTTY);
59
+ }
60
+ export function createSpinner(text) {
61
+ return ora({ text, spinner: 'dots', isEnabled: isInteractive() }).start();
62
+ }
63
+ export function formatError(error) {
64
+ if (error instanceof Error)
65
+ return error.message;
66
+ return String(error);
67
+ }
68
+ export function fail(message) {
69
+ console.error(`Error: ${message}`);
70
+ process.exit(1);
71
+ }
72
+ //# sourceMappingURL=ui.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui.js","sourceRoot":"","sources":["../../src/cli/ui.ts"],"names":[],"mappings":"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"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};