@skillkit/tui 2.0.0 → 2.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.
- package/README.md +1 -1
- package/dist/index.d.ts +6 -6
- package/dist/index.js +138 -109
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -34,7 +34,7 @@ pnpm ui
|
|
|
34
34
|
- **Animated UI** - Smooth entrance animations and transitions
|
|
35
35
|
- **Browse Skills** - Explore skill repositories with search and filtering
|
|
36
36
|
- **Smart Recommendations** - AI-powered skill suggestions with match scores
|
|
37
|
-
- **Cross-Agent Translation** - Convert skills between
|
|
37
|
+
- **Cross-Agent Translation** - Convert skills between 32 agent formats
|
|
38
38
|
- **Team Collaboration** - Share and sync skills across teams
|
|
39
39
|
- **Responsive Design** - Adapts to any terminal size
|
|
40
40
|
|
package/dist/index.d.ts
CHANGED
|
@@ -8,6 +8,9 @@ interface SkillItem {
|
|
|
8
8
|
source?: string;
|
|
9
9
|
installs?: number;
|
|
10
10
|
enabled?: boolean;
|
|
11
|
+
quality?: number;
|
|
12
|
+
grade?: string;
|
|
13
|
+
warnings?: number;
|
|
11
14
|
}
|
|
12
15
|
interface RepoInfo {
|
|
13
16
|
source: string;
|
|
@@ -111,7 +114,7 @@ interface AgentLogo {
|
|
|
111
114
|
company: string;
|
|
112
115
|
}
|
|
113
116
|
/**
|
|
114
|
-
* All
|
|
117
|
+
* All 32 supported agents with monochromatic Unicode logos
|
|
115
118
|
*/
|
|
116
119
|
declare const AGENT_LOGOS: Record<string, AgentLogo>;
|
|
117
120
|
/**
|
|
@@ -367,13 +370,10 @@ declare function getDetectedAgents(state: AgentsState): AgentStatus[];
|
|
|
367
370
|
*/
|
|
368
371
|
declare function getAgentAdapter(type: AgentType): _skillkit_agents.AgentAdapter;
|
|
369
372
|
/**
|
|
370
|
-
* Total number of supported agents
|
|
373
|
+
* Total number of supported agents (derived from adapters)
|
|
371
374
|
*/
|
|
372
|
-
declare const TOTAL_AGENTS
|
|
375
|
+
declare const TOTAL_AGENTS: number;
|
|
373
376
|
|
|
374
|
-
/**
|
|
375
|
-
* Default popular repos - can be extended via config.marketplaceSources
|
|
376
|
-
*/
|
|
377
377
|
declare const DEFAULT_REPOS: RepoInfo[];
|
|
378
378
|
/**
|
|
379
379
|
* Marketplace state
|
package/dist/index.js
CHANGED
|
@@ -5,6 +5,7 @@ import { createRoot } from "@opentui/react";
|
|
|
5
5
|
// src/App.tsx
|
|
6
6
|
import { useState as useState15, useCallback as useCallback9, useEffect as useEffect13 } from "react";
|
|
7
7
|
import { useKeyboard as useKeyboard8 } from "@opentui/react";
|
|
8
|
+
import { exec } from "child_process";
|
|
8
9
|
|
|
9
10
|
// src/state/types.ts
|
|
10
11
|
var NAV_KEYS = {
|
|
@@ -155,6 +156,21 @@ var AGENT_LOGOS = {
|
|
|
155
156
|
"trae": { icon: "\u25C6", name: "Trae", company: "ByteDance" },
|
|
156
157
|
"antigravity": { icon: "\u229B", name: "Antigravity", company: "" },
|
|
157
158
|
"clawdbot": { icon: "\u27D0", name: "Clawdbot", company: "" },
|
|
159
|
+
"cline": { icon: "\u2295", name: "Cline", company: "" },
|
|
160
|
+
"codebuddy": { icon: "\u2297", name: "CodeBuddy", company: "" },
|
|
161
|
+
"commandcode": { icon: "\u2298", name: "CommandCode", company: "" },
|
|
162
|
+
"continue": { icon: "\u229E", name: "Continue", company: "" },
|
|
163
|
+
"crush": { icon: "\u229F", name: "Crush", company: "" },
|
|
164
|
+
"factory": { icon: "\u22A0", name: "Factory", company: "" },
|
|
165
|
+
"mcpjam": { icon: "\u22A1", name: "MCPJam", company: "" },
|
|
166
|
+
"mux": { icon: "\u22A2", name: "Mux", company: "" },
|
|
167
|
+
"neovate": { icon: "\u22A3", name: "Neovate", company: "" },
|
|
168
|
+
"openhands": { icon: "\u22A4", name: "OpenHands", company: "" },
|
|
169
|
+
"pi": { icon: "\u22A5", name: "Pi", company: "" },
|
|
170
|
+
"qoder": { icon: "\u22A6", name: "Qoder", company: "" },
|
|
171
|
+
"qwen": { icon: "\u22A7", name: "Qwen", company: "Alibaba" },
|
|
172
|
+
"vercel": { icon: "\u25B2", name: "Vercel", company: "Vercel" },
|
|
173
|
+
"zencoder": { icon: "\u22A9", name: "Zencoder", company: "" },
|
|
158
174
|
"universal": { icon: "\u25CF", name: "Universal", company: "" }
|
|
159
175
|
};
|
|
160
176
|
var symbols = {
|
|
@@ -525,7 +541,7 @@ function isNavKey(key) {
|
|
|
525
541
|
}
|
|
526
542
|
|
|
527
543
|
// src/state/skills.ts
|
|
528
|
-
import { findAllSkills } from "@skillkit/core";
|
|
544
|
+
import { findAllSkills, evaluateSkillDirectory, getQualityGrade } from "@skillkit/core";
|
|
529
545
|
import { rmSync } from "fs";
|
|
530
546
|
import { resolve, normalize } from "path";
|
|
531
547
|
function createSkillsState() {
|
|
@@ -539,12 +555,18 @@ function loadSkills(agentType) {
|
|
|
539
555
|
try {
|
|
540
556
|
const searchDirs = getSearchDirs(agentType);
|
|
541
557
|
const foundSkills = findAllSkills(searchDirs);
|
|
542
|
-
const skillItems = foundSkills.map((s) =>
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
558
|
+
const skillItems = foundSkills.map((s) => {
|
|
559
|
+
const quality = evaluateSkillDirectory(s.path);
|
|
560
|
+
return {
|
|
561
|
+
name: s.name,
|
|
562
|
+
description: s.description,
|
|
563
|
+
source: s.metadata?.source,
|
|
564
|
+
enabled: s.enabled,
|
|
565
|
+
quality: quality?.overall,
|
|
566
|
+
grade: quality ? getQualityGrade(quality.overall) : void 0,
|
|
567
|
+
warnings: quality?.warnings.length
|
|
568
|
+
};
|
|
569
|
+
});
|
|
548
570
|
return {
|
|
549
571
|
skills: skillItems,
|
|
550
572
|
loading: false,
|
|
@@ -635,44 +657,59 @@ function getDetectedAgents(state) {
|
|
|
635
657
|
function getAgentAdapter(type) {
|
|
636
658
|
return getAdapter2(type);
|
|
637
659
|
}
|
|
638
|
-
var TOTAL_AGENTS =
|
|
660
|
+
var TOTAL_AGENTS = getAllAdapters().length;
|
|
639
661
|
|
|
640
662
|
// src/state/marketplace.ts
|
|
641
663
|
import { detectProvider, loadConfig as loadConfig3, extractFrontmatter } from "@skillkit/core";
|
|
642
664
|
import { readFileSync as readFileSync2, existsSync, rmSync as rmSync2 } from "fs";
|
|
643
665
|
import { join as join2 } from "path";
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
666
|
+
|
|
667
|
+
// ../../marketplace/sources.json
|
|
668
|
+
var sources_default = {
|
|
669
|
+
$schema: "./sources-schema.json",
|
|
670
|
+
version: 1,
|
|
671
|
+
updatedAt: "2026-01-26",
|
|
672
|
+
description: "Curated skill repository sources - THE SINGLE SOURCE OF TRUTH",
|
|
673
|
+
sources: [
|
|
674
|
+
{ source: "anthropics/skills", name: "Anthropic Official", official: true },
|
|
675
|
+
{ source: "vercel-labs/agent-skills", name: "Vercel Labs", official: true },
|
|
676
|
+
{ source: "expo/skills", name: "Expo / React Native", official: true },
|
|
677
|
+
{ source: "remotion-dev/skills", name: "Remotion Video", official: true },
|
|
678
|
+
{ source: "supabase/agent-skills", name: "Supabase", official: true },
|
|
679
|
+
{ source: "stripe/ai", name: "Stripe Payments", official: true },
|
|
680
|
+
{ source: "ComposioHQ/awesome-claude-skills", name: "Composio Awesome" },
|
|
681
|
+
{ source: "travisvn/awesome-claude-skills", name: "Travis Awesome" },
|
|
682
|
+
{ source: "mhattingpete/claude-skills-marketplace", name: "Skills Marketplace" },
|
|
683
|
+
{ source: "coreyhaines31/marketingskills", name: "Marketing Skills" },
|
|
684
|
+
{ source: "obra/superpowers", name: "Superpowers TDD" },
|
|
685
|
+
{ source: "softaworks/agent-toolkit", name: "Softaworks Toolkit" },
|
|
686
|
+
{ source: "wshobson/agents", name: "Dev Patterns" },
|
|
687
|
+
{ source: "langgenius/dify", name: "Dify Frontend" },
|
|
688
|
+
{ source: "trailofbits/skills", name: "Trail of Bits Security" },
|
|
689
|
+
{ source: "better-auth/skills", name: "Better Auth" },
|
|
690
|
+
{ source: "onmax/nuxt-skills", name: "Nuxt / Vue" },
|
|
691
|
+
{ source: "hyf0/vue-skills", name: "Vue Best Practices" },
|
|
692
|
+
{ source: "jezweb/claude-skills", name: "Cloudflare / TanStack" },
|
|
693
|
+
{ source: "elysiajs/skills", name: "ElysiaJS / Bun" },
|
|
694
|
+
{ source: "kadajett/agent-nestjs-skills", name: "NestJS" },
|
|
695
|
+
{ source: "callstackincubator/agent-skills", name: "React Native" },
|
|
696
|
+
{ source: "cloudai-x/threejs-skills", name: "Three.js" },
|
|
697
|
+
{ source: "emalorenzo/three-agent-skills", name: "Three.js Advanced" },
|
|
698
|
+
{ source: "dimillian/skills", name: "SwiftUI iOS" },
|
|
699
|
+
{ source: "waynesutton/convexskills", name: "Convex Backend" },
|
|
700
|
+
{ source: "kepano/obsidian-skills", name: "Obsidian Notes" },
|
|
701
|
+
{ source: "jimliu/baoyu-skills", name: "Baoyu Tools" },
|
|
702
|
+
{ source: "giuseppe-trisciuoglio/developer-kit", name: "Shadcn / Radix" },
|
|
703
|
+
{ source: "openrouterteam/agent-skills", name: "OpenRouter SDK" },
|
|
704
|
+
{ source: "intellectronica/agent-skills", name: "Context7" }
|
|
705
|
+
]
|
|
706
|
+
};
|
|
707
|
+
|
|
708
|
+
// src/state/marketplace.ts
|
|
709
|
+
var DEFAULT_REPOS = sources_default.sources.map((s) => ({
|
|
710
|
+
source: s.source,
|
|
711
|
+
name: s.name
|
|
712
|
+
}));
|
|
676
713
|
function getMarketplaceRepos() {
|
|
677
714
|
try {
|
|
678
715
|
const config = loadConfig3();
|
|
@@ -991,17 +1028,10 @@ function Browse({ onNavigate, cols = 80, rows = 24 }) {
|
|
|
991
1028
|
const actualIdx = startIdx + idx;
|
|
992
1029
|
const selected = actualIdx === selectedIndex;
|
|
993
1030
|
const indicator = selected ? "\u25B8" : " ";
|
|
994
|
-
const
|
|
995
|
-
const
|
|
996
|
-
const
|
|
997
|
-
return /* @__PURE__ */
|
|
998
|
-
/* @__PURE__ */ jsx4("text", { fg: terminalColors.text, children: indicator }),
|
|
999
|
-
/* @__PURE__ */ jsx4("text", { fg: selected ? terminalColors.accent : terminalColors.text, children: repo.name }),
|
|
1000
|
-
/* @__PURE__ */ jsxs4("text", { fg: terminalColors.textMuted, children: [
|
|
1001
|
-
" \xB7 ",
|
|
1002
|
-
displaySource
|
|
1003
|
-
] })
|
|
1004
|
-
] }, repo.source);
|
|
1031
|
+
const maxSourceLen = Math.max(0, contentWidth - repo.name.length - 6);
|
|
1032
|
+
const displaySource = maxSourceLen > 3 && repo.source.length > maxSourceLen ? repo.source.slice(0, maxSourceLen - 3) + "..." : repo.source;
|
|
1033
|
+
const line = `${indicator}${repo.name} \xB7 ${displaySource}`;
|
|
1034
|
+
return /* @__PURE__ */ jsx4("text", { fg: selected ? terminalColors.accent : terminalColors.text, children: line }, repo.source);
|
|
1005
1035
|
}) }),
|
|
1006
1036
|
filteredRepos.length > maxVisible && /* @__PURE__ */ jsxs4("text", { fg: terminalColors.textMuted, children: [
|
|
1007
1037
|
"\n",
|
|
@@ -1160,15 +1190,11 @@ function Installed({ onNavigate, cols = 80, rows = 24 }) {
|
|
|
1160
1190
|
const selected = actualIdx === selectedIndex;
|
|
1161
1191
|
const indicator = selected ? "\u25B8" : " ";
|
|
1162
1192
|
const statusIcon = skill.enabled !== false ? "\u25CF" : "\u25CB";
|
|
1163
|
-
const
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
" "
|
|
1169
|
-
] }),
|
|
1170
|
-
/* @__PURE__ */ jsx5("text", { fg: selected ? terminalColors.accent : terminalColors.text, children: skill.name })
|
|
1171
|
-
] }, skill.name);
|
|
1193
|
+
const qualityBadge = skill.grade ? ` [${skill.grade}]` : "";
|
|
1194
|
+
const warningIndicator = skill.warnings && skill.warnings > 2 ? " \u26A0" : "";
|
|
1195
|
+
const line = `${indicator}${statusIcon} ${skill.name}${qualityBadge}${warningIndicator}`;
|
|
1196
|
+
const badgeColor = skill.quality !== void 0 ? skill.quality >= 80 ? terminalColors.success : skill.quality >= 60 ? terminalColors.warning : terminalColors.error : terminalColors.text;
|
|
1197
|
+
return /* @__PURE__ */ jsx5("text", { fg: selected ? terminalColors.accent : badgeColor, children: line }, skill.name);
|
|
1172
1198
|
}),
|
|
1173
1199
|
filteredSkills.length > maxVisible && /* @__PURE__ */ jsxs5("text", { fg: terminalColors.textMuted, children: [
|
|
1174
1200
|
"\n",
|
|
@@ -1268,22 +1294,16 @@ function Marketplace({ onNavigate, cols = 80, rows = 24 }) {
|
|
|
1268
1294
|
/* @__PURE__ */ jsx6("text", { children: " " })
|
|
1269
1295
|
] }),
|
|
1270
1296
|
animPhase >= 3 && /* @__PURE__ */ jsxs6("box", { flexDirection: "column", children: [
|
|
1271
|
-
/* @__PURE__ */ jsxs6("
|
|
1272
|
-
|
|
1273
|
-
/* @__PURE__ */ jsx6("text", { fg: terminalColors.textMuted, children: "
|
|
1297
|
+
/* @__PURE__ */ jsxs6("text", { fg: terminalColors.text, children: [
|
|
1298
|
+
"Featured \xB7 ",
|
|
1299
|
+
/* @__PURE__ */ jsx6("text", { fg: terminalColors.textMuted, children: "trending" })
|
|
1274
1300
|
] }),
|
|
1275
1301
|
/* @__PURE__ */ jsx6("text", { children: " " }),
|
|
1276
1302
|
visibleFeatured.map((item, idx) => {
|
|
1277
1303
|
const selected = idx === selectedIndex;
|
|
1278
1304
|
const indicator = selected ? "\u25B8" : " ";
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
/* @__PURE__ */ jsx6("text", { fg: selected ? terminalColors.accent : terminalColors.text, children: item.name }),
|
|
1282
|
-
/* @__PURE__ */ jsxs6("text", { fg: terminalColors.recommend, children: [
|
|
1283
|
-
" \u2605",
|
|
1284
|
-
item.stars
|
|
1285
|
-
] })
|
|
1286
|
-
] }, item.source);
|
|
1305
|
+
const line = `${indicator}${item.name} \u2605${item.stars}`;
|
|
1306
|
+
return /* @__PURE__ */ jsx6("text", { fg: selected ? terminalColors.accent : terminalColors.text, children: line }, item.source);
|
|
1287
1307
|
}),
|
|
1288
1308
|
featured.length > maxVisible && /* @__PURE__ */ jsxs6("text", { fg: terminalColors.textMuted, children: [
|
|
1289
1309
|
"\n",
|
|
@@ -1339,12 +1359,12 @@ function Recommend({ onNavigate, cols = 80, rows = 24 }) {
|
|
|
1339
1359
|
return () => clearInterval(interval);
|
|
1340
1360
|
}, [analyzing]);
|
|
1341
1361
|
const recommendations = useMemo6(() => [
|
|
1342
|
-
{ name: "tdd-workflow", reason: "Based on your test files and coverage patterns", confidence: 95 },
|
|
1343
|
-
{ name: "react-patterns", reason: "Detected React in package.json with hooks usage", confidence: 88 },
|
|
1344
|
-
{ name: "typescript-strict", reason: "tsconfig.json found with strict mode disabled", confidence: 82 },
|
|
1345
|
-
{ name: "git-workflow", reason: ".git directory with complex branching detected", confidence: 75 },
|
|
1346
|
-
{ name: "api-design", reason: "REST endpoints found in your codebase", confidence: 68 },
|
|
1347
|
-
{ name: "docker-compose", reason: "docker-compose.yml detected for orchestration", confidence: 62 }
|
|
1362
|
+
{ name: "tdd-workflow", reason: "Based on your test files and coverage patterns", confidence: 95, quality: 92, grade: "A" },
|
|
1363
|
+
{ name: "react-patterns", reason: "Detected React in package.json with hooks usage", confidence: 88, quality: 85, grade: "B" },
|
|
1364
|
+
{ name: "typescript-strict", reason: "tsconfig.json found with strict mode disabled", confidence: 82, quality: 78, grade: "C" },
|
|
1365
|
+
{ name: "git-workflow", reason: ".git directory with complex branching detected", confidence: 75, quality: 82, grade: "B" },
|
|
1366
|
+
{ name: "api-design", reason: "REST endpoints found in your codebase", confidence: 68, quality: 71, grade: "C" },
|
|
1367
|
+
{ name: "docker-compose", reason: "docker-compose.yml detected for orchestration", confidence: 62, quality: 65, grade: "D" }
|
|
1348
1368
|
], []);
|
|
1349
1369
|
const maxVisible = Math.max(3, Math.floor((rows - 10) / 2));
|
|
1350
1370
|
const visibleRecs = recommendations.slice(0, maxVisible);
|
|
@@ -1426,6 +1446,7 @@ function Recommend({ onNavigate, cols = 80, rows = 24 }) {
|
|
|
1426
1446
|
visibleRecs.map((rec, idx) => {
|
|
1427
1447
|
const selected = idx === selectedIndex;
|
|
1428
1448
|
const indicator = selected ? "\u25B8" : " ";
|
|
1449
|
+
const qualityColor = rec.quality >= 80 ? terminalColors.success : rec.quality >= 60 ? terminalColors.warning : terminalColors.error;
|
|
1429
1450
|
return /* @__PURE__ */ jsxs7("box", { flexDirection: "column", children: [
|
|
1430
1451
|
/* @__PURE__ */ jsxs7("box", { flexDirection: "row", children: [
|
|
1431
1452
|
/* @__PURE__ */ jsx7("text", { fg: terminalColors.text, children: indicator }),
|
|
@@ -1434,6 +1455,11 @@ function Recommend({ onNavigate, cols = 80, rows = 24 }) {
|
|
|
1434
1455
|
" ",
|
|
1435
1456
|
rec.confidence,
|
|
1436
1457
|
"%"
|
|
1458
|
+
] }),
|
|
1459
|
+
/* @__PURE__ */ jsxs7("text", { fg: qualityColor, children: [
|
|
1460
|
+
" [",
|
|
1461
|
+
rec.grade,
|
|
1462
|
+
"]"
|
|
1437
1463
|
] })
|
|
1438
1464
|
] }),
|
|
1439
1465
|
/* @__PURE__ */ jsxs7("text", { fg: terminalColors.textMuted, children: [
|
|
@@ -2271,14 +2297,16 @@ var SHORTCUTS = [
|
|
|
2271
2297
|
{ key: "m", desc: "Marketplace" },
|
|
2272
2298
|
{ key: "r", desc: "Recommendations" },
|
|
2273
2299
|
{ key: "i", desc: "Installed skills" },
|
|
2274
|
-
{ key: "s", desc: "Sync settings" }
|
|
2300
|
+
{ key: "s", desc: "Sync settings" },
|
|
2301
|
+
{ key: "f", desc: "Find skills" }
|
|
2275
2302
|
] },
|
|
2276
2303
|
{ section: "Actions", items: [
|
|
2277
2304
|
{ key: "t", desc: "Translate skills" },
|
|
2278
2305
|
{ key: "w", desc: "Workflows" },
|
|
2279
2306
|
{ key: "x", desc: "Execute" },
|
|
2280
2307
|
{ key: "n", desc: "Plan" },
|
|
2281
|
-
{ key: "
|
|
2308
|
+
{ key: "v", desc: "Validate" },
|
|
2309
|
+
{ key: "u", desc: "Publish" }
|
|
2282
2310
|
] },
|
|
2283
2311
|
{ section: "Team & Config", items: [
|
|
2284
2312
|
{ key: "a", desc: "Team settings" },
|
|
@@ -2290,10 +2318,10 @@ var SHORTCUTS = [
|
|
|
2290
2318
|
] },
|
|
2291
2319
|
{ section: "Global", items: [
|
|
2292
2320
|
{ key: "/", desc: "This help screen" },
|
|
2321
|
+
{ key: "d", desc: "Open docs" },
|
|
2293
2322
|
{ key: "esc", desc: "Go back / Home" },
|
|
2294
2323
|
{ key: "q", desc: "Quit application" },
|
|
2295
|
-
{ key: "j/k", desc: "Navigate lists" }
|
|
2296
|
-
{ key: "enter", desc: "Select item" }
|
|
2324
|
+
{ key: "j/k", desc: "Navigate lists" }
|
|
2297
2325
|
] }
|
|
2298
2326
|
];
|
|
2299
2327
|
function ShortcutSection({ section, items, isLast }) {
|
|
@@ -2354,6 +2382,11 @@ function Help({ cols = 80 }) {
|
|
|
2354
2382
|
|
|
2355
2383
|
// src/App.tsx
|
|
2356
2384
|
import { jsx as jsx24, jsxs as jsxs24 } from "@opentui/react/jsx-runtime";
|
|
2385
|
+
var DOCS_URL = "https://agenstskills.com/docs";
|
|
2386
|
+
function openUrl(url) {
|
|
2387
|
+
const cmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
|
|
2388
|
+
exec(`${cmd} ${url}`);
|
|
2389
|
+
}
|
|
2357
2390
|
function App({ onExit } = {}) {
|
|
2358
2391
|
const [showSplash, setShowSplash] = useState15(true);
|
|
2359
2392
|
const [screen, setScreen] = useState15("home");
|
|
@@ -2390,6 +2423,10 @@ function App({ onExit } = {}) {
|
|
|
2390
2423
|
onExit ? onExit(0) : process.exit(0);
|
|
2391
2424
|
return;
|
|
2392
2425
|
}
|
|
2426
|
+
if (key.name === "d") {
|
|
2427
|
+
openUrl(DOCS_URL);
|
|
2428
|
+
return;
|
|
2429
|
+
}
|
|
2393
2430
|
const targetScreen = NAV_KEYS[key.name || ""];
|
|
2394
2431
|
if (targetScreen) {
|
|
2395
2432
|
setScreen(targetScreen);
|
|
@@ -2678,7 +2715,7 @@ function StatusBar({
|
|
|
2678
2715
|
}
|
|
2679
2716
|
|
|
2680
2717
|
// src/components/SkillList.tsx
|
|
2681
|
-
import {
|
|
2718
|
+
import { jsx as jsx28, jsxs as jsxs28 } from "@opentui/react/jsx-runtime";
|
|
2682
2719
|
function SkillList({
|
|
2683
2720
|
skills,
|
|
2684
2721
|
selectedIndex,
|
|
@@ -2703,28 +2740,9 @@ function SkillList({
|
|
|
2703
2740
|
const pointer = isSelected ? symbols.pointer : symbols.pointerInactive;
|
|
2704
2741
|
const fg = isSelected ? terminalColors.accent : terminalColors.text;
|
|
2705
2742
|
const statusIcon = skill.enabled ? symbols.active : symbols.pending;
|
|
2706
|
-
const
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
pointer,
|
|
2710
|
-
" ",
|
|
2711
|
-
skill.name
|
|
2712
|
-
] }) : /* @__PURE__ */ jsxs28(Fragment5, { children: [
|
|
2713
|
-
pointer,
|
|
2714
|
-
" ",
|
|
2715
|
-
skill.name
|
|
2716
|
-
] }) }),
|
|
2717
|
-
/* @__PURE__ */ jsxs28("text", { fg: terminalColors.textMuted, children: [
|
|
2718
|
-
" ",
|
|
2719
|
-
statusIcon
|
|
2720
|
-
] }),
|
|
2721
|
-
skill.description && /* @__PURE__ */ jsxs28("text", { fg: terminalColors.textMuted, children: [
|
|
2722
|
-
" ",
|
|
2723
|
-
"- ",
|
|
2724
|
-
skill.description.slice(0, 40),
|
|
2725
|
-
skill.description.length > 40 ? "..." : ""
|
|
2726
|
-
] })
|
|
2727
|
-
] }, skill.name);
|
|
2743
|
+
const descPart = skill.description ? ` - ${skill.description.slice(0, 40)}${skill.description.length > 40 ? "..." : ""}` : "";
|
|
2744
|
+
const line = `${pointer} ${skill.name} ${statusIcon}${descPart}`;
|
|
2745
|
+
return /* @__PURE__ */ jsx28("text", { fg, children: isSelected ? /* @__PURE__ */ jsx28("b", { children: line }) : line }, skill.name);
|
|
2728
2746
|
}),
|
|
2729
2747
|
pagination.itemsBelow > 0 && /* @__PURE__ */ jsxs28("text", { fg: terminalColors.textMuted, children: [
|
|
2730
2748
|
symbols.arrowDown,
|
|
@@ -2777,17 +2795,28 @@ function FeatureList({ features = FEATURES2 }) {
|
|
|
2777
2795
|
|
|
2778
2796
|
// src/index.tsx
|
|
2779
2797
|
import { jsx as jsx31 } from "@opentui/react/jsx-runtime";
|
|
2798
|
+
var rootInstance = null;
|
|
2780
2799
|
function exitTUI(code = 0) {
|
|
2781
2800
|
try {
|
|
2782
|
-
|
|
2801
|
+
if (rootInstance) {
|
|
2802
|
+
try {
|
|
2803
|
+
rootInstance.unmount();
|
|
2804
|
+
} catch {
|
|
2805
|
+
}
|
|
2806
|
+
rootInstance = null;
|
|
2807
|
+
}
|
|
2808
|
+
process.stdout.write("\x1B[?1049l\x1B[?25h\x1B[0m\x1B[H\x1B[2J");
|
|
2783
2809
|
} catch {
|
|
2784
2810
|
}
|
|
2785
|
-
process.exit(code);
|
|
2811
|
+
setImmediate(() => process.exit(code));
|
|
2786
2812
|
}
|
|
2787
2813
|
async function startTUI() {
|
|
2788
|
-
const
|
|
2789
|
-
|
|
2790
|
-
|
|
2814
|
+
const handleSignal = () => exitTUI(0);
|
|
2815
|
+
process.on("SIGINT", handleSignal);
|
|
2816
|
+
process.on("SIGTERM", handleSignal);
|
|
2817
|
+
const renderer = await createCliRenderer({ exitOnCtrlC: false });
|
|
2818
|
+
rootInstance = createRoot(renderer);
|
|
2819
|
+
rootInstance.render(/* @__PURE__ */ jsx31(App, { onExit: exitTUI }));
|
|
2791
2820
|
return new Promise(() => {
|
|
2792
2821
|
});
|
|
2793
2822
|
}
|