@goodboyjs/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 (61) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +21 -0
  3. package/dist/commands/add.d.ts +2 -0
  4. package/dist/commands/add.js +100 -0
  5. package/dist/commands/init.d.ts +2 -0
  6. package/dist/commands/init.js +32 -0
  7. package/dist/commands/install.d.ts +13 -0
  8. package/dist/commands/install.js +192 -0
  9. package/dist/commands/list.d.ts +2 -0
  10. package/dist/commands/list.js +106 -0
  11. package/dist/commands/registry-cmd.d.ts +2 -0
  12. package/dist/commands/registry-cmd.js +122 -0
  13. package/dist/commands/search.d.ts +2 -0
  14. package/dist/commands/search.js +49 -0
  15. package/dist/commands/skill-create.d.ts +2 -0
  16. package/dist/commands/skill-create.js +143 -0
  17. package/dist/commands/skill-diff.d.ts +8 -0
  18. package/dist/commands/skill-diff.js +120 -0
  19. package/dist/commands/skill-open.d.ts +3 -0
  20. package/dist/commands/skill-open.js +82 -0
  21. package/dist/commands/skill-status.d.ts +2 -0
  22. package/dist/commands/skill-status.js +136 -0
  23. package/dist/commands/skill-version.d.ts +6 -0
  24. package/dist/commands/skill-version.js +119 -0
  25. package/dist/commands/skill.d.ts +2 -0
  26. package/dist/commands/skill.js +13 -0
  27. package/dist/commands/uninstall.d.ts +2 -0
  28. package/dist/commands/uninstall.js +53 -0
  29. package/dist/commands/upgrade.d.ts +2 -0
  30. package/dist/commands/upgrade.js +103 -0
  31. package/dist/index.d.ts +2 -0
  32. package/dist/index.js +33 -0
  33. package/dist/lib/agents.d.ts +14 -0
  34. package/dist/lib/agents.js +83 -0
  35. package/dist/lib/consent.d.ts +3 -0
  36. package/dist/lib/consent.js +48 -0
  37. package/dist/lib/fs-security.d.ts +8 -0
  38. package/dist/lib/fs-security.js +27 -0
  39. package/dist/lib/goodboy-file.d.ts +24 -0
  40. package/dist/lib/goodboy-file.js +99 -0
  41. package/dist/lib/local-registry-adapter.d.ts +18 -0
  42. package/dist/lib/local-registry-adapter.js +71 -0
  43. package/dist/lib/logger.d.ts +7 -0
  44. package/dist/lib/logger.js +28 -0
  45. package/dist/lib/manifest.d.ts +4 -0
  46. package/dist/lib/manifest.js +86 -0
  47. package/dist/lib/registry-adapter.d.ts +56 -0
  48. package/dist/lib/registry-adapter.js +15 -0
  49. package/dist/lib/registry-entry.d.ts +16 -0
  50. package/dist/lib/registry-entry.js +74 -0
  51. package/dist/lib/registry.d.ts +8 -0
  52. package/dist/lib/registry.js +114 -0
  53. package/dist/lib/skill-validator.d.ts +11 -0
  54. package/dist/lib/skill-validator.js +122 -0
  55. package/dist/lib/store.d.ts +13 -0
  56. package/dist/lib/store.js +62 -0
  57. package/dist/lib/validation.d.ts +1 -0
  58. package/dist/lib/validation.js +1 -0
  59. package/dist/types/index.d.ts +2 -0
  60. package/dist/types/index.js +1 -0
  61. package/package.json +67 -0
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Global skill store: ~/.goodboy/skills/<skill-name>/
3
+ * Skills are stored here once and symlinked into agent directories.
4
+ * @internal
5
+ */
6
+ import { existsSync, mkdirSync, cpSync, rmSync } from 'node:fs';
7
+ import { join, sep } from 'node:path';
8
+ import { homedir } from 'node:os';
9
+ import { scanForSymlinks } from './fs-security.js';
10
+ import { SKILL_NAME_RE } from './validation.js';
11
+ export function getGoodboyHome() {
12
+ return join(homedir(), '.goodboy');
13
+ }
14
+ export function getStorePath() {
15
+ return join(getGoodboyHome(), 'skills');
16
+ }
17
+ export function ensureStoreExists() {
18
+ const storePath = getStorePath();
19
+ if (!existsSync(storePath)) {
20
+ mkdirSync(storePath, { recursive: true, mode: 0o700 });
21
+ }
22
+ }
23
+ function assertValidSkillName(skillName) {
24
+ if (!SKILL_NAME_RE.test(skillName)) {
25
+ throw new Error(`Invalid skill name: "${skillName}". Must match ^[a-z0-9-]+$.`);
26
+ }
27
+ }
28
+ function assertWithinStore(target) {
29
+ const storePath = getStorePath();
30
+ /* c8 ignore next 3 */
31
+ if (!target.startsWith(storePath + sep) && target !== storePath) {
32
+ throw new Error(`Refused: path escapes the store directory`);
33
+ }
34
+ }
35
+ /**
36
+ * Copy a skill from `sourcePath` into the store.
37
+ * Returns the absolute path of the installed store entry.
38
+ */
39
+ export async function installToStore(skillName, sourcePath) {
40
+ assertValidSkillName(skillName);
41
+ const storePath = getStorePath();
42
+ const dest = join(storePath, skillName);
43
+ assertWithinStore(dest);
44
+ await scanForSymlinks(sourcePath);
45
+ ensureStoreExists();
46
+ mkdirSync(dest, { recursive: true, mode: 0o700 });
47
+ cpSync(sourcePath, dest, { recursive: true });
48
+ return dest;
49
+ }
50
+ /**
51
+ * Remove a skill from the store.
52
+ * No-op if the skill is not present.
53
+ */
54
+ export function removeFromStore(skillName) {
55
+ assertValidSkillName(skillName);
56
+ const storePath = getStorePath();
57
+ const dest = join(storePath, skillName);
58
+ assertWithinStore(dest);
59
+ if (existsSync(dest)) {
60
+ rmSync(dest, { recursive: true, force: true });
61
+ }
62
+ }
@@ -0,0 +1 @@
1
+ export declare const SKILL_NAME_RE: RegExp;
@@ -0,0 +1 @@
1
+ export const SKILL_NAME_RE = /^[a-z0-9-]+$/;
@@ -0,0 +1,2 @@
1
+ export type { GoodBoySkillManifest as GoodBoyManifest } from '@goodboyjs/schema';
2
+ export type { RegistryAdapter } from '../lib/registry-adapter.js';
@@ -0,0 +1 @@
1
+ export {};
package/package.json ADDED
@@ -0,0 +1,67 @@
1
+ {
2
+ "name": "@goodboyjs/cli",
3
+ "version": "0.1.0",
4
+ "description": "A personal skill registry and package manager for Claude Code and the Agent Skills ecosystem",
5
+ "keywords": [
6
+ "claude-code",
7
+ "agent-skills",
8
+ "skill",
9
+ "registry",
10
+ "package-manager",
11
+ "ai",
12
+ "cli"
13
+ ],
14
+ "homepage": "https://goodboyjs.io",
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "https://github.com/xpera-ch/goodboy.git",
18
+ "directory": "packages/cli"
19
+ },
20
+ "bugs": {
21
+ "url": "https://github.com/xpera-ch/goodboy/issues"
22
+ },
23
+ "license": "MIT",
24
+ "type": "module",
25
+ "bin": {
26
+ "goodboy": "./dist/index.js"
27
+ },
28
+ "main": "./dist/index.js",
29
+ "engines": {
30
+ "node": ">=20.12.0"
31
+ },
32
+ "publishConfig": {
33
+ "access": "public",
34
+ "registry": "https://registry.npmjs.org"
35
+ },
36
+ "files": [
37
+ "dist/",
38
+ "README.md",
39
+ "LICENSE"
40
+ ],
41
+ "scripts": {
42
+ "build": "rm -rf dist && tsc",
43
+ "dev": "tsx src/index.ts",
44
+ "test": "vitest run",
45
+ "test:watch": "vitest",
46
+ "test:coverage": "vitest run --coverage",
47
+ "link": "npm run build && npm link"
48
+ },
49
+ "dependencies": {
50
+ "@goodboyjs/schema": "*",
51
+ "@inquirer/prompts": "^8.5.0",
52
+ "ajv": "^8.17.0",
53
+ "ajv-formats": "^3.0.1",
54
+ "chalk": "^5.3.0",
55
+ "cli-table3": "^0.6.3",
56
+ "commander": "^12.0.0",
57
+ "ora": "^8.0.1"
58
+ },
59
+ "devDependencies": {
60
+ "@types/node": "^20.0.0",
61
+ "@vitest/coverage-v8": "^2.0.0",
62
+ "tsx": "^4.0.0",
63
+ "typescript": "^5.5.0",
64
+ "vite": "^5.0.0",
65
+ "vitest": "^2.0.0"
66
+ }
67
+ }