@skillkit/tui 1.14.0 → 1.16.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.d.ts CHANGED
@@ -22,7 +22,7 @@ interface FetchedSkill {
22
22
  repoName: string;
23
23
  description?: string;
24
24
  }
25
- type Screen = 'home' | 'browse' | 'installed' | 'marketplace' | 'recommend' | 'translate' | 'context' | 'memory' | 'team' | 'plugins' | 'methodology' | 'plan' | 'workflow' | 'execute' | 'history' | 'sync' | 'settings' | 'help' | 'mesh' | 'message';
25
+ type Screen = 'home' | 'browse' | 'installed' | 'marketplace' | 'recommend' | 'translate' | 'context' | 'memory' | 'team' | 'plugins' | 'methodology' | 'plan' | 'workflow' | 'execute' | 'history' | 'sync' | 'settings' | 'help' | 'mesh' | 'message' | 'scan';
26
26
  declare const NAV_KEYS: Record<string, Screen>;
27
27
  declare const STATUS_BAR_SHORTCUTS = "b browse m market i installed s sync / help q quit";
28
28
  interface ScreenMeta {
@@ -1208,7 +1208,14 @@ interface MessageProps {
1208
1208
  }
1209
1209
  declare function Message(props: MessageProps): any;
1210
1210
 
1211
+ interface ScanProps {
1212
+ onNavigate: (screen: Screen) => void;
1213
+ cols?: number;
1214
+ rows?: number;
1215
+ }
1216
+ declare function Scan(props: ScanProps): any;
1217
+
1211
1218
  declare function exitTUI(code?: number): void;
1212
1219
  declare function startTUI(): Promise<never>;
1213
1220
 
1214
- export { AGENT_LOGOS, AgentGrid, type AgentLogo, type AgentStatus, type AgentsState, AnimatedText, type AnimationPreset, App, BlinkingText, BottomStatusBar, Breadcrumb, type BreadcrumbItem, Browse, Button, ButtonGroup, type ButtonSize, type ButtonVariant, Clickable, ClickableRow, ClickableText, CodeBlock, type ColorName, type ColorValue, Context, CountUpText, DEFAULT_REPOS, DEFAULT_SCRAMBLE_CONFIG, type DetailField, DetailPane, type EasingFunction, EmptyState, ErrorBoundary, ErrorState, Execute, FEATURES, type Feature, FeatureList, type FetchedSkill, FocusRing, FormField, Header, Help, HighlightableListItem, History, Home, HoverHighlight, IconButton, InlineCode, InlineStatus, Installed, InteractiveArea, LoadingState, Marketplace, type MarketplaceState, Memory, Mesh, Message, Methodology, NAV_KEYS, type NavigationState, NavigationTrail, type PaginationResult, PathBreadcrumb, Plan, Plugins, PressEffect, ProgressBar, PulsingText, Recommend, type RepoInfo, RightSidebar, SCRAMBLE_CHARS, SIDEBAR_NAV, STATUS_BAR_SHORTCUTS, type ScrambleConfig, type Screen, type ScreenMeta, SearchInput, SelectField, SelectList, type SelectListItem, Settings, Sidebar, type SidebarSection, type SkillItem, SkillList, type SkillWithDetails, type SkillsState, Spinner, Splash, SplitPane, StatsCard, StatusBadge, StatusBar, StatusIndicator, type StatusType, type SymbolName, Sync, TOTAL_AGENTS, type Tab, TabBar, Team, TextAreaField, ThreePaneLayout, Translate, Try, VerticalTabBar, Workflow, animations, calculateMaxVisible, calculatePagination, clampIndex, cleanupTempRoot, colors, createAgentsState, createMarketplaceState, createNavigationState, createSkillsState, exitTUI, fetchRepoSkills, filterMarketplaceSkills, filterSkills, formatAgentDisplay, getAgentAdapter, getAgentLogo, getAgentTypes, getColor, getDetectedAgentCount, getDetectedAgents, getInstallDir, getMarketplaceRepos, getScreenFromKey, getSearchDirs, getStaggerDelay, getVersion, goBack, isNavKey, loadAgents, loadSkills, loadSkillsWithDetails, moveDown, moveUp, navigateTo, readSkillDescription, removeSkill, saveSkillMetadata, scrambleText, sortSkillsByName, startTUI, symbols, terminalColors, toSkillItems };
1221
+ export { AGENT_LOGOS, AgentGrid, type AgentLogo, type AgentStatus, type AgentsState, AnimatedText, type AnimationPreset, App, BlinkingText, BottomStatusBar, Breadcrumb, type BreadcrumbItem, Browse, Button, ButtonGroup, type ButtonSize, type ButtonVariant, Clickable, ClickableRow, ClickableText, CodeBlock, type ColorName, type ColorValue, Context, CountUpText, DEFAULT_REPOS, DEFAULT_SCRAMBLE_CONFIG, type DetailField, DetailPane, type EasingFunction, EmptyState, ErrorBoundary, ErrorState, Execute, FEATURES, type Feature, FeatureList, type FetchedSkill, FocusRing, FormField, Header, Help, HighlightableListItem, History, Home, HoverHighlight, IconButton, InlineCode, InlineStatus, Installed, InteractiveArea, LoadingState, Marketplace, type MarketplaceState, Memory, Mesh, Message, Methodology, NAV_KEYS, type NavigationState, NavigationTrail, type PaginationResult, PathBreadcrumb, Plan, Plugins, PressEffect, ProgressBar, PulsingText, Recommend, type RepoInfo, RightSidebar, SCRAMBLE_CHARS, SIDEBAR_NAV, STATUS_BAR_SHORTCUTS, Scan, type ScrambleConfig, type Screen, type ScreenMeta, SearchInput, SelectField, SelectList, type SelectListItem, Settings, Sidebar, type SidebarSection, type SkillItem, SkillList, type SkillWithDetails, type SkillsState, Spinner, Splash, SplitPane, StatsCard, StatusBadge, StatusBar, StatusIndicator, type StatusType, type SymbolName, Sync, TOTAL_AGENTS, type Tab, TabBar, Team, TextAreaField, ThreePaneLayout, Translate, Try, VerticalTabBar, Workflow, animations, calculateMaxVisible, calculatePagination, clampIndex, cleanupTempRoot, colors, createAgentsState, createMarketplaceState, createNavigationState, createSkillsState, exitTUI, fetchRepoSkills, filterMarketplaceSkills, filterSkills, formatAgentDisplay, getAgentAdapter, getAgentLogo, getAgentTypes, getColor, getDetectedAgentCount, getDetectedAgents, getInstallDir, getMarketplaceRepos, getScreenFromKey, getSearchDirs, getStaggerDelay, getVersion, goBack, isNavKey, loadAgents, loadSkills, loadSkillsWithDetails, moveDown, moveUp, navigateTo, readSkillDescription, removeSkill, saveSkillMetadata, scrambleText, sortSkillsByName, startTUI, symbols, terminalColors, toSkillItems };
package/dist/index.js CHANGED
@@ -1721,7 +1721,7 @@ var render = async (node, rendererOrConfig = {}) => {
1721
1721
  import { createCliRenderer as createCliRenderer2 } from "@opentui/core";
1722
1722
 
1723
1723
  // src/App.tsx
1724
- import { execFile } from "child_process";
1724
+ import { execFile as execFile2 } from "child_process";
1725
1725
 
1726
1726
  // src/state/types.ts
1727
1727
  var NAV_KEYS = {
@@ -1744,7 +1744,8 @@ var NAV_KEYS = {
1744
1744
  ",": "settings",
1745
1745
  "/": "help",
1746
1746
  "g": "mesh",
1747
- "j": "message"
1747
+ "j": "message",
1748
+ "z": "scan"
1748
1749
  };
1749
1750
  var STATUS_BAR_SHORTCUTS = "b browse m market i installed s sync / help q quit";
1750
1751
  var SIDEBAR_NAV = [
@@ -1762,7 +1763,8 @@ var SIDEBAR_NAV = [
1762
1763
  items: [
1763
1764
  { key: "i", label: "Installed", screen: "installed" },
1764
1765
  { key: "s", label: "Sync", screen: "sync" },
1765
- { key: "t", label: "Translate", screen: "translate" }
1766
+ { key: "t", label: "Translate", screen: "translate" },
1767
+ { key: "z", label: "Scan", screen: "scan" }
1766
1768
  ]
1767
1769
  },
1768
1770
  {
@@ -2208,6 +2210,18 @@ var AGENT_LOGOS = {
2208
2210
  "qwen": { icon: "\u22A7", name: "Qwen", company: "Alibaba" },
2209
2211
  "vercel": { icon: "\u25B2", name: "Vercel", company: "Vercel" },
2210
2212
  "zencoder": { icon: "\u22A9", name: "Zencoder", company: "" },
2213
+ "devin": { icon: "\u25A7", name: "Devin", company: "Cognition" },
2214
+ "aider": { icon: "\u25A8", name: "Aider", company: "" },
2215
+ "sourcegraph-cody": { icon: "\u25A9", name: "Cody", company: "Sourcegraph" },
2216
+ "amazon-q": { icon: "\u25AA", name: "Amazon Q", company: "AWS" },
2217
+ "augment-code": { icon: "\u25AB", name: "Augment", company: "Augment Code" },
2218
+ "replit-agent": { icon: "\u25B4", name: "Replit Agent", company: "Replit" },
2219
+ "bolt": { icon: "\u26A1", name: "Bolt", company: "StackBlitz" },
2220
+ "lovable": { icon: "\u2665", name: "Lovable", company: "Lovable" },
2221
+ "tabby": { icon: "\u25B9", name: "Tabby", company: "TabbyML" },
2222
+ "tabnine": { icon: "\u25BA", name: "Tabnine", company: "Tabnine" },
2223
+ "codegpt": { icon: "\u25BB", name: "CodeGPT", company: "" },
2224
+ "playcode-agent": { icon: "\u25BD", name: "PlayCode", company: "" },
2211
2225
  "universal": { icon: "\u25CF", name: "Universal", company: "" }
2212
2226
  };
2213
2227
  var symbols = {
@@ -10409,6 +10423,9 @@ var SHORTCUTS = [{
10409
10423
  }, {
10410
10424
  key: "u",
10411
10425
  desc: "Publish"
10426
+ }, {
10427
+ key: "z",
10428
+ desc: "Security scan"
10412
10429
  }]
10413
10430
  }, {
10414
10431
  section: "Team & Config",
@@ -10864,14 +10881,339 @@ function Message(props) {
10864
10881
  })();
10865
10882
  }
10866
10883
 
10884
+ // src/screens/Scan.tsx
10885
+ import { execFile } from "child_process";
10886
+ function getSeverityColor(severity) {
10887
+ switch (severity.toLowerCase()) {
10888
+ case "critical":
10889
+ return "#ff5555";
10890
+ case "high":
10891
+ return "#ff4444";
10892
+ case "medium":
10893
+ return "#ffaa00";
10894
+ case "low":
10895
+ return "#00bbcc";
10896
+ case "info":
10897
+ return "#888888";
10898
+ default:
10899
+ return terminalColors.textMuted;
10900
+ }
10901
+ }
10902
+ function getVerdictColor(verdict) {
10903
+ switch (verdict) {
10904
+ case "pass":
10905
+ return "#22cc44";
10906
+ case "warn":
10907
+ return "#ffaa00";
10908
+ case "fail":
10909
+ return "#ff5555";
10910
+ default:
10911
+ return terminalColors.textMuted;
10912
+ }
10913
+ }
10914
+ function Scan(props) {
10915
+ const [scanning, setScanning] = createSignal(false);
10916
+ const [result, setResult] = createSignal(null);
10917
+ const [error, setError] = createSignal(null);
10918
+ const [scanPath] = createSignal(".");
10919
+ const [selectedIndex, setSelectedIndex] = createSignal(0);
10920
+ const rows = () => props.rows ?? 24;
10921
+ const visibleCount = () => Math.max(1, rows() - 14);
10922
+ const runScan = (path) => {
10923
+ setScanning(true);
10924
+ setError(null);
10925
+ setResult(null);
10926
+ try {
10927
+ execFile("npx", ["skillkit", "scan", path, "--format", "json"], {
10928
+ timeout: 3e4,
10929
+ maxBuffer: 1024 * 1024
10930
+ }, (err, stdout, stderr) => {
10931
+ setScanning(false);
10932
+ if (err && !stdout) {
10933
+ setError(stderr || err.message || "Scan failed");
10934
+ return;
10935
+ }
10936
+ try {
10937
+ const parsed = JSON.parse(stdout);
10938
+ setResult(parsed);
10939
+ } catch {
10940
+ setError("Failed to parse scan results");
10941
+ }
10942
+ });
10943
+ } catch (err) {
10944
+ setScanning(false);
10945
+ setError(err instanceof Error ? err.message : "Failed to start scan");
10946
+ }
10947
+ };
10948
+ createEffect(() => {
10949
+ runScan(scanPath());
10950
+ });
10951
+ const findings = createMemo(() => result()?.findings ?? []);
10952
+ const windowStart = createMemo(() => Math.max(0, selectedIndex() - visibleCount() + 1));
10953
+ const visibleFindings = createMemo(() => findings().slice(windowStart(), windowStart() + visibleCount()));
10954
+ useKeyboard((key) => {
10955
+ if (key.name === "k" || key.name === "up") {
10956
+ setSelectedIndex((i) => Math.max(0, i - 1));
10957
+ } else if (key.name === "j" || key.name === "down") {
10958
+ setSelectedIndex((i) => Math.min(findings().length - 1, i + 1));
10959
+ } else if (key.name === "r") {
10960
+ runScan(scanPath());
10961
+ }
10962
+ });
10963
+ return (() => {
10964
+ var _el$ = createElement("box"), _el$29 = createElement("text"), _el$31 = createElement("text");
10965
+ insertNode(_el$, _el$29);
10966
+ insertNode(_el$, _el$31);
10967
+ setProp(_el$, "flexDirection", "column");
10968
+ setProp(_el$, "padding", 1);
10969
+ insert(_el$, createComponent2(Header, {
10970
+ title: "Security Scan",
10971
+ subtitle: "detect vulnerabilities in skills",
10972
+ icon: "\\u25D0"
10973
+ }), _el$29);
10974
+ insert(_el$, createComponent2(Show, {
10975
+ get when() {
10976
+ return scanning();
10977
+ },
10978
+ get children() {
10979
+ var _el$2 = createElement("box"), _el$3 = createElement("text"), _el$4 = createTextNode(`Scanning `), _el$5 = createTextNode(`...`);
10980
+ insertNode(_el$2, _el$3);
10981
+ setProp(_el$2, "flexDirection", "row");
10982
+ setProp(_el$2, "gap", 1);
10983
+ insert(_el$2, createComponent2(Spinner, {}), _el$3);
10984
+ insertNode(_el$3, _el$4);
10985
+ insertNode(_el$3, _el$5);
10986
+ insert(_el$3, scanPath, _el$5);
10987
+ effect((_$p) => setProp(_el$3, "fg", terminalColors.textMuted, _$p));
10988
+ return _el$2;
10989
+ }
10990
+ }), _el$29);
10991
+ insert(_el$, createComponent2(Show, {
10992
+ get when() {
10993
+ return error();
10994
+ },
10995
+ get children() {
10996
+ var _el$6 = createElement("box"), _el$7 = createElement("text"), _el$8 = createTextNode(`Scan error: `), _el$9 = createElement("text");
10997
+ insertNode(_el$6, _el$7);
10998
+ insertNode(_el$6, _el$9);
10999
+ setProp(_el$6, "flexDirection", "column");
11000
+ insertNode(_el$7, _el$8);
11001
+ setProp(_el$7, "fg", "#ff5555");
11002
+ insert(_el$7, error, null);
11003
+ insertNode(_el$9, createTextNode(`Press r to retry`));
11004
+ effect((_$p) => setProp(_el$9, "fg", terminalColors.textMuted, _$p));
11005
+ return _el$6;
11006
+ }
11007
+ }), _el$29);
11008
+ insert(_el$, createComponent2(Show, {
11009
+ get when() {
11010
+ return memo2(() => !!result())() && !scanning();
11011
+ },
11012
+ get children() {
11013
+ var _el$1 = createElement("box"), _el$10 = createElement("box"), _el$11 = createElement("text"), _el$12 = createElement("text"), _el$13 = createElement("text"), _el$14 = createTextNode(`ms`), _el$15 = createElement("box"), _el$28 = createElement("text");
11014
+ insertNode(_el$1, _el$10);
11015
+ insertNode(_el$1, _el$15);
11016
+ insertNode(_el$1, _el$28);
11017
+ setProp(_el$1, "flexDirection", "column");
11018
+ insertNode(_el$10, _el$11);
11019
+ insertNode(_el$10, _el$12);
11020
+ insertNode(_el$10, _el$13);
11021
+ setProp(_el$10, "flexDirection", "row");
11022
+ setProp(_el$10, "gap", 2);
11023
+ insert(_el$11, () => result().skillName);
11024
+ insert(_el$12, () => result().verdict.toUpperCase());
11025
+ insertNode(_el$13, _el$14);
11026
+ insert(_el$13, () => result().duration, _el$14);
11027
+ setProp(_el$15, "flexDirection", "row");
11028
+ setProp(_el$15, "gap", 2);
11029
+ insert(_el$15, createComponent2(Show, {
11030
+ get when() {
11031
+ return result().stats.critical > 0;
11032
+ },
11033
+ get children() {
11034
+ var _el$16 = createElement("text"), _el$17 = createTextNode(` critical`);
11035
+ insertNode(_el$16, _el$17);
11036
+ setProp(_el$16, "fg", "#ff5555");
11037
+ insert(_el$16, () => result().stats.critical, _el$17);
11038
+ return _el$16;
11039
+ }
11040
+ }), null);
11041
+ insert(_el$15, createComponent2(Show, {
11042
+ get when() {
11043
+ return result().stats.high > 0;
11044
+ },
11045
+ get children() {
11046
+ var _el$18 = createElement("text"), _el$19 = createTextNode(` high`);
11047
+ insertNode(_el$18, _el$19);
11048
+ setProp(_el$18, "fg", "#ff4444");
11049
+ insert(_el$18, () => result().stats.high, _el$19);
11050
+ return _el$18;
11051
+ }
11052
+ }), null);
11053
+ insert(_el$15, createComponent2(Show, {
11054
+ get when() {
11055
+ return result().stats.medium > 0;
11056
+ },
11057
+ get children() {
11058
+ var _el$20 = createElement("text"), _el$21 = createTextNode(` medium`);
11059
+ insertNode(_el$20, _el$21);
11060
+ setProp(_el$20, "fg", "#ffaa00");
11061
+ insert(_el$20, () => result().stats.medium, _el$21);
11062
+ return _el$20;
11063
+ }
11064
+ }), null);
11065
+ insert(_el$15, createComponent2(Show, {
11066
+ get when() {
11067
+ return result().stats.low > 0;
11068
+ },
11069
+ get children() {
11070
+ var _el$22 = createElement("text"), _el$23 = createTextNode(` low`);
11071
+ insertNode(_el$22, _el$23);
11072
+ setProp(_el$22, "fg", "#00bbcc");
11073
+ insert(_el$22, () => result().stats.low, _el$23);
11074
+ return _el$22;
11075
+ }
11076
+ }), null);
11077
+ insert(_el$15, createComponent2(Show, {
11078
+ get when() {
11079
+ return result().stats.info > 0;
11080
+ },
11081
+ get children() {
11082
+ var _el$24 = createElement("text"), _el$25 = createTextNode(` info`);
11083
+ insertNode(_el$24, _el$25);
11084
+ setProp(_el$24, "fg", "#888888");
11085
+ insert(_el$24, () => result().stats.info, _el$25);
11086
+ return _el$24;
11087
+ }
11088
+ }), null);
11089
+ insert(_el$15, createComponent2(Show, {
11090
+ get when() {
11091
+ return findings().length === 0;
11092
+ },
11093
+ get children() {
11094
+ var _el$26 = createElement("text");
11095
+ insertNode(_el$26, createTextNode(`No findings`));
11096
+ setProp(_el$26, "fg", "#22cc44");
11097
+ return _el$26;
11098
+ }
11099
+ }), null);
11100
+ insert(_el$28, () => "\u2500".repeat(Math.min(60, (props.cols ?? 80) - 4)));
11101
+ insert(_el$1, createComponent2(Show, {
11102
+ get when() {
11103
+ return findings().length === 0;
11104
+ },
11105
+ get children() {
11106
+ return createComponent2(EmptyState, {
11107
+ title: "No security findings detected"
11108
+ });
11109
+ }
11110
+ }), null);
11111
+ insert(_el$1, createComponent2(Show, {
11112
+ get when() {
11113
+ return findings().length > 0;
11114
+ },
11115
+ get children() {
11116
+ return createComponent2(For, {
11117
+ get each() {
11118
+ return visibleFindings();
11119
+ },
11120
+ children: (finding, idx) => {
11121
+ const absoluteIdx = () => windowStart() + idx();
11122
+ const isSelected = () => absoluteIdx() === selectedIndex();
11123
+ return (() => {
11124
+ var _el$33 = createElement("box"), _el$34 = createElement("box"), _el$35 = createElement("text"), _el$36 = createElement("text"), _el$37 = createElement("text"), _el$38 = createTextNode(`[`), _el$39 = createTextNode(`]`), _el$40 = createElement("text");
11125
+ insertNode(_el$33, _el$34);
11126
+ setProp(_el$33, "flexDirection", "column");
11127
+ insertNode(_el$34, _el$35);
11128
+ insertNode(_el$34, _el$36);
11129
+ insertNode(_el$34, _el$37);
11130
+ insertNode(_el$34, _el$40);
11131
+ setProp(_el$34, "flexDirection", "row");
11132
+ setProp(_el$34, "gap", 1);
11133
+ insert(_el$35, () => isSelected() ? ">" : " ");
11134
+ insert(_el$36, () => finding.severity.toUpperCase().padEnd(8));
11135
+ insertNode(_el$37, _el$38);
11136
+ insertNode(_el$37, _el$39);
11137
+ insert(_el$37, () => finding.ruleId, _el$39);
11138
+ insert(_el$40, () => finding.title);
11139
+ insert(_el$33, createComponent2(Show, {
11140
+ get when() {
11141
+ return memo2(() => !!isSelected())() && finding.filePath;
11142
+ },
11143
+ get children() {
11144
+ var _el$41 = createElement("text"), _el$42 = createTextNode(` `);
11145
+ insertNode(_el$41, _el$42);
11146
+ insert(_el$41, () => finding.filePath, null);
11147
+ insert(_el$41, (() => {
11148
+ var _c$ = memo2(() => !!finding.lineNumber);
11149
+ return () => _c$() ? `:${finding.lineNumber}` : "";
11150
+ })(), null);
11151
+ effect((_$p) => setProp(_el$41, "fg", terminalColors.textMuted, _$p));
11152
+ return _el$41;
11153
+ }
11154
+ }), null);
11155
+ insert(_el$33, createComponent2(Show, {
11156
+ get when() {
11157
+ return memo2(() => !!isSelected())() && finding.remediation;
11158
+ },
11159
+ get children() {
11160
+ var _el$43 = createElement("text"), _el$44 = createTextNode(` Fix: `);
11161
+ insertNode(_el$43, _el$44);
11162
+ insert(_el$43, () => finding.remediation, null);
11163
+ effect((_$p) => setProp(_el$43, "fg", terminalColors.accent, _$p));
11164
+ return _el$43;
11165
+ }
11166
+ }), null);
11167
+ effect((_p$) => {
11168
+ var _v$5 = isSelected() ? terminalColors.accent : terminalColors.textMuted, _v$6 = getSeverityColor(finding.severity), _v$7 = terminalColors.textMuted, _v$8 = isSelected() ? terminalColors.text : terminalColors.textMuted;
11169
+ _v$5 !== _p$.e && (_p$.e = setProp(_el$35, "fg", _v$5, _p$.e));
11170
+ _v$6 !== _p$.t && (_p$.t = setProp(_el$36, "fg", _v$6, _p$.t));
11171
+ _v$7 !== _p$.a && (_p$.a = setProp(_el$37, "fg", _v$7, _p$.a));
11172
+ _v$8 !== _p$.o && (_p$.o = setProp(_el$40, "fg", _v$8, _p$.o));
11173
+ return _p$;
11174
+ }, {
11175
+ e: void 0,
11176
+ t: void 0,
11177
+ a: void 0,
11178
+ o: void 0
11179
+ });
11180
+ return _el$33;
11181
+ })();
11182
+ }
11183
+ });
11184
+ }
11185
+ }), null);
11186
+ effect((_p$) => {
11187
+ var _v$ = terminalColors.text, _v$2 = getVerdictColor(result().verdict), _v$3 = terminalColors.textMuted, _v$4 = terminalColors.textMuted;
11188
+ _v$ !== _p$.e && (_p$.e = setProp(_el$11, "fg", _v$, _p$.e));
11189
+ _v$2 !== _p$.t && (_p$.t = setProp(_el$12, "fg", _v$2, _p$.t));
11190
+ _v$3 !== _p$.a && (_p$.a = setProp(_el$13, "fg", _v$3, _p$.a));
11191
+ _v$4 !== _p$.o && (_p$.o = setProp(_el$28, "fg", _v$4, _p$.o));
11192
+ return _p$;
11193
+ }, {
11194
+ e: void 0,
11195
+ t: void 0,
11196
+ a: void 0,
11197
+ o: void 0
11198
+ });
11199
+ return _el$1;
11200
+ }
11201
+ }), _el$29);
11202
+ insertNode(_el$29, createTextNode(` `));
11203
+ insertNode(_el$31, createTextNode(`j/k navigate r rescan esc back`));
11204
+ effect((_$p) => setProp(_el$31, "fg", terminalColors.textMuted, _$p));
11205
+ return _el$;
11206
+ })();
11207
+ }
11208
+
10867
11209
  // src/App.tsx
10868
11210
  var DOCS_URL = "https://agenstskills.com/docs";
10869
11211
  function openUrl(url) {
10870
11212
  if (process.platform === "win32") {
10871
- execFile("cmd", ["/c", "start", "", url]);
11213
+ execFile2("cmd", ["/c", "start", "", url]);
10872
11214
  } else {
10873
11215
  const cmd = process.platform === "darwin" ? "open" : "xdg-open";
10874
- execFile(cmd, [url]);
11216
+ execFile2(cmd, [url]);
10875
11217
  }
10876
11218
  }
10877
11219
  function App(props) {
@@ -11117,6 +11459,13 @@ function App(props) {
11117
11459
  get children() {
11118
11460
  return createComponent2(Message, mergeProps3(screenProps));
11119
11461
  }
11462
+ }), createComponent2(Match, {
11463
+ get when() {
11464
+ return currentScreen() === "scan";
11465
+ },
11466
+ get children() {
11467
+ return createComponent2(Scan, mergeProps3(screenProps));
11468
+ }
11120
11469
  })];
11121
11470
  }
11122
11471
  }));
@@ -11540,7 +11889,8 @@ var SCREEN_LABELS = {
11540
11889
  sync: "Sync",
11541
11890
  help: "Help",
11542
11891
  mesh: "Mesh",
11543
- message: "Message"
11892
+ message: "Message",
11893
+ scan: "Security Scan"
11544
11894
  };
11545
11895
  function BottomStatusBar(props) {
11546
11896
  const version = getVersion();
@@ -13810,6 +14160,7 @@ export {
13810
14160
  SCRAMBLE_CHARS,
13811
14161
  SIDEBAR_NAV,
13812
14162
  STATUS_BAR_SHORTCUTS,
14163
+ Scan,
13813
14164
  SearchInput,
13814
14165
  SelectField,
13815
14166
  SelectList,