ai-agent-skills 3.4.2 → 3.4.4

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/README.md CHANGED
@@ -5,10 +5,10 @@ My curated agent skills library.
5
5
  There are a lot of skills now. These are the ones I actually keep around.
6
6
 
7
7
  <!-- GENERATED:library-stats:start -->
8
- - 35 skills total
8
+ - 36 skills total
9
9
  - 10 shelves
10
10
  - 11 house copies
11
- - 24 cataloged upstream
11
+ - 25 cataloged upstream
12
12
  <!-- GENERATED:library-stats:end -->
13
13
 
14
14
  The point is not to be a registry. The point is to be a bookshelf.
@@ -97,7 +97,7 @@ These are the shelves. They are the product.
97
97
  <!-- GENERATED:shelf-table:start -->
98
98
  | Shelf | Skills | What it covers |
99
99
  | --- | --- | --- |
100
- | Frontend | 4 | Interface systems, web product craft, and frontend execution. |
100
+ | Frontend | 5 | Interface systems, web product craft, and frontend execution. |
101
101
  | Backend | 3 | Infra, tooling, application architecture, and codebase depth. |
102
102
  | Docs | 6 | Documents, specs, file handling, and long-form output. |
103
103
  | Testing | 2 | Review, QA, regression work, and keeping product quality sharp. |
@@ -171,6 +171,7 @@ Current source mix:
171
171
  | `wshobson/agents` | 4 |
172
172
  | `MoizIbnYousaf/Ai-Agent-Skills` | 3 |
173
173
  | `emilkowalski/skill` | 1 |
174
+ | `raphaelsalaja/userinterface-wiki` | 1 |
174
175
  | `shadcn-ui/ui` | 1 |
175
176
  <!-- GENERATED:source-table:end -->
176
177
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-agent-skills",
3
- "version": "3.4.2",
3
+ "version": "3.4.4",
4
4
  "description": "My curated agent skills library, with a CLI that installs from any source.",
5
5
  "main": "cli.js",
6
6
  "bin": {
package/skills.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
- "version": "3.4.2",
3
- "updated": "2026-03-21T00:00:00Z",
4
- "total": 35,
2
+ "version": "3.4.4",
3
+ "updated": "2026-03-25T00:00:00Z",
4
+ "total": 36,
5
5
  "workAreas": [
6
6
  {
7
7
  "id": "frontend",
@@ -1054,6 +1054,34 @@
1054
1054
  "labels": [],
1055
1055
  "addedDate": "2026-03-21",
1056
1056
  "path": ""
1057
+ },
1058
+ {
1059
+ "name": "userinterface-wiki",
1060
+ "description": "UI/UX best practices for web interfaces. Use when reviewing animations, CSS, audio, typography, UX patterns, prefetching, or icon implementations. Covers 11 categories from animation principles to typography. Outputs file:line findings.",
1061
+ "category": "development",
1062
+ "workArea": "frontend",
1063
+ "branch": "Frontend (Community)",
1064
+ "author": "raphaelsalaja",
1065
+ "source": "raphaelsalaja/userinterface-wiki",
1066
+ "license": "MIT",
1067
+ "tier": "upstream",
1068
+ "distribution": "live",
1069
+ "vendored": false,
1070
+ "installSource": "raphaelsalaja/userinterface-wiki/skills",
1071
+ "tags": [],
1072
+ "featured": false,
1073
+ "verified": false,
1074
+ "origin": "curated",
1075
+ "trust": "listed",
1076
+ "syncMode": "live",
1077
+ "sourceUrl": "https://github.com/raphaelsalaja/userinterface-wiki/tree/main/skills",
1078
+ "whyHere": "High-signal UI/UX review skill for interface polish, implementation critique, and stronger frontend craft.",
1079
+ "lastVerified": "",
1080
+ "notes": "",
1081
+ "labels": [],
1082
+ "addedDate": "2026-03-25",
1083
+ "lastCurated": "2026-03-25T00:00:00Z",
1084
+ "path": ""
1057
1085
  }
1058
1086
  ]
1059
1087
  }
package/tui/index.mjs CHANGED
@@ -245,22 +245,6 @@ function getReservedRows(screen, viewport, {showInspector = false} = {}) {
245
245
  return base + screenExtra + inspectorExtra;
246
246
  }
247
247
 
248
- function getVisibleHomeSectionIndices(sectionCount, activeIndex, viewport) {
249
- if (sectionCount <= 0) return [];
250
- const active = clamp(activeIndex, 0, sectionCount - 1);
251
- const visible = new Set([active]);
252
- const limit = viewport.micro ? 3 : viewport.compact ? 3 : 5;
253
-
254
- for (let offset = 1; visible.size < Math.min(limit, sectionCount); offset += 1) {
255
- if (active + offset < sectionCount) visible.add(active + offset);
256
- if (visible.size >= Math.min(limit, sectionCount)) break;
257
- if (active - offset >= 0) visible.add(active - offset);
258
- if (active + offset >= sectionCount && active - offset < 0) break;
259
- }
260
-
261
- return Array.from(visible).sort((left, right) => left - right);
262
- }
263
-
264
248
  function fitText(text, maxLength) {
265
249
  const value = String(text || '');
266
250
  if (value.length <= maxLength) return value;
@@ -701,137 +685,6 @@ function ShelfStrip({items, selectedIndex, columns, mode = 'default', active = t
701
685
  `;
702
686
  }
703
687
 
704
- function CompactShelfPreview({title, subtitle, active, summary, compact = false}) {
705
- return html`
706
- <${Box} marginTop=${compact ? 0 : 1} marginBottom=${compact ? 0 : 1} flexDirection="column">
707
- <${Text} bold=${active} color=${active ? COLORS.text : COLORS.muted}>
708
- ${active ? '› ' : '· '}${title}
709
- <//>
710
- ${compact ? null : html`<${Text} color=${COLORS.border}>${compactText(subtitle, 120)}<//>`}
711
- <${Text} color=${COLORS.muted}>${compactText(summary, 120)}<//>
712
- ${compact ? null : html`<${Text} color=${COLORS.border}>${'─'.repeat(72)}<//>`}
713
- <//>
714
- `;
715
- }
716
-
717
- function PosterSectionLead({item, mode, columns, viewport = null}) {
718
- if (!item) return null;
719
-
720
- const profile = viewport || getViewportProfile({columns, rows: 40});
721
- const wide = columns >= 108 && !profile.compact;
722
- const introLabel = mode === 'areas' ? 'Shelf focus' : 'Source focus';
723
- const actionLabel = mode === 'areas' ? 'Open this shelf' : 'Open this publisher';
724
- const dividerWidth = Math.max(28, Math.min(columns - 4, wide ? 84 : 56));
725
- const contextLine = compactText((item.chips || []).join(' · '), Math.max(32, columns - 4));
726
- const sampleLines = (item.sampleLines || []).slice(0, wide ? 2 : 1);
727
- const description = compactText(item.description || '', Math.max(42, wide ? Math.floor(columns * 0.55) : columns - 4));
728
- const metaLine = compactText(
729
- [item.count, item.footerLeft].filter(Boolean).join(' · '),
730
- Math.max(32, columns - 4)
731
- );
732
-
733
- return html`
734
- <${Box} flexDirection="column" marginTop=${1} marginBottom=${1}>
735
- <${Text} color=${COLORS.accentSoft}>${introLabel}<//>
736
- <${Box} flexDirection=${wide ? 'row' : 'column'} marginTop=${1}>
737
- <${Box} width=${wide ? Math.max(42, Math.floor(columns * 0.56)) : undefined} marginRight=${wide ? 3 : 0} flexDirection="column">
738
- <${Text} bold color=${COLORS.text}>${item.title}<//>
739
- ${description ? html`<${Text} color=${COLORS.muted}>${description}<//>` : null}
740
- ${metaLine ? html`<${Text} color=${COLORS.border}>${metaLine}<//>` : null}
741
- <//>
742
- <${Box} flexDirection="column" marginTop=${wide ? 0 : 1}>
743
- ${contextLine ? html`<${Text} color=${COLORS.accent}>${contextLine}<//>` : null}
744
- ${sampleLines.map((line, index) => html`
745
- <${Text} key=${`${line}-${index}`} color=${COLORS.text}>
746
- ◆ ${compactText(line, Math.max(36, wide ? Math.floor(columns * 0.36) : columns - 4))}
747
- <//>
748
- `)}
749
- <${Text} color=${COLORS.border}>${actionLabel} · Enter<//>
750
- <//>
751
- <//>
752
- <${Text} color=${COLORS.border}>${'─'.repeat(dividerWidth)}<//>
753
- <//>
754
- `;
755
- }
756
-
757
- function PosterSectionPreview({item, selected = false, viewport = null, columns = 80}) {
758
- if (!item) return null;
759
-
760
- const profile = viewport || getViewportProfile({columns, rows: 40});
761
- const supportingLine = compactText(
762
- item.sampleLines?.[0] || item.footerLeft || item.description || '',
763
- Math.max(34, columns - 10)
764
- );
765
- const detailLine = compactText(
766
- item.footerLeft || item.description || '',
767
- Math.max(28, columns - 10)
768
- );
769
-
770
- return html`
771
- <${Box} flexDirection="column" marginBottom=${profile.micro ? 0 : 1}>
772
- <${Box} justifyContent="space-between">
773
- <${Text} bold=${selected} color=${selected ? COLORS.text : COLORS.muted}>
774
- ${selected ? '◆ ' : '· '}${item.title}
775
- <//>
776
- ${item.count ? html`<${Text} color=${selected ? COLORS.accent : COLORS.border}>${item.count}<//>` : null}
777
- <//>
778
- ${item.description
779
- ? html`<${Text} color=${COLORS.border}>${compactText(item.description, Math.max(34, columns - 6))}<//>`
780
- : null}
781
- ${supportingLine
782
- ? html`<${Text} color=${selected ? COLORS.text : COLORS.muted}>${supportingLine}<//>`
783
- : null}
784
- ${profile.micro
785
- ? null
786
- : html`<${Text} color=${COLORS.border}>${detailLine}<//>`}
787
- <//>
788
- `;
789
- }
790
-
791
- function PosterHomeView({rootMode, items, selectedIndex, columns, viewport = null}) {
792
- const profile = viewport || getViewportProfile({columns, rows: 40});
793
- const safeIndex = clamp(selectedIndex, 0, Math.max(0, items.length - 1));
794
- const lead = items[safeIndex] || items[0];
795
- const visibleIndices = getVisibleHomeSectionIndices(items.length, safeIndex, profile);
796
- const minVisibleIndex = visibleIndices.length > 0 ? visibleIndices[0] : safeIndex;
797
- const maxVisibleIndex = visibleIndices.length > 0 ? visibleIndices[visibleIndices.length - 1] : safeIndex;
798
- const supportingIndices = visibleIndices.filter((index) => index !== safeIndex);
799
- const supportingItems = supportingIndices.map((index) => items[index]).filter(Boolean);
800
- const hiddenAbove = minVisibleIndex;
801
- const hiddenBelow = Math.max(0, items.length - maxVisibleIndex - 1);
802
- const supportTitle = rootMode === 'areas' ? 'Nearby shelves' : 'Nearby sources';
803
-
804
- return html`
805
- <${Box} flexDirection="column">
806
- ${hiddenAbove > 0
807
- ? html`<${Text} color=${COLORS.muted}>↑ ${hiddenAbove} more above<//>`
808
- : null}
809
- <${PosterSectionLead} item=${lead} mode=${rootMode} columns=${columns} viewport=${profile} />
810
- ${supportingItems.length > 0
811
- ? html`
812
- <${Box} flexDirection="column">
813
- <${Text} color=${COLORS.accentSoft}>${supportTitle}<//>
814
- <${Box} marginTop=${1} flexDirection="column">
815
- ${supportingItems.map((item) => html`
816
- <${PosterSectionPreview}
817
- key=${item.id}
818
- item=${item}
819
- selected=${false}
820
- viewport=${profile}
821
- columns=${columns}
822
- />
823
- `)}
824
- <//>
825
- <//>
826
- `
827
- : null}
828
- ${hiddenBelow > 0
829
- ? html`<${Text} color=${COLORS.muted}>↓ ${hiddenBelow} more below<//>`
830
- : null}
831
- <//>
832
- `;
833
- }
834
-
835
688
  function getHeroHighlights(section, selectedItem, selectedIndex = 0, limit = 4) {
836
689
  if (!section || !Array.isArray(section.items) || section.items.length === 0) return [];
837
690
  const around = [];
@@ -2650,6 +2503,8 @@ function App({catalog: initialCatalog, scope, agent, onExit}) {
2650
2503
  `;
2651
2504
  } else if (current.type === 'home') {
2652
2505
  const homeItems = rootMode === 'areas' ? getShelfItems(catalog) : getSourceItems(catalog);
2506
+ const selectedHomeItem = homeItems[selectedIndex] || homeItems[0];
2507
+ const showHomeInspector = !viewport.compact && Boolean(selectedHomeItem);
2653
2508
  body = html`
2654
2509
  <${Box} flexDirection="column">
2655
2510
  <${Header}
@@ -2663,13 +2518,29 @@ function App({catalog: initialCatalog, scope, agent, onExit}) {
2663
2518
  viewport=${viewport}
2664
2519
  />
2665
2520
  <${ModeTabs} rootMode=${rootMode} compact=${viewport.compact} />
2666
- <${PosterHomeView}
2667
- rootMode=${rootMode}
2668
- items=${homeItems}
2669
- selectedIndex=${selectedIndex}
2670
- columns=${columns}
2671
- viewport=${viewport}
2672
- />
2521
+ <${Box} marginTop=${1}>
2522
+ <${AtlasGrid}
2523
+ items=${homeItems}
2524
+ selectedIndex=${selectedIndex}
2525
+ columns=${columns}
2526
+ rows=${rows}
2527
+ reservedRows=${getReservedRows('home-grid', viewport, {showInspector: showHomeInspector})}
2528
+ compact=${viewport.compact}
2529
+ />
2530
+ <//>
2531
+ ${showHomeInspector
2532
+ ? html`
2533
+ <${Inspector}
2534
+ title=${selectedHomeItem.title}
2535
+ eyebrow=${rootMode === 'areas' ? 'Shelf' : 'Source'}
2536
+ lines=${[
2537
+ selectedHomeItem.description,
2538
+ ...(selectedHomeItem.sampleLines || []),
2539
+ ]}
2540
+ footer="Enter opens the focused tile"
2541
+ />
2542
+ `
2543
+ : null}
2673
2544
  <//>
2674
2545
  `;
2675
2546
  } else if (current.type === 'collection' && currentCollection) {
@@ -3099,7 +2970,6 @@ export const __test = {
3099
2970
  getAtlasTileHeight,
3100
2971
  formatPreviewLines,
3101
2972
  getViewportProfile,
3102
- getVisibleHomeSectionIndices,
3103
2973
  getReservedRows,
3104
2974
  getViewportState,
3105
2975
  };