@dealdeploy/skl 1.3.0 → 1.5.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/add-tui.ts CHANGED
@@ -202,7 +202,9 @@ export function createAddTui(renderer: CliRenderer, deps: AddTuiDeps) {
202
202
  renderer.keyInput.on("keypress", (key: KeyEvent) => {
203
203
  const prevCursor = cursor;
204
204
 
205
- switch (key.name) {
205
+ const navKey = (key.ctrl && { h: "left", j: "down", k: "up", l: "right" }[key.name]) || key.name;
206
+
207
+ switch (navKey) {
206
208
  case "j":
207
209
  case "down":
208
210
  if (cursor < skills.length - 1) cursor++;
package/lib.test.ts CHANGED
@@ -288,7 +288,7 @@ describe("parseRepoArg", () => {
288
288
  // ── buildAddArgs ────────────────────────────────────────────────────
289
289
 
290
290
  describe("buildAddArgs", () => {
291
- test("uses lock entry sourceUrl for remote skill with project agents", () => {
291
+ test("uses owner/repo/skillPath shorthand for remote skill with project agents", () => {
292
292
  const entry: LockEntry = {
293
293
  source: "owner/repo",
294
294
  sourceUrl: "https://github.com/owner/repo",
@@ -299,7 +299,7 @@ describe("buildAddArgs", () => {
299
299
  addToLock("myskill", entry);
300
300
 
301
301
  const args = buildAddArgs("/catalog", "myskill", false, ["claude-code", "roo"]);
302
- expect(args).toEqual(["add", "https://github.com/owner/repo", "--skill", "myskill", "-y", "--agent", "claude-code", "roo"]);
302
+ expect(args).toEqual(["add", "owner/repo/skills/myskill", "-y", "--agent", "claude-code", "roo"]);
303
303
  });
304
304
 
305
305
  test("global install does not pass --agent", () => {
@@ -315,6 +315,7 @@ describe("buildAddArgs", () => {
315
315
  const args = buildAddArgs("/catalog", "myskill", true, ["claude-code"]);
316
316
  expect(args).toContain("-g");
317
317
  expect(args).not.toContain("--agent");
318
+ expect(args).toContain("owner/repo/skills/myskill");
318
319
  });
319
320
 
320
321
  test("uses catalog path for hand-authored skill with project agents", () => {
@@ -326,6 +327,21 @@ describe("buildAddArgs", () => {
326
327
  const args = buildAddArgs("/my/catalog", "custom-skill", true);
327
328
  expect(args).toEqual(["add", "/my/catalog/custom-skill", "-y", "-g"]);
328
329
  });
330
+
331
+ test("uses subpath for nested skill paths", () => {
332
+ const entry: LockEntry = {
333
+ source: "owner/repo",
334
+ sourceUrl: "https://github.com/owner/repo",
335
+ skillPath: "skills/code-review",
336
+ treeSHA: "abc",
337
+ addedAt: "2026-01-01",
338
+ };
339
+ addToLock("code-review", entry);
340
+
341
+ const args = buildAddArgs("/catalog", "code-review", true);
342
+ expect(args).toEqual(["add", "owner/repo/skills/code-review", "-y", "-g"]);
343
+ expect(args).not.toContain("--skill");
344
+ });
329
345
  });
330
346
 
331
347
  // ── detectProjectAgents ─────────────────────────────────────────────
package/lib.ts CHANGED
@@ -172,7 +172,9 @@ export function buildAddArgs(
172
172
  ? ["--agent", ...projectAgents]
173
173
  : [];
174
174
  if (lockEntry) {
175
- const args = ["add", lockEntry.sourceUrl, "--skill", name, "-y", ...agentArgs];
175
+ // Use owner/repo/skillPath shorthand so the CLI narrows via subpath
176
+ const source = `${lockEntry.source}/${lockEntry.skillPath}`;
177
+ const args = ["add", source, "-y", ...agentArgs];
176
178
  if (isGlobal) args.push("-g");
177
179
  return args;
178
180
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dealdeploy/skl",
3
- "version": "1.3.0",
3
+ "version": "1.5.0",
4
4
  "description": "TUI skill manager for Claude Code agents",
5
5
  "module": "index.ts",
6
6
  "bin": {
package/tui.ts CHANGED
@@ -227,7 +227,7 @@ export function createTui(renderer: CliRenderer, deps: TuiDeps) {
227
227
  width: "100%",
228
228
  });
229
229
 
230
- type HeaderRef = { spacer: BoxRenderable | null; row: BoxRenderable; text: TextRenderable };
230
+ type HeaderRef = { spacer: BoxRenderable; row: BoxRenderable; text: TextRenderable };
231
231
  const headerRefs = new Map<number, HeaderRef>();
232
232
 
233
233
  type RowRefs = {
@@ -243,16 +243,13 @@ export function createTui(renderer: CliRenderer, deps: TuiDeps) {
243
243
  for (let di = 0; di < displayItems.length; di++) {
244
244
  const item = displayItems[di]!;
245
245
  if (item.type === "header") {
246
- let spacer: BoxRenderable | null = null;
247
- if (di > 0) {
248
- spacer = new BoxRenderable(renderer, {
249
- id: `spacer-${di}`,
250
- height: 1,
251
- width: "100%",
252
- backgroundColor: C.rowBg,
253
- });
254
- scrollBox.add(spacer);
255
- }
246
+ const spacer = new BoxRenderable(renderer, {
247
+ id: `spacer-${di}`,
248
+ height: 1,
249
+ width: "100%",
250
+ backgroundColor: C.rowBg,
251
+ });
252
+ scrollBox.add(spacer);
256
253
  const hRow = new BoxRenderable(renderer, {
257
254
  id: `header-${di}`,
258
255
  flexDirection: "row",
@@ -368,7 +365,7 @@ export function createTui(renderer: CliRenderer, deps: TuiDeps) {
368
365
  const visible = visibleRepos.has(item.repo);
369
366
  const ref = headerRefs.get(di)!;
370
367
  ref.row.visible = visible;
371
- if (ref.spacer) ref.spacer.visible = visible;
368
+ ref.spacer.visible = visible;
372
369
  } else {
373
370
  const visible = matchingSkills.has(item.skillIndex);
374
371
  rows[item.skillIndex]!.row.visible = visible;
@@ -484,13 +481,13 @@ export function createTui(renderer: CliRenderer, deps: TuiDeps) {
484
481
  const ref = headerRefs.get(di)!;
485
482
  if (ref.row.visible) {
486
483
  visibleBefore++;
487
- if (ref.spacer?.visible) visibleBefore++;
484
+ if (ref.spacer.visible) visibleBefore++;
488
485
  }
489
486
  } else {
490
487
  if (rows[item.skillIndex]!.row.visible) visibleBefore++;
491
488
  }
492
489
  }
493
- scrollBox.scrollTo(Math.max(0, visibleBefore + 1 - 2));
490
+ scrollBox.scrollTo(Math.max(0, visibleBefore + 2 - 2));
494
491
  }
495
492
  }
496
493
 
@@ -614,7 +611,7 @@ export function createTui(renderer: CliRenderer, deps: TuiDeps) {
614
611
  }
615
612
  return;
616
613
  }
617
- if (key.name === "down" || key.name === "return") {
614
+ if (key.name === "down" || key.name === "return" || (key.ctrl && key.name === "j")) {
618
615
  focusArea = "grid";
619
616
  refreshAll();
620
617
  ensureVisible();
@@ -634,7 +631,15 @@ export function createTui(renderer: CliRenderer, deps: TuiDeps) {
634
631
  // ── Grid-focused input ──
635
632
 
636
633
  if (key.name === "backspace") return;
637
- if (key.ctrl) return;
634
+ const ctrlNav: Record<string, string> = { h: "left", j: "down", k: "up", l: "right" };
635
+ let navKey = key.name;
636
+ if (key.ctrl) {
637
+ if (ctrlNav[key.name]) {
638
+ navKey = ctrlNav[key.name]!;
639
+ } else {
640
+ return;
641
+ }
642
+ }
638
643
 
639
644
  if (key.sequence === "q") {
640
645
  deps.onQuit();
@@ -664,7 +669,7 @@ export function createTui(renderer: CliRenderer, deps: TuiDeps) {
664
669
  }
665
670
 
666
671
  // ── Navigation & actions ──
667
- switch (key.name) {
672
+ switch (navKey) {
668
673
  case "down":
669
674
  if (cursor < filteredDisplayIndices.length - 1) cursor++;
670
675
  break;