skilllib 1.7.0 → 1.11.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/dist/index.js CHANGED
@@ -2,6 +2,7 @@
2
2
  import {
3
3
  add,
4
4
  agentSkill,
5
+ apply,
5
6
  doctor,
6
7
  error,
7
8
  folders,
@@ -27,22 +28,24 @@ import {
27
28
  unhide,
28
29
  update,
29
30
  usage
30
- } from "./chunk-AYAN7Q2X.js";
31
+ } from "./chunk-LO4FMXDE.js";
31
32
 
32
33
  // src/index.ts
33
34
  import { readFileSync } from "fs";
34
35
  var HELP = `
35
- skilllib \u2014 one library of agent skills (Claude Code, Cursor, Codex, Zed), installed per project
36
+ skilllib \u2014 one library of agent skills (Claude Code, Cursor, Codex, Zed, Grok), installed per project
36
37
 
37
38
  skilllib Open the interactive app (run it from anywhere)
38
39
 
39
40
  Set up:
40
41
  skilllib scan [folder...] Add folders that contain your projects and scan them
41
42
  skilllib folders [add|remove] Show or change your project folders
42
- skilllib harnesses [id...] Show or set the agents you use (claude-code cursor codex zed)
43
+ skilllib harnesses [id...] Show or set the agents you use (claude-code cursor codex zed grok)
43
44
  skilllib import <dir>... Add skill folders to the library (--force replaces)
44
45
  skilllib import --global Copy your global skills (every agent's folder) into the library
45
46
  skilllib global [keep|unkeep <name>...] Your global skills; mark ones you keep global on purpose
47
+ skilllib global move <name>... --to <repo>...
48
+ Load global skills only in those repos (by path or project name)
46
49
 
47
50
  In a project (a git repo or a folder with skilllib.json; never your home folder):
48
51
  skilllib status This project's skills, which agents load them, and issues
@@ -65,6 +68,7 @@ Library:
65
68
 
66
69
  Health:
67
70
  skilllib doctor [--fix] Broken links, duplicates, out-of-date projects
71
+ skilllib apply <id> [choice] Apply one issue's fix, or the choice you pick (number or label)
68
72
  skilllib restore [name] Restore something skilllib moved out of the way
69
73
  skilllib unhide <path> Show a hidden project again
70
74
 
@@ -73,7 +77,7 @@ Agents:
73
77
  Teach your agents to use skilllib, so you can ask them
74
78
  "which skills can you use here?" in any repo
75
79
  --json Machine-readable output (status list show projects outdated
76
- usage doctor add remove sync update import agent-skill)
80
+ usage doctor apply add remove sync update import global move agent-skill)
77
81
 
78
82
  Options: --force (overwrite local edits) --allow-tracked (link into git-tracked skill folders) --days N
79
83
  `.trim();
@@ -92,10 +96,10 @@ async function main() {
92
96
  if (!["--version", "-v", "version", "help", "--help", "-h"].includes(command ?? "")) refreshAgentSkill();
93
97
  switch (command) {
94
98
  case void 0:
95
- return process.stdin.isTTY && process.stdout.isTTY ? (await import("./tui-RU255WYX.js")).tui() : overview(args);
99
+ return process.stdin.isTTY && process.stdout.isTTY ? (await import("./tui-3LDZ5GOZ.js")).tui() : overview(args);
96
100
  case "ui":
97
101
  if (!process.stdin.isTTY || !process.stdout.isTTY) throw new Error("`skilllib ui` needs an interactive terminal. Agents and scripts: use `skilllib status --json`.");
98
- return (await import("./tui-RU255WYX.js")).tui();
102
+ return (await import("./tui-3LDZ5GOZ.js")).tui();
99
103
  case "status":
100
104
  return status(args);
101
105
  case "add":
@@ -144,6 +148,8 @@ async function main() {
144
148
  return restore(args);
145
149
  case "doctor":
146
150
  return doctor(args);
151
+ case "apply":
152
+ return apply(args);
147
153
  case "usage":
148
154
  return usage(args);
149
155
  case "agent-skill":
@@ -0,0 +1,222 @@
1
+ type HarnessId = "claude-code" | "cursor" | "codex" | "zed" | "grok";
2
+
3
+ type AgentSkillState = "installed" | "outdated" | "missing";
4
+
5
+ /**
6
+ * Whether a skill folder is shared through git:
7
+ * - committed: tracked and unchanged, so teammates get it
8
+ * - changed: tracked, with uncommitted edits or new files
9
+ * - new: not tracked yet, but not ignored (shows in `git status`)
10
+ * - ignored: matched by .gitignore, so it only exists on this machine
11
+ */
12
+ type GitState = "committed" | "changed" | "new" | "ignored";
13
+
14
+ type SkillState = "ok" | "update available" | "edited locally" | "edited locally, update available" | "folder missing" | "not in library" | "untracked copy of library skill" | "untracked, differs from library" | "local only" | "repo skill" | "repo skill, in library" | "repo skill, differs from library" | "from npx skills";
15
+ type Change = {
16
+ name: string;
17
+ /** reset: back to the version it had; its local edits were overwritten (and backed up, see `backedUp`). */
18
+ action: "installed" | "updated" | "reset" | "removed" | "skipped";
19
+ reason?: string;
20
+ from?: number;
21
+ to?: number;
22
+ /** Harness folders a link couldn't be written to because git tracks them. */
23
+ blocked?: string[];
24
+ /** Harness folders git tracks, left without a link because git doesn't share the real copy (teammates would get a broken link). */
25
+ uncommitted?: string[];
26
+ /** Where overwritten local edits went (~/.skilllib/edit-backup/…); `skilllib restore` puts them back. */
27
+ backedUp?: string;
28
+ };
29
+
30
+ /**
31
+ * Where a skill Claude Code can load comes from.
32
+ * - global: a real folder in ~/.claude/skills (you, or a tool, copied it there)
33
+ * - skills.sh: a symlink into ~/.agents/skills, installed by `npx skills`
34
+ * - claude.ai: synced from your claude.ai account
35
+ * - plugin: shipped inside an enabled Claude Code plugin
36
+ * - built-in: bundled with an agent (Cursor's ~/.cursor/skills-cursor, Grok's ~/.grok/bundled/skills)
37
+ * - system: a machine-wide folder an admin manages (/etc/codex/skills)
38
+ * - skilllib: skilllib's own skill, which `skilllib agent-skill install` puts in your global folders
39
+ */
40
+ type SourceKind = "global" | "skills.sh" | "claude.ai" | "plugin" | "built-in" | "system" | "skilllib";
41
+
42
+ /**
43
+ * - library: added from your skills with skilllib (pinned in skilllib.json)
44
+ * - repo: the team's: committed to git (any skill folder), or in .agents/skills
45
+ * - local: only on this machine: not committed, not managed by skilllib
46
+ */
47
+ type ProjectSource = "library" | "repo" | "local";
48
+ /** The repo's own skills (or its subfolders') that share every attribute. */
49
+ type StatusSkillGroup = {
50
+ source: ProjectSource;
51
+ skills: string[];
52
+ /** Folder with the real copy, when it isn't .claude/skills. */
53
+ dir?: string;
54
+ version?: number;
55
+ /** Only when it isn't "ok". */
56
+ state?: SkillState;
57
+ /** Newer library version, when there is one. */
58
+ latest?: number;
59
+ git?: GitState;
60
+ /** Only when some of your agents don't load it here. */
61
+ agents?: HarnessId[];
62
+ };
63
+ /** Global skills that come from the same place and load in the same agents. */
64
+ type StatusGlobalGroup = {
65
+ source: SourceKind;
66
+ /** e.g. "railway@claude-plugins-official", "vercel-labs/agent-skills", "~/.claude/skills". */
67
+ from: string;
68
+ agents: HarnessId[];
69
+ skills: string[];
70
+ };
71
+ /**
72
+ * Problems skilllib found here or in your global skills that share a cause and remedy: a `fix` is a
73
+ * safe repair (`skilllib doctor --fix` runs it); `choices` need the user to decide.
74
+ * `skilllib apply <id> [choice]` applies either, one problem at a time.
75
+ */
76
+ type StatusIssue = {
77
+ problems: string[];
78
+ /** One per problem, in the same order: what `skilllib apply` takes. */
79
+ ids: string[];
80
+ detail: string;
81
+ fix?: string;
82
+ choices?: string[];
83
+ };
84
+ /** `skilllib status --json`: everything your agents can use in this repo. */
85
+ type StatusJson = {
86
+ project: string;
87
+ /** The repo's top-level files and folders (folders end in "/"), so an agent can read the right ones in one step. */
88
+ files: string[];
89
+ agents: HarnessId[];
90
+ skills: StatusSkillGroup[];
91
+ /** Skills in subfolders (monorepo packages), always with their `dir`: agents load them only when they work there. */
92
+ nested?: StatusSkillGroup[];
93
+ /** Skills that load in every repo, as this one loads them (its .claude/settings can turn a plugin on or off). */
94
+ global: StatusGlobalGroup[];
95
+ issues: StatusIssue[];
96
+ /** Claude Code uses in this repo per skill, when there were any. */
97
+ usesHere?: Record<string, number>;
98
+ };
99
+ /** `skilllib list --json`: your library; inside a repo, split into what it has and what it could add. */
100
+ type ListJson = {
101
+ /** Library skills the current project already has (names only). */
102
+ inThisProject?: string[];
103
+ /** The rest, with what's needed to choose: description, and the projects that use it. */
104
+ skills: {
105
+ name: string;
106
+ description: string;
107
+ projects?: string[];
108
+ }[];
109
+ };
110
+ /** `skilllib show <name> --json` */
111
+ type ShowJson = {
112
+ name: string;
113
+ description: string;
114
+ path: string;
115
+ /** Newest version in your library. */
116
+ latest: number | null;
117
+ /** Where it came from, e.g. a plugin or an `npx skills` repo; "" when unknown. */
118
+ origin: string;
119
+ /** Projects that have it in their skilllib.json. */
120
+ projects: string[];
121
+ /** The whole SKILL.md. */
122
+ skillMd: string;
123
+ };
124
+ /** `skilllib projects --json` */
125
+ type ProjectsJson = {
126
+ name: string;
127
+ path: string;
128
+ skills: {
129
+ name: string;
130
+ managed: boolean;
131
+ state: SkillState;
132
+ version: number | null;
133
+ latest: number | null;
134
+ }[];
135
+ }[];
136
+ /** One skill that `add`, `remove`, `sync` or `update` changed or skipped. */
137
+ type ChangeJson = Change & {
138
+ /** Where an installed, updated or reset skill now is: the real copy first, then its links. */
139
+ dirs?: string[];
140
+ };
141
+ /** `skilllib add|remove --json`, and `sync|update --json` without --all. */
142
+ type ChangesJson = ChangeJson[];
143
+ /** `skilllib sync|update --all --json`: the changes in each project. */
144
+ type AllChangesJson = {
145
+ project: string;
146
+ path: string;
147
+ changes: ChangeJson[];
148
+ }[];
149
+ /** `skilllib outdated [--all] --json` */
150
+ type OutdatedJson = {
151
+ project: string;
152
+ path: string;
153
+ skill: string;
154
+ installed: number;
155
+ latest: number;
156
+ state: SkillState;
157
+ }[];
158
+ /** `skilllib import <dir>... --json` */
159
+ type ImportJson = {
160
+ path: string;
161
+ /** Missing when the folder has no SKILL.md. */
162
+ name?: string;
163
+ status: "added" | "updated" | "unchanged" | "exists" | "no SKILL.md";
164
+ }[];
165
+ /** `skilllib doctor [--fix] --json` */
166
+ type DoctorJson = {
167
+ id: string;
168
+ severity: "problem" | "suggestion";
169
+ title: string;
170
+ detail: string;
171
+ /** A safe repair; `doctor --fix` runs it. */
172
+ fix?: string;
173
+ /** Fixes that need a decision: `skilllib apply <id> <n>` runs the nth (from 1). */
174
+ choices?: string[];
175
+ /** With --fix: what running `fix` did. */
176
+ fixed?: {
177
+ ok: boolean;
178
+ message: string;
179
+ };
180
+ }[];
181
+ /** `skilllib apply <issue-id> [choice] --json` */
182
+ type ApplyJson = {
183
+ id: string;
184
+ applied: string;
185
+ ok: boolean;
186
+ message: string;
187
+ };
188
+ /** `skilllib global move <name>... --to <repo>... --json`: one entry per skill. */
189
+ type GlobalMoveJson = {
190
+ skill: string;
191
+ /** Added to every repo and no longer global. When false, it still loads globally and `reason` says why. */
192
+ moved: boolean;
193
+ reason?: string;
194
+ projects: {
195
+ project: string;
196
+ path: string;
197
+ change: ChangeJson;
198
+ }[];
199
+ }[];
200
+ /** `skilllib usage [--days N] --json` */
201
+ type UsageJson = {
202
+ usageDays: number;
203
+ source: "Claude Code transcripts";
204
+ skills: {
205
+ skill: string;
206
+ uses: number;
207
+ lastUsed: string;
208
+ projects: string[];
209
+ inLibrary: boolean;
210
+ }[];
211
+ unusedLibrarySkills: string[];
212
+ };
213
+ /** `skilllib agent-skill [install|remove] --json` */
214
+ type AgentSkillJson = {
215
+ state: AgentSkillState;
216
+ /** Where it's installed (or would be). Not set after `remove`. */
217
+ dirs?: string[];
218
+ /** After `remove`: the folders it was removed from. */
219
+ removed?: string[];
220
+ };
221
+
222
+ export type { AgentSkillJson, AgentSkillState, AllChangesJson, ApplyJson, ChangeJson, ChangesJson, DoctorJson, GitState, GlobalMoveJson, HarnessId, ImportJson, ListJson, OutdatedJson, ProjectSource, ProjectsJson, ShowJson, SkillState, SourceKind, StatusGlobalGroup, StatusIssue, StatusJson, StatusSkillGroup, UsageJson };
package/dist/json.d.ts ADDED
@@ -0,0 +1,222 @@
1
+ type HarnessId = "claude-code" | "cursor" | "codex" | "zed" | "grok";
2
+
3
+ type AgentSkillState = "installed" | "outdated" | "missing";
4
+
5
+ /**
6
+ * Whether a skill folder is shared through git:
7
+ * - committed: tracked and unchanged, so teammates get it
8
+ * - changed: tracked, with uncommitted edits or new files
9
+ * - new: not tracked yet, but not ignored (shows in `git status`)
10
+ * - ignored: matched by .gitignore, so it only exists on this machine
11
+ */
12
+ type GitState = "committed" | "changed" | "new" | "ignored";
13
+
14
+ type SkillState = "ok" | "update available" | "edited locally" | "edited locally, update available" | "folder missing" | "not in library" | "untracked copy of library skill" | "untracked, differs from library" | "local only" | "repo skill" | "repo skill, in library" | "repo skill, differs from library" | "from npx skills";
15
+ type Change = {
16
+ name: string;
17
+ /** reset: back to the version it had; its local edits were overwritten (and backed up, see `backedUp`). */
18
+ action: "installed" | "updated" | "reset" | "removed" | "skipped";
19
+ reason?: string;
20
+ from?: number;
21
+ to?: number;
22
+ /** Harness folders a link couldn't be written to because git tracks them. */
23
+ blocked?: string[];
24
+ /** Harness folders git tracks, left without a link because git doesn't share the real copy (teammates would get a broken link). */
25
+ uncommitted?: string[];
26
+ /** Where overwritten local edits went (~/.skilllib/edit-backup/…); `skilllib restore` puts them back. */
27
+ backedUp?: string;
28
+ };
29
+
30
+ /**
31
+ * Where a skill Claude Code can load comes from.
32
+ * - global: a real folder in ~/.claude/skills (you, or a tool, copied it there)
33
+ * - skills.sh: a symlink into ~/.agents/skills, installed by `npx skills`
34
+ * - claude.ai: synced from your claude.ai account
35
+ * - plugin: shipped inside an enabled Claude Code plugin
36
+ * - built-in: bundled with an agent (Cursor's ~/.cursor/skills-cursor, Grok's ~/.grok/bundled/skills)
37
+ * - system: a machine-wide folder an admin manages (/etc/codex/skills)
38
+ * - skilllib: skilllib's own skill, which `skilllib agent-skill install` puts in your global folders
39
+ */
40
+ type SourceKind = "global" | "skills.sh" | "claude.ai" | "plugin" | "built-in" | "system" | "skilllib";
41
+
42
+ /**
43
+ * - library: added from your skills with skilllib (pinned in skilllib.json)
44
+ * - repo: the team's: committed to git (any skill folder), or in .agents/skills
45
+ * - local: only on this machine: not committed, not managed by skilllib
46
+ */
47
+ type ProjectSource = "library" | "repo" | "local";
48
+ /** The repo's own skills (or its subfolders') that share every attribute. */
49
+ type StatusSkillGroup = {
50
+ source: ProjectSource;
51
+ skills: string[];
52
+ /** Folder with the real copy, when it isn't .claude/skills. */
53
+ dir?: string;
54
+ version?: number;
55
+ /** Only when it isn't "ok". */
56
+ state?: SkillState;
57
+ /** Newer library version, when there is one. */
58
+ latest?: number;
59
+ git?: GitState;
60
+ /** Only when some of your agents don't load it here. */
61
+ agents?: HarnessId[];
62
+ };
63
+ /** Global skills that come from the same place and load in the same agents. */
64
+ type StatusGlobalGroup = {
65
+ source: SourceKind;
66
+ /** e.g. "railway@claude-plugins-official", "vercel-labs/agent-skills", "~/.claude/skills". */
67
+ from: string;
68
+ agents: HarnessId[];
69
+ skills: string[];
70
+ };
71
+ /**
72
+ * Problems skilllib found here or in your global skills that share a cause and remedy: a `fix` is a
73
+ * safe repair (`skilllib doctor --fix` runs it); `choices` need the user to decide.
74
+ * `skilllib apply <id> [choice]` applies either, one problem at a time.
75
+ */
76
+ type StatusIssue = {
77
+ problems: string[];
78
+ /** One per problem, in the same order: what `skilllib apply` takes. */
79
+ ids: string[];
80
+ detail: string;
81
+ fix?: string;
82
+ choices?: string[];
83
+ };
84
+ /** `skilllib status --json`: everything your agents can use in this repo. */
85
+ type StatusJson = {
86
+ project: string;
87
+ /** The repo's top-level files and folders (folders end in "/"), so an agent can read the right ones in one step. */
88
+ files: string[];
89
+ agents: HarnessId[];
90
+ skills: StatusSkillGroup[];
91
+ /** Skills in subfolders (monorepo packages), always with their `dir`: agents load them only when they work there. */
92
+ nested?: StatusSkillGroup[];
93
+ /** Skills that load in every repo, as this one loads them (its .claude/settings can turn a plugin on or off). */
94
+ global: StatusGlobalGroup[];
95
+ issues: StatusIssue[];
96
+ /** Claude Code uses in this repo per skill, when there were any. */
97
+ usesHere?: Record<string, number>;
98
+ };
99
+ /** `skilllib list --json`: your library; inside a repo, split into what it has and what it could add. */
100
+ type ListJson = {
101
+ /** Library skills the current project already has (names only). */
102
+ inThisProject?: string[];
103
+ /** The rest, with what's needed to choose: description, and the projects that use it. */
104
+ skills: {
105
+ name: string;
106
+ description: string;
107
+ projects?: string[];
108
+ }[];
109
+ };
110
+ /** `skilllib show <name> --json` */
111
+ type ShowJson = {
112
+ name: string;
113
+ description: string;
114
+ path: string;
115
+ /** Newest version in your library. */
116
+ latest: number | null;
117
+ /** Where it came from, e.g. a plugin or an `npx skills` repo; "" when unknown. */
118
+ origin: string;
119
+ /** Projects that have it in their skilllib.json. */
120
+ projects: string[];
121
+ /** The whole SKILL.md. */
122
+ skillMd: string;
123
+ };
124
+ /** `skilllib projects --json` */
125
+ type ProjectsJson = {
126
+ name: string;
127
+ path: string;
128
+ skills: {
129
+ name: string;
130
+ managed: boolean;
131
+ state: SkillState;
132
+ version: number | null;
133
+ latest: number | null;
134
+ }[];
135
+ }[];
136
+ /** One skill that `add`, `remove`, `sync` or `update` changed or skipped. */
137
+ type ChangeJson = Change & {
138
+ /** Where an installed, updated or reset skill now is: the real copy first, then its links. */
139
+ dirs?: string[];
140
+ };
141
+ /** `skilllib add|remove --json`, and `sync|update --json` without --all. */
142
+ type ChangesJson = ChangeJson[];
143
+ /** `skilllib sync|update --all --json`: the changes in each project. */
144
+ type AllChangesJson = {
145
+ project: string;
146
+ path: string;
147
+ changes: ChangeJson[];
148
+ }[];
149
+ /** `skilllib outdated [--all] --json` */
150
+ type OutdatedJson = {
151
+ project: string;
152
+ path: string;
153
+ skill: string;
154
+ installed: number;
155
+ latest: number;
156
+ state: SkillState;
157
+ }[];
158
+ /** `skilllib import <dir>... --json` */
159
+ type ImportJson = {
160
+ path: string;
161
+ /** Missing when the folder has no SKILL.md. */
162
+ name?: string;
163
+ status: "added" | "updated" | "unchanged" | "exists" | "no SKILL.md";
164
+ }[];
165
+ /** `skilllib doctor [--fix] --json` */
166
+ type DoctorJson = {
167
+ id: string;
168
+ severity: "problem" | "suggestion";
169
+ title: string;
170
+ detail: string;
171
+ /** A safe repair; `doctor --fix` runs it. */
172
+ fix?: string;
173
+ /** Fixes that need a decision: `skilllib apply <id> <n>` runs the nth (from 1). */
174
+ choices?: string[];
175
+ /** With --fix: what running `fix` did. */
176
+ fixed?: {
177
+ ok: boolean;
178
+ message: string;
179
+ };
180
+ }[];
181
+ /** `skilllib apply <issue-id> [choice] --json` */
182
+ type ApplyJson = {
183
+ id: string;
184
+ applied: string;
185
+ ok: boolean;
186
+ message: string;
187
+ };
188
+ /** `skilllib global move <name>... --to <repo>... --json`: one entry per skill. */
189
+ type GlobalMoveJson = {
190
+ skill: string;
191
+ /** Added to every repo and no longer global. When false, it still loads globally and `reason` says why. */
192
+ moved: boolean;
193
+ reason?: string;
194
+ projects: {
195
+ project: string;
196
+ path: string;
197
+ change: ChangeJson;
198
+ }[];
199
+ }[];
200
+ /** `skilllib usage [--days N] --json` */
201
+ type UsageJson = {
202
+ usageDays: number;
203
+ source: "Claude Code transcripts";
204
+ skills: {
205
+ skill: string;
206
+ uses: number;
207
+ lastUsed: string;
208
+ projects: string[];
209
+ inLibrary: boolean;
210
+ }[];
211
+ unusedLibrarySkills: string[];
212
+ };
213
+ /** `skilllib agent-skill [install|remove] --json` */
214
+ type AgentSkillJson = {
215
+ state: AgentSkillState;
216
+ /** Where it's installed (or would be). Not set after `remove`. */
217
+ dirs?: string[];
218
+ /** After `remove`: the folders it was removed from. */
219
+ removed?: string[];
220
+ };
221
+
222
+ export type { AgentSkillJson, AgentSkillState, AllChangesJson, ApplyJson, ChangeJson, ChangesJson, DoctorJson, GitState, GlobalMoveJson, HarnessId, ImportJson, ListJson, OutdatedJson, ProjectSource, ProjectsJson, ShowJson, SkillState, SourceKind, StatusGlobalGroup, StatusIssue, StatusJson, StatusSkillGroup, UsageJson };