@skillsmanager/cli 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 (48) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +84 -0
  3. package/dist/auth.d.ts +5 -0
  4. package/dist/auth.js +68 -0
  5. package/dist/backends/gdrive.d.ts +24 -0
  6. package/dist/backends/gdrive.js +371 -0
  7. package/dist/backends/interface.d.ts +14 -0
  8. package/dist/backends/interface.js +1 -0
  9. package/dist/backends/local.d.ts +20 -0
  10. package/dist/backends/local.js +159 -0
  11. package/dist/bm25.d.ts +20 -0
  12. package/dist/bm25.js +65 -0
  13. package/dist/cache.d.ts +21 -0
  14. package/dist/cache.js +59 -0
  15. package/dist/commands/add.d.ts +3 -0
  16. package/dist/commands/add.js +62 -0
  17. package/dist/commands/collection.d.ts +1 -0
  18. package/dist/commands/collection.js +42 -0
  19. package/dist/commands/fetch.d.ts +5 -0
  20. package/dist/commands/fetch.js +46 -0
  21. package/dist/commands/init.d.ts +1 -0
  22. package/dist/commands/init.js +45 -0
  23. package/dist/commands/install.d.ts +8 -0
  24. package/dist/commands/install.js +89 -0
  25. package/dist/commands/list.d.ts +3 -0
  26. package/dist/commands/list.js +38 -0
  27. package/dist/commands/refresh.d.ts +1 -0
  28. package/dist/commands/refresh.js +46 -0
  29. package/dist/commands/registry.d.ts +14 -0
  30. package/dist/commands/registry.js +258 -0
  31. package/dist/commands/search.d.ts +1 -0
  32. package/dist/commands/search.js +37 -0
  33. package/dist/commands/setup/google.d.ts +1 -0
  34. package/dist/commands/setup/google.js +281 -0
  35. package/dist/commands/update.d.ts +3 -0
  36. package/dist/commands/update.js +83 -0
  37. package/dist/config.d.ts +28 -0
  38. package/dist/config.js +136 -0
  39. package/dist/index.d.ts +2 -0
  40. package/dist/index.js +128 -0
  41. package/dist/ready.d.ts +15 -0
  42. package/dist/ready.js +39 -0
  43. package/dist/registry.d.ts +10 -0
  44. package/dist/registry.js +58 -0
  45. package/dist/types.d.ts +54 -0
  46. package/dist/types.js +13 -0
  47. package/package.json +56 -0
  48. package/skills/skillsmanager/SKILL.md +139 -0
@@ -0,0 +1,15 @@
1
+ import type { OAuth2Client } from "google-auth-library";
2
+ import { GDriveBackend } from "./backends/gdrive.js";
3
+ import type { Config } from "./types.js";
4
+ export interface ReadyContext {
5
+ auth: OAuth2Client;
6
+ config: Config;
7
+ backend: GDriveBackend;
8
+ }
9
+ /**
10
+ * Ensures the user is authenticated and has at least one collection configured.
11
+ * - If not authenticated: launches OAuth flow automatically.
12
+ * - If no config or empty collections: auto-discovers from Google Drive.
13
+ * Call this at the start of any command that needs Drive access.
14
+ */
15
+ export declare function ensureReady(): Promise<ReadyContext>;
package/dist/ready.js ADDED
@@ -0,0 +1,39 @@
1
+ import chalk from "chalk";
2
+ import { ensureAuth } from "./auth.js";
3
+ import { readConfig, writeConfig, mergeCollections, CONFIG_PATH } from "./config.js";
4
+ import { GDriveBackend } from "./backends/gdrive.js";
5
+ import fs from "fs";
6
+ /**
7
+ * Ensures the user is authenticated and has at least one collection configured.
8
+ * - If not authenticated: launches OAuth flow automatically.
9
+ * - If no config or empty collections: auto-discovers from Google Drive.
10
+ * Call this at the start of any command that needs Drive access.
11
+ */
12
+ export async function ensureReady() {
13
+ const auth = await ensureAuth();
14
+ const backend = new GDriveBackend(auth);
15
+ // Try to load config
16
+ let config = null;
17
+ if (fs.existsSync(CONFIG_PATH)) {
18
+ try {
19
+ config = readConfig();
20
+ }
21
+ catch {
22
+ config = null;
23
+ }
24
+ }
25
+ // Auto-discover if no config or no collections
26
+ if (!config || config.collections.length === 0) {
27
+ process.stdout.write(chalk.dim("Discovering collections... "));
28
+ const fresh = await backend.discoverCollections();
29
+ const collections = mergeCollections(fresh, config?.collections ?? []);
30
+ config = { registries: config?.registries ?? [], collections, skills: config?.skills ?? {}, discoveredAt: new Date().toISOString() };
31
+ writeConfig(config);
32
+ if (collections.length === 0) {
33
+ process.stdout.write("\n");
34
+ throw new Error("No collections found. Run: skillsmanager collection create <name>");
35
+ }
36
+ process.stdout.write(chalk.green(`found ${collections.length}.\n`));
37
+ }
38
+ return { auth, config: config, backend };
39
+ }
@@ -0,0 +1,10 @@
1
+ import type { CollectionFile, RegistryFile } from "./types.js";
2
+ export declare const REGISTRY_FILENAME = "SKILLS_REGISTRY.yaml";
3
+ export declare const COLLECTION_FILENAME = "SKILLS_COLLECTION.yaml";
4
+ export declare const LEGACY_COLLECTION_FILENAME = "SKILLS_SYNC.yaml";
5
+ export declare function parseCollection(content: string): CollectionFile;
6
+ export declare function serializeCollection(collection: CollectionFile): string;
7
+ export declare const parseRegistry: typeof parseCollection;
8
+ export declare const serializeRegistry: typeof serializeCollection;
9
+ export declare function parseRegistryFile(content: string): RegistryFile;
10
+ export declare function serializeRegistryFile(registry: RegistryFile): string;
@@ -0,0 +1,58 @@
1
+ import YAML from "yaml";
2
+ // ── Filename constants ───────────────────────────────────────────────────────
3
+ export const REGISTRY_FILENAME = "SKILLS_REGISTRY.yaml";
4
+ export const COLLECTION_FILENAME = "SKILLS_COLLECTION.yaml";
5
+ export const LEGACY_COLLECTION_FILENAME = "SKILLS_SYNC.yaml";
6
+ // ── Collection (formerly "registry") parsing ─────────────────────────────────
7
+ export function parseCollection(content) {
8
+ const data = YAML.parse(content);
9
+ return {
10
+ name: data.name ?? "",
11
+ owner: data.owner ?? "",
12
+ skills: (data.skills ?? []).map((s) => ({
13
+ name: s.name,
14
+ path: s.path ?? `${s.name}/`,
15
+ description: s.description ?? "",
16
+ })),
17
+ };
18
+ }
19
+ export function serializeCollection(collection) {
20
+ return YAML.stringify({
21
+ name: collection.name,
22
+ owner: collection.owner,
23
+ skills: collection.skills.map((s) => ({
24
+ name: s.name,
25
+ path: s.path,
26
+ description: s.description,
27
+ })),
28
+ });
29
+ }
30
+ // Backwards-compat aliases
31
+ export const parseRegistry = parseCollection;
32
+ export const serializeRegistry = serializeCollection;
33
+ // ── Registry file parsing ────────────────────────────────────────────────────
34
+ export function parseRegistryFile(content) {
35
+ const data = YAML.parse(content);
36
+ return {
37
+ name: data.name ?? "",
38
+ owner: data.owner ?? "",
39
+ source: data.source ?? "local",
40
+ collections: (data.collections ?? []).map((c) => ({
41
+ name: c.name,
42
+ backend: c.backend ?? "local",
43
+ ref: c.ref ?? c.name,
44
+ })),
45
+ };
46
+ }
47
+ export function serializeRegistryFile(registry) {
48
+ return YAML.stringify({
49
+ name: registry.name,
50
+ owner: registry.owner,
51
+ source: registry.source,
52
+ collections: registry.collections.map((c) => ({
53
+ name: c.name,
54
+ backend: c.backend,
55
+ ref: c.ref,
56
+ })),
57
+ });
58
+ }
@@ -0,0 +1,54 @@
1
+ export interface SkillEntry {
2
+ name: string;
3
+ path: string;
4
+ description: string;
5
+ }
6
+ export interface CollectionFile {
7
+ name: string;
8
+ owner: string;
9
+ skills: SkillEntry[];
10
+ }
11
+ export interface CollectionInfo {
12
+ id: string;
13
+ name: string;
14
+ backend: string;
15
+ folderId: string;
16
+ registryFileId?: string;
17
+ sourceRegistryId?: string;
18
+ }
19
+ export interface RegistryCollectionRef {
20
+ name: string;
21
+ backend: string;
22
+ ref: string;
23
+ }
24
+ export interface RegistryFile {
25
+ name: string;
26
+ owner: string;
27
+ source: string;
28
+ collections: RegistryCollectionRef[];
29
+ }
30
+ export interface RegistryInfo {
31
+ id: string;
32
+ name: string;
33
+ backend: string;
34
+ folderId: string;
35
+ fileId?: string;
36
+ }
37
+ export interface SkillLocation {
38
+ collectionId: string;
39
+ installedAt: string[];
40
+ }
41
+ export interface SkillIndex {
42
+ [skillName: string]: SkillLocation[];
43
+ }
44
+ export interface Config {
45
+ registries: RegistryInfo[];
46
+ collections: CollectionInfo[];
47
+ skills: SkillIndex;
48
+ discoveredAt: string;
49
+ }
50
+ export interface ResolvedSkill {
51
+ entry: SkillEntry;
52
+ collection: CollectionInfo;
53
+ }
54
+ export declare const AGENT_PATHS: Record<string, string>;
package/dist/types.js ADDED
@@ -0,0 +1,13 @@
1
+ import os from "os";
2
+ import path from "path";
3
+ // Agent name → user-level skills directory path
4
+ export const AGENT_PATHS = {
5
+ claude: path.join(os.homedir(), ".claude", "skills"),
6
+ codex: path.join(os.homedir(), ".codex", "skills"),
7
+ agents: path.join(os.homedir(), ".agents", "skills"),
8
+ cursor: path.join(os.homedir(), ".cursor", "skills"),
9
+ windsurf: path.join(os.homedir(), ".codeium", "windsurf", "skills"),
10
+ copilot: path.join(os.homedir(), ".copilot", "skills"),
11
+ gemini: path.join(os.homedir(), ".gemini", "skills"),
12
+ roo: path.join(os.homedir(), ".roo", "skills"),
13
+ };
package/package.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "@skillsmanager/cli",
3
+ "version": "0.0.1",
4
+ "description": "Discover, fetch, and manage agent skills from local or remote storage",
5
+ "type": "module",
6
+ "bin": {
7
+ "skillsmanager": "./dist/index.js"
8
+ },
9
+ "files": [
10
+ "dist/",
11
+ "!dist/tests/",
12
+ "skills/"
13
+ ],
14
+ "scripts": {
15
+ "build": "tsc",
16
+ "prepublishOnly": "npm run build",
17
+ "dev": "node --loader ts-node/esm src/index.ts",
18
+ "test": "vitest run",
19
+ "test:watch": "vitest"
20
+ },
21
+ "keywords": [
22
+ "ai",
23
+ "agent",
24
+ "skills",
25
+ "claude",
26
+ "codex",
27
+ "cursor",
28
+ "copilot",
29
+ "gemini",
30
+ "registry",
31
+ "sync"
32
+ ],
33
+ "repository": {
34
+ "type": "git",
35
+ "url": "git+https://github.com/talktoajayprakash/skillsmanager.git"
36
+ },
37
+ "author": "Ajay Prakash",
38
+ "license": "MIT",
39
+ "homepage": "https://github.com/talktoajayprakash/skillsmanager#readme",
40
+ "dependencies": {
41
+ "chalk": "^4.1.2",
42
+ "commander": "^12.0.0",
43
+ "googleapis": "^144.0.0",
44
+ "ora": "^5.4.1",
45
+ "yaml": "^2.4.0"
46
+ },
47
+ "devDependencies": {
48
+ "@types/node": "^20.0.0",
49
+ "ts-node": "^10.9.2",
50
+ "typescript": "^5.4.0",
51
+ "vitest": "^4.1.0"
52
+ },
53
+ "engines": {
54
+ "node": ">=18"
55
+ }
56
+ }
@@ -0,0 +1,139 @@
1
+ ---
2
+ name: skillsmanager
3
+ description: Discover, fetch, add, and update agent skills from local or remote storage using the skillsmanager CLI
4
+ ---
5
+
6
+ # Skills Manager
7
+
8
+ Skills Manager is a CLI tool for managing agent skills stored locally or in remote storage (Google Drive). Use it to find, install, share, and update skills. Works offline by default — no setup needed for local use.
9
+
10
+ ## Prerequisites
11
+
12
+ - Local storage works out of the box — no setup needed.
13
+ - For Google Drive: a human must run `skillsmanager setup google` once to configure credentials.
14
+ - All commands except `setup google` are non-interactive and designed for agent use.
15
+
16
+ ## Commands
17
+
18
+ ### Find and install a skill
19
+
20
+ ```bash
21
+ # Search by name or description (BM25 ranked — partial/reordered terms work)
22
+ skillsmanager search <query>
23
+
24
+ # Download and install for this agent
25
+ skillsmanager fetch <name> --agent <agent>
26
+
27
+ # Install to current project only (instead of global)
28
+ skillsmanager fetch <name> --agent <agent> --scope project
29
+
30
+ # List all available skills across all collections
31
+ skillsmanager list
32
+ ```
33
+
34
+ Supported agents: `claude`, `codex`, `agents`, `cursor`, `windsurf`, `copilot`, `gemini`, `roo`
35
+
36
+ ### Share a skill
37
+
38
+ ```bash
39
+ # Upload a local skill directory to a collection
40
+ # The directory must contain a SKILL.md with name and description in YAML frontmatter
41
+ skillsmanager add <path>
42
+
43
+ # Upload to a specific collection
44
+ skillsmanager add <path> --collection <name>
45
+ ```
46
+
47
+ ### Update a skill
48
+
49
+ ```bash
50
+ # Push local edits back to storage
51
+ # The skill must have been fetched on this machine first
52
+ skillsmanager update <path>
53
+
54
+ # If the skill exists in multiple collections, specify which one
55
+ skillsmanager update <path> --collection <name>
56
+ ```
57
+
58
+ After updating, the local cache is refreshed so all symlinks on this machine reflect the change immediately.
59
+
60
+ ### Registry and collection management
61
+
62
+ ```bash
63
+ # Create a local registry (auto-created on first use)
64
+ skillsmanager registry create
65
+
66
+ # Create a registry in Google Drive
67
+ skillsmanager registry create --backend gdrive
68
+
69
+ # Show all registries and their collection references
70
+ skillsmanager registry list
71
+
72
+ # Search a backend for registries owned by the current user
73
+ skillsmanager registry discover --backend gdrive
74
+
75
+ # Add a collection reference to the registry
76
+ skillsmanager registry add-collection <name>
77
+
78
+ # Push local registry and collections to Google Drive
79
+ skillsmanager registry push --backend gdrive
80
+
81
+ # Create a new collection
82
+ skillsmanager collection create [name]
83
+
84
+ # Re-discover collections from storage
85
+ skillsmanager refresh
86
+ ```
87
+
88
+ ### Install the skillsmanager skill for agents
89
+
90
+ ```bash
91
+ # Install to all agent directories
92
+ skillsmanager install
93
+
94
+ # Install to specific agents
95
+ skillsmanager install --agent claude,codex
96
+
97
+ # Install to a custom path
98
+ skillsmanager install --path <dir>
99
+
100
+ # Remove from all agents
101
+ skillsmanager uninstall
102
+ ```
103
+
104
+ ## Common Workflows
105
+
106
+ **User asks to find a skill:**
107
+ 1. `skillsmanager search <relevant terms>`
108
+ 2. `skillsmanager fetch <skill-name> --agent claude`
109
+
110
+ **User asks to share a skill they created:**
111
+ 1. Ensure the skill directory has a `SKILL.md` with `name` and `description` in YAML frontmatter
112
+ 2. `skillsmanager add <path-to-skill-directory>`
113
+
114
+ **User asks to update a skill:**
115
+ 1. Edit the skill files locally
116
+ 2. `skillsmanager update <path-to-skill-directory>`
117
+
118
+ **User asks to install a skill for this project only:**
119
+ 1. `skillsmanager fetch <name> --agent claude --scope project`
120
+
121
+ **User wants to back up local skills to Google Drive:**
122
+ 1. `skillsmanager setup google` (one-time, human-only)
123
+ 2. `skillsmanager registry push --backend gdrive`
124
+
125
+ **User wants to see what registries and collections exist:**
126
+ 1. `skillsmanager registry list`
127
+
128
+ ## Architecture
129
+
130
+ - **Registry** (`SKILLS_REGISTRY.yaml`): root index pointing to all collections across backends
131
+ - **Collection** (`SKILLS_COLLECTION.yaml`): folder of skills with an index file
132
+ - **Backends**: `local` (default, `~/.skillsmanager/`) and `gdrive` (Google Drive)
133
+ - **Cache**: skills are cached at `~/.skillsmanager/cache/<uuid>/` and symlinked to agent directories
134
+ - **Symlinks**: all agents share one cached copy — updating the cache updates all agents
135
+
136
+ ## Scope
137
+
138
+ - `--scope global` (default): installs to `~/.agent/skills/` — available across all projects
139
+ - `--scope project`: installs to `./.agent/skills/` in the current working directory — this project only