@skillkit/tui 1.4.0 → 1.6.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,8 +2,8 @@
2
2
  import { render } from "ink";
3
3
 
4
4
  // src/App.tsx
5
- import { useState as useState17 } from "react";
6
- import { Box as Box15, Text as Text15, useInput as useInput13, useApp, useStdout } from "ink";
5
+ import { useState as useState21 } from "react";
6
+ import { Box as Box19, Text as Text19, useInput as useInput17, useApp, useStdout } from "ink";
7
7
 
8
8
  // src/components/Sidebar.tsx
9
9
  import { Box, Text } from "ink";
@@ -55,6 +55,12 @@ var NAV = [
55
55
  { id: "workflow", label: "Workflows", key: "w" },
56
56
  { id: "execute", label: "Execute", key: "x" },
57
57
  { id: "history", label: "History", key: "y" },
58
+ // Collaboration
59
+ { id: "team", label: "Team", key: "a" },
60
+ { id: "plugins", label: "Plugins", key: "p" },
61
+ // Methodology
62
+ { id: "methodology", label: "Methodology", key: "o" },
63
+ { id: "plan", label: "Plans", key: "n" },
58
64
  // Tools
59
65
  { id: "recommend", label: "Recommend", key: "r" },
60
66
  { id: "translate", label: "Translate", key: "t" },
@@ -78,12 +84,22 @@ function Sidebar({ screen }) {
78
84
  item.label
79
85
  ] }, item.id)),
80
86
  /* @__PURE__ */ jsx(Text, { children: " " }),
81
- NAV.slice(6, 10).map((item) => /* @__PURE__ */ jsxs(Text, { inverse: screen === item.id, children: [
87
+ NAV.slice(6, 8).map((item) => /* @__PURE__ */ jsxs(Text, { inverse: screen === item.id, children: [
82
88
  screen === item.id ? symbols.bullet : " ",
83
89
  item.label
84
90
  ] }, item.id)),
85
91
  /* @__PURE__ */ jsx(Text, { children: " " }),
86
- NAV.slice(10).map((item) => /* @__PURE__ */ jsxs(Text, { inverse: screen === item.id, children: [
92
+ NAV.slice(8, 10).map((item) => /* @__PURE__ */ jsxs(Text, { inverse: screen === item.id, children: [
93
+ screen === item.id ? symbols.bullet : " ",
94
+ item.label
95
+ ] }, item.id)),
96
+ /* @__PURE__ */ jsx(Text, { children: " " }),
97
+ NAV.slice(10, 14).map((item) => /* @__PURE__ */ jsxs(Text, { inverse: screen === item.id, children: [
98
+ screen === item.id ? symbols.bullet : " ",
99
+ item.label
100
+ ] }, item.id)),
101
+ /* @__PURE__ */ jsx(Text, { children: " " }),
102
+ NAV.slice(14).map((item) => /* @__PURE__ */ jsxs(Text, { inverse: screen === item.id, children: [
87
103
  screen === item.id ? symbols.bullet : " ",
88
104
  item.label
89
105
  ] }, item.id)),
@@ -174,14 +190,16 @@ function Home({ cols = 80, rows = 24 }) {
174
190
 
175
191
  // src/screens/Browse.tsx
176
192
  import { useState as useState3 } from "react";
177
- import { existsSync, mkdirSync, cpSync, rmSync } from "fs";
178
- import { join as join2 } from "path";
193
+ import { existsSync as existsSync2, mkdirSync, cpSync, rmSync } from "fs";
194
+ import { join as join3 } from "path";
179
195
  import { Box as Box3, Text as Text3, useInput } from "ink";
180
196
 
181
197
  // src/hooks/useMarketplace.ts
182
198
  import { useState as useState2, useCallback, useEffect as useEffect2 } from "react";
183
- import { detectProvider } from "@skillkit/core";
184
- var POPULAR_REPOS = [
199
+ import { detectProvider, loadConfig, extractFrontmatter } from "@skillkit/core";
200
+ import { readFileSync as readFileSync2, existsSync } from "fs";
201
+ import { join as join2 } from "path";
202
+ var DEFAULT_REPOS = [
185
203
  { source: "anthropics/skills", name: "Anthropic Official" },
186
204
  { source: "vercel-labs/agent-skills", name: "Vercel Labs" },
187
205
  { source: "expo/skills", name: "Expo / React Native" },
@@ -213,6 +231,41 @@ var POPULAR_REPOS = [
213
231
  { source: "openrouterteam/agent-skills", name: "OpenRouter SDK" },
214
232
  { source: "intellectronica/agent-skills", name: "Context7" }
215
233
  ];
234
+ function getMarketplaceRepos() {
235
+ try {
236
+ const config = loadConfig();
237
+ if (config.marketplaceSources?.length) {
238
+ const configRepos = config.marketplaceSources.map((source) => ({
239
+ source,
240
+ name: source.split("/").pop() || source
241
+ }));
242
+ const existingSources = new Set(configRepos.map((r) => r.source));
243
+ for (const repo of DEFAULT_REPOS) {
244
+ if (!existingSources.has(repo.source)) {
245
+ configRepos.push(repo);
246
+ }
247
+ }
248
+ return configRepos;
249
+ }
250
+ } catch {
251
+ }
252
+ return DEFAULT_REPOS;
253
+ }
254
+ function readSkillDescription(skillPath) {
255
+ const skillMdPath = join2(skillPath, "SKILL.md");
256
+ if (!existsSync(skillMdPath)) {
257
+ return void 0;
258
+ }
259
+ try {
260
+ const content = readFileSync2(skillMdPath, "utf-8");
261
+ const frontmatter = extractFrontmatter(content);
262
+ if (frontmatter && typeof frontmatter.description === "string") {
263
+ return frontmatter.description;
264
+ }
265
+ } catch {
266
+ }
267
+ return void 0;
268
+ }
216
269
  function useMarketplace() {
217
270
  const [allSkills, setAllSkills] = useState2([]);
218
271
  const [filteredSkills, setFilteredSkills] = useState2([]);
@@ -220,6 +273,8 @@ function useMarketplace() {
220
273
  const [error, setError] = useState2(null);
221
274
  const [currentRepo, setCurrentRepo] = useState2(null);
222
275
  const [fetchedRepos, setFetchedRepos] = useState2(/* @__PURE__ */ new Set());
276
+ const [failedRepos, setFailedRepos] = useState2([]);
277
+ const [repos] = useState2(() => getMarketplaceRepos());
223
278
  const fetchRepo = useCallback(async (source) => {
224
279
  if (fetchedRepos.has(source)) return;
225
280
  setLoading(true);
@@ -234,12 +289,13 @@ function useMarketplace() {
234
289
  if (!result.success || !result.discoveredSkills) {
235
290
  throw new Error(result.error || "Failed to fetch skills");
236
291
  }
237
- const repoName = POPULAR_REPOS.find((r) => r.source === source)?.name || source;
292
+ const repoName = repos.find((r) => r.source === source)?.name || source;
238
293
  const newSkills = result.discoveredSkills.map((skill) => ({
239
294
  name: skill.name,
240
295
  source,
241
296
  repoName,
242
- description: void 0
297
+ // Try to read description from skill frontmatter
298
+ description: readSkillDescription(skill.path)
243
299
  }));
244
300
  setAllSkills((prev) => {
245
301
  const updated = [...prev, ...newSkills];
@@ -251,27 +307,37 @@ function useMarketplace() {
251
307
  rmSync3(result.tempRoot, { recursive: true, force: true });
252
308
  }
253
309
  } catch (err) {
254
- setError(err instanceof Error ? err.message : "Failed to fetch repository");
310
+ const errorMsg = err instanceof Error ? err.message : "Failed to fetch repository";
311
+ setError(errorMsg);
312
+ setFailedRepos((prev) => prev.includes(source) ? prev : [...prev, source]);
255
313
  } finally {
256
314
  setLoading(false);
257
315
  setCurrentRepo(null);
258
316
  }
259
- }, [fetchedRepos]);
317
+ }, [fetchedRepos, repos]);
260
318
  const fetchAllRepos = useCallback(async () => {
261
319
  setLoading(true);
262
320
  setError(null);
263
- for (const repo of POPULAR_REPOS) {
321
+ const failures = [];
322
+ for (const repo of repos) {
264
323
  if (!fetchedRepos.has(repo.source)) {
265
324
  setCurrentRepo(repo.source);
266
325
  try {
267
326
  await fetchRepo(repo.source);
268
- } catch {
327
+ } catch (err) {
328
+ failures.push(repo.source);
269
329
  }
270
330
  }
271
331
  }
332
+ if (failures.length > 0) {
333
+ setFailedRepos((prev) => {
334
+ const combined = [...prev, ...failures];
335
+ return [...new Set(combined)];
336
+ });
337
+ }
272
338
  setLoading(false);
273
339
  setCurrentRepo(null);
274
- }, [fetchRepo, fetchedRepos]);
340
+ }, [fetchRepo, fetchedRepos, repos]);
275
341
  const search = useCallback((query) => {
276
342
  if (!query.trim()) {
277
343
  setFilteredSkills(allSkills);
@@ -288,6 +354,8 @@ function useMarketplace() {
288
354
  setFetchedRepos(/* @__PURE__ */ new Set());
289
355
  setAllSkills([]);
290
356
  setFilteredSkills([]);
357
+ setFailedRepos([]);
358
+ setError(null);
291
359
  }, []);
292
360
  useEffect2(() => {
293
361
  setFilteredSkills(allSkills);
@@ -302,8 +370,9 @@ function useMarketplace() {
302
370
  loading,
303
371
  error,
304
372
  totalCount: allSkills.length,
305
- repos: POPULAR_REPOS,
373
+ repos,
306
374
  currentRepo,
375
+ failedRepos,
307
376
  refresh,
308
377
  search,
309
378
  fetchRepo,
@@ -317,14 +386,14 @@ import { detectAgent, getAdapter as getAdapter2, getAllAdapters } from "@skillki
317
386
 
318
387
  // src/helpers.ts
319
388
  import {
320
- loadConfig,
389
+ loadConfig as loadConfig2,
321
390
  getSearchDirs as coreGetSearchDirs,
322
391
  getInstallDir as coreGetInstallDir,
323
392
  saveSkillMetadata as coreSaveSkillMetadata
324
393
  } from "@skillkit/core";
325
394
  import { getAdapter } from "@skillkit/agents";
326
395
  function getSearchDirs(agentType) {
327
- const type = agentType || loadConfig().agent;
396
+ const type = agentType || loadConfig2().agent;
328
397
  const adapter = getAdapter(type);
329
398
  const adapterInfo = {
330
399
  type: adapter.type,
@@ -335,7 +404,7 @@ function getSearchDirs(agentType) {
335
404
  return coreGetSearchDirs(adapterInfo);
336
405
  }
337
406
  function getInstallDir(global = false, agentType) {
338
- const type = agentType || loadConfig().agent;
407
+ const type = agentType || loadConfig2().agent;
339
408
  const adapter = getAdapter(type);
340
409
  const adapterInfo = {
341
410
  type: adapter.type,
@@ -400,11 +469,11 @@ function Browse({ rows = 24 }) {
400
469
  const targetAgentType = agentType || await detectAgent();
401
470
  const adapter = getAdapter2(targetAgentType);
402
471
  const installDir = getInstallDir(false, targetAgentType);
403
- if (!existsSync(installDir)) {
472
+ if (!existsSync2(installDir)) {
404
473
  mkdirSync(installDir, { recursive: true });
405
474
  }
406
- const targetPath = join2(installDir, skillName);
407
- if (existsSync(targetPath)) {
475
+ const targetPath = join3(installDir, skillName);
476
+ if (existsSync2(targetPath)) {
408
477
  rmSync(targetPath, { recursive: true, force: true });
409
478
  }
410
479
  cpSync(skill.path, targetPath, { recursive: true, dereference: true });
@@ -710,44 +779,167 @@ function Sync({ rows = 24 }) {
710
779
  }
711
780
 
712
781
  // src/screens/Settings.tsx
713
- import { useState as useState7 } from "react";
782
+ import { useState as useState7, useEffect as useEffect5 } from "react";
714
783
  import { Box as Box6, Text as Text6, useInput as useInput4 } from "ink";
784
+ import TextInput from "ink-text-input";
785
+ import { loadConfig as loadConfig3, saveConfig, AgentType as AgentTypeSchema } from "@skillkit/core";
715
786
  import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
787
+ var ALL_AGENTS = AgentTypeSchema.options;
716
788
  var SETTINGS = [
717
- { id: "agent", label: "Default Agent", value: "auto-detect" },
718
- { id: "sync", label: "Auto Sync", value: "disabled" },
719
- { id: "cache", label: "Cache Dir", value: "~/.skillkit/cache" }
789
+ { id: "agent", label: "Default Agent", type: "select", options: ["auto-detect", ...ALL_AGENTS] },
790
+ { id: "autoSync", label: "Auto Sync", type: "toggle" },
791
+ { id: "cacheDir", label: "Cache Dir", type: "text" }
720
792
  ];
721
- function Settings({}) {
793
+ function Settings(_props) {
794
+ const [config, setConfig] = useState7(null);
722
795
  const [sel, setSel] = useState7(0);
723
- useInput4((_, key) => {
724
- if (key.upArrow) setSel((i) => Math.max(0, i - 1));
725
- else if (key.downArrow) setSel((i) => Math.min(SETTINGS.length - 1, i + 1));
796
+ const [editing, setEditing] = useState7(false);
797
+ const [editValue, setEditValue] = useState7("");
798
+ const [saved, setSaved] = useState7(false);
799
+ const [error, setError] = useState7(null);
800
+ useEffect5(() => {
801
+ try {
802
+ const loaded = loadConfig3();
803
+ setConfig(loaded);
804
+ } catch (err) {
805
+ setError(`Failed to load config: ${err}`);
806
+ }
807
+ }, []);
808
+ const getCurrentValue = (setting) => {
809
+ if (!config) return "";
810
+ switch (setting.id) {
811
+ case "agent":
812
+ return config.agent === "universal" ? "auto-detect" : config.agent || "auto-detect";
813
+ case "autoSync":
814
+ return config.autoSync ? "enabled" : "disabled";
815
+ case "cacheDir":
816
+ return config.cacheDir || "~/.skillkit/cache";
817
+ default:
818
+ return "";
819
+ }
820
+ };
821
+ const handleSave = (setting, value) => {
822
+ if (!config) return;
823
+ const newConfig = { ...config };
824
+ switch (setting.id) {
825
+ case "agent":
826
+ if (value === "auto-detect") {
827
+ newConfig.agent = "universal";
828
+ } else {
829
+ newConfig.agent = value;
830
+ }
831
+ break;
832
+ case "autoSync":
833
+ newConfig.autoSync = value === "enabled";
834
+ break;
835
+ case "cacheDir":
836
+ newConfig.cacheDir = value || void 0;
837
+ break;
838
+ }
839
+ try {
840
+ saveConfig(newConfig, false);
841
+ setConfig(newConfig);
842
+ setSaved(true);
843
+ setTimeout(() => setSaved(false), 2e3);
844
+ } catch (err) {
845
+ setError(`Failed to save: ${err}`);
846
+ setTimeout(() => setError(null), 3e3);
847
+ }
848
+ };
849
+ useInput4((input, key) => {
850
+ if (editing) {
851
+ if (key.return) {
852
+ handleSave(SETTINGS[sel], editValue);
853
+ setEditing(false);
854
+ } else if (key.escape) {
855
+ setEditing(false);
856
+ }
857
+ return;
858
+ }
859
+ if (key.upArrow) {
860
+ setSel((i) => Math.max(0, i - 1));
861
+ } else if (key.downArrow) {
862
+ setSel((i) => Math.min(SETTINGS.length - 1, i + 1));
863
+ } else if (key.return || input === " ") {
864
+ const setting = SETTINGS[sel];
865
+ if (setting.type === "toggle") {
866
+ const current = getCurrentValue(setting);
867
+ const newValue = current === "enabled" ? "disabled" : "enabled";
868
+ handleSave(setting, newValue);
869
+ } else if (setting.type === "select" && setting.options) {
870
+ const current = getCurrentValue(setting);
871
+ const idx = setting.options.indexOf(current);
872
+ const nextIdx = (idx + 1) % setting.options.length;
873
+ handleSave(setting, setting.options[nextIdx]);
874
+ } else if (setting.type === "text") {
875
+ setEditValue(getCurrentValue(setting));
876
+ setEditing(true);
877
+ }
878
+ }
726
879
  });
880
+ if (!config) {
881
+ return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
882
+ /* @__PURE__ */ jsx6(Text6, { bold: true, color: colors.primary, children: "SETTINGS" }),
883
+ error ? /* @__PURE__ */ jsxs6(Text6, { color: colors.danger, children: [
884
+ symbols.error,
885
+ " ",
886
+ error
887
+ ] }) : /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: "Loading..." })
888
+ ] });
889
+ }
727
890
  return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
728
891
  /* @__PURE__ */ jsx6(Text6, { bold: true, color: colors.primary, children: "SETTINGS" }),
729
- /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: "Configure SkillKit" }),
892
+ /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: "Configure SkillKit (changes save automatically)" }),
730
893
  /* @__PURE__ */ jsx6(Box6, { marginTop: 1, flexDirection: "column", children: SETTINGS.map((s, i) => {
731
894
  const isSel = i === sel;
732
- return /* @__PURE__ */ jsxs6(Text6, { inverse: isSel, children: [
733
- isSel ? symbols.pointer : " ",
734
- s.label.padEnd(16),
735
- " ",
736
- /* @__PURE__ */ jsx6(Text6, { color: colors.secondaryDim, children: s.value })
895
+ const value = getCurrentValue(s);
896
+ const isEditing = editing && isSel;
897
+ return /* @__PURE__ */ jsxs6(Box6, { children: [
898
+ /* @__PURE__ */ jsxs6(Text6, { inverse: isSel && !isEditing, children: [
899
+ isSel ? symbols.pointer : " ",
900
+ s.label.padEnd(16)
901
+ ] }),
902
+ isEditing ? /* @__PURE__ */ jsx6(Box6, { marginLeft: 1, children: /* @__PURE__ */ jsx6(
903
+ TextInput,
904
+ {
905
+ value: editValue,
906
+ onChange: setEditValue,
907
+ onSubmit: () => {
908
+ handleSave(s, editValue);
909
+ setEditing(false);
910
+ }
911
+ }
912
+ ) }) : /* @__PURE__ */ jsxs6(Text6, { color: colors.secondaryDim, children: [
913
+ " ",
914
+ value
915
+ ] }),
916
+ s.type === "toggle" && isSel && !isEditing && /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: " (space to toggle)" }),
917
+ s.type === "select" && isSel && !isEditing && /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: " (enter to cycle)" })
737
918
  ] }, s.id);
738
919
  }) }),
739
- /* @__PURE__ */ jsx6(Box6, { marginTop: 1, children: /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: "Enter=edit q=quit" }) })
920
+ /* @__PURE__ */ jsxs6(Box6, { marginTop: 1, children: [
921
+ saved && /* @__PURE__ */ jsxs6(Text6, { color: colors.success, children: [
922
+ symbols.check,
923
+ " Settings saved"
924
+ ] }),
925
+ error && /* @__PURE__ */ jsxs6(Text6, { color: colors.danger, children: [
926
+ symbols.error,
927
+ " ",
928
+ error
929
+ ] }),
930
+ !saved && !error && /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: editing ? "Enter=save Esc=cancel" : "Enter/Space=edit q=quit" })
931
+ ] })
740
932
  ] });
741
933
  }
742
934
 
743
935
  // src/screens/Recommend.tsx
744
936
  import { useState as useState9 } from "react";
745
- import { existsSync as existsSync2, mkdirSync as mkdirSync2, cpSync as cpSync2, rmSync as rmSync2 } from "fs";
746
- import { join as join3 } from "path";
937
+ import { existsSync as existsSync3, mkdirSync as mkdirSync2, cpSync as cpSync2, rmSync as rmSync2 } from "fs";
938
+ import { join as join4 } from "path";
747
939
  import { Box as Box7, Text as Text7, useInput as useInput5 } from "ink";
748
940
 
749
941
  // src/hooks/useRecommend.ts
750
- import { useState as useState8, useCallback as useCallback2, useEffect as useEffect5 } from "react";
942
+ import { useState as useState8, useCallback as useCallback2, useEffect as useEffect6 } from "react";
751
943
  import {
752
944
  RecommendationEngine,
753
945
  ContextManager,
@@ -875,7 +1067,7 @@ function useRecommend(projectPath = process.cwd()) {
875
1067
  const refresh = useCallback2(() => {
876
1068
  loadRecommendations();
877
1069
  }, [loadRecommendations]);
878
- useEffect5(() => {
1070
+ useEffect6(() => {
879
1071
  loadRecommendations();
880
1072
  }, [loadRecommendations]);
881
1073
  return {
@@ -965,11 +1157,11 @@ function Recommend({ rows = 24 }) {
965
1157
  const targetAgentType = agentType || await detectAgent2();
966
1158
  const adapter = getAdapter3(targetAgentType);
967
1159
  const installDir = getInstallDir(false, targetAgentType);
968
- if (!existsSync2(installDir)) {
1160
+ if (!existsSync3(installDir)) {
969
1161
  mkdirSync2(installDir, { recursive: true });
970
1162
  }
971
- const targetPath = join3(installDir, skillName);
972
- if (existsSync2(targetPath)) {
1163
+ const targetPath = join4(installDir, skillName);
1164
+ if (existsSync3(targetPath)) {
973
1165
  rmSync2(targetPath, { recursive: true, force: true });
974
1166
  }
975
1167
  cpSync2(skill.path, targetPath, { recursive: true, dereference: true });
@@ -1172,9 +1364,9 @@ function Recommend({ rows = 24 }) {
1172
1364
  }
1173
1365
 
1174
1366
  // src/screens/Translate.tsx
1175
- import { useState as useState10, useEffect as useEffect6 } from "react";
1176
- import { existsSync as existsSync3, readdirSync, readFileSync as readFileSync2, writeFileSync, mkdirSync as mkdirSync3 } from "fs";
1177
- import { join as join4 } from "path";
1367
+ import { useState as useState10, useEffect as useEffect7 } from "react";
1368
+ import { existsSync as existsSync4, readdirSync, readFileSync as readFileSync3, writeFileSync, mkdirSync as mkdirSync3 } from "fs";
1369
+ import { join as join5 } from "path";
1178
1370
  import { Box as Box8, Text as Text8, useInput as useInput6 } from "ink";
1179
1371
  import {
1180
1372
  translateSkill,
@@ -1192,17 +1384,17 @@ function Translate({ rows = 24 }) {
1192
1384
  const [preview, setPreview] = useState10("");
1193
1385
  const [result, setResult] = useState10(null);
1194
1386
  const [loading, setLoading] = useState10(false);
1195
- useEffect6(() => {
1387
+ useEffect7(() => {
1196
1388
  const loadSkills = () => {
1197
1389
  const installDir = getInstallDir(false);
1198
1390
  const foundSkills = [];
1199
- if (existsSync3(installDir)) {
1391
+ if (existsSync4(installDir)) {
1200
1392
  const dirs = readdirSync(installDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
1201
1393
  for (const dir of dirs) {
1202
- const skillPath = join4(installDir, dir);
1203
- const skillMdPath = join4(skillPath, "SKILL.md");
1204
- if (existsSync3(skillMdPath)) {
1205
- const content = readFileSync2(skillMdPath, "utf-8");
1394
+ const skillPath = join5(installDir, dir);
1395
+ const skillMdPath = join5(skillPath, "SKILL.md");
1396
+ if (existsSync4(skillMdPath)) {
1397
+ const content = readFileSync3(skillMdPath, "utf-8");
1206
1398
  foundSkills.push({
1207
1399
  name: dir,
1208
1400
  path: skillPath,
@@ -1215,7 +1407,7 @@ function Translate({ rows = 24 }) {
1215
1407
  };
1216
1408
  loadSkills();
1217
1409
  }, []);
1218
- useEffect6(() => {
1410
+ useEffect7(() => {
1219
1411
  const adapters = getAllAdapters4();
1220
1412
  const supportedAgents = getSupportedTranslationAgents();
1221
1413
  const agentList = adapters.filter((a) => supportedAgents.includes(a.type)).map((a) => ({
@@ -1252,12 +1444,12 @@ function Translate({ rows = 24 }) {
1252
1444
  return;
1253
1445
  }
1254
1446
  const adapter = getAdapter4(selectedAgent.type);
1255
- const targetDir = adapter?.skillsDir ? join4(process.cwd(), adapter.skillsDir) : join4(process.cwd(), `.${selectedAgent.type}/skills/`);
1256
- if (!existsSync3(targetDir)) {
1447
+ const targetDir = adapter?.skillsDir ? join5(process.cwd(), adapter.skillsDir) : join5(process.cwd(), `.${selectedAgent.type}/skills/`);
1448
+ if (!existsSync4(targetDir)) {
1257
1449
  mkdirSync3(targetDir, { recursive: true });
1258
1450
  }
1259
1451
  const filename = translationResult.filename || `${selectedSkill.name}.md`;
1260
- const targetPath = join4(targetDir, filename);
1452
+ const targetPath = join5(targetDir, filename);
1261
1453
  writeFileSync(targetPath, translationResult.content, "utf-8");
1262
1454
  setResult({
1263
1455
  success: true,
@@ -1403,7 +1595,7 @@ function Translate({ rows = 24 }) {
1403
1595
  }
1404
1596
 
1405
1597
  // src/screens/Context.tsx
1406
- import { useState as useState11, useEffect as useEffect7 } from "react";
1598
+ import { useState as useState11, useEffect as useEffect8 } from "react";
1407
1599
  import { Box as Box9, Text as Text9, useInput as useInput7 } from "ink";
1408
1600
  import {
1409
1601
  loadContext,
@@ -1423,7 +1615,7 @@ function Context({ rows = 24 }) {
1423
1615
  const [message, setMessage] = useState11(null);
1424
1616
  const [error, setError] = useState11(null);
1425
1617
  const projectPath = process.cwd();
1426
- useEffect7(() => {
1618
+ useEffect8(() => {
1427
1619
  const load = async () => {
1428
1620
  setLoading(true);
1429
1621
  try {
@@ -1652,7 +1844,7 @@ function Context({ rows = 24 }) {
1652
1844
  }
1653
1845
 
1654
1846
  // src/screens/Workflow.tsx
1655
- import { useState as useState12, useEffect as useEffect8 } from "react";
1847
+ import { useState as useState12, useEffect as useEffect9 } from "react";
1656
1848
  import { Box as Box10, Text as Text10, useInput as useInput8 } from "ink";
1657
1849
  import { listWorkflows } from "@skillkit/core";
1658
1850
  import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
@@ -1665,7 +1857,7 @@ function Workflow({ rows = 24 }) {
1665
1857
  const maxVisible = Math.max(5, rows - 8);
1666
1858
  const start = Math.max(0, Math.min(sel - Math.floor(maxVisible / 2), workflows.length - maxVisible));
1667
1859
  const visible = workflows.slice(start, start + maxVisible);
1668
- useEffect8(() => {
1860
+ useEffect9(() => {
1669
1861
  loadWorkflows();
1670
1862
  }, []);
1671
1863
  const loadWorkflows = () => {
@@ -1745,7 +1937,7 @@ function Workflow({ rows = 24 }) {
1745
1937
  }
1746
1938
 
1747
1939
  // src/screens/Execute.tsx
1748
- import { useState as useState13, useEffect as useEffect9 } from "react";
1940
+ import { useState as useState13, useEffect as useEffect10 } from "react";
1749
1941
  import { Box as Box11, Text as Text11, useInput as useInput9 } from "ink";
1750
1942
  import { createSessionManager } from "@skillkit/core";
1751
1943
  import { jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
@@ -1753,7 +1945,7 @@ function Execute({ rows = 24 }) {
1753
1945
  const [session, setSession] = useState13(null);
1754
1946
  const [loading, setLoading] = useState13(true);
1755
1947
  const maxVisible = Math.max(5, rows - 10);
1756
- useEffect9(() => {
1948
+ useEffect10(() => {
1757
1949
  loadSession();
1758
1950
  const interval = setInterval(loadSession, 1e3);
1759
1951
  return () => clearInterval(interval);
@@ -1858,7 +2050,7 @@ function Execute({ rows = 24 }) {
1858
2050
  }
1859
2051
 
1860
2052
  // src/screens/History.tsx
1861
- import { useState as useState14, useEffect as useEffect10 } from "react";
2053
+ import { useState as useState14, useEffect as useEffect11 } from "react";
1862
2054
  import { Box as Box12, Text as Text12, useInput as useInput10 } from "ink";
1863
2055
  import { createSessionManager as createSessionManager2 } from "@skillkit/core";
1864
2056
  import { jsx as jsx12, jsxs as jsxs12 } from "react/jsx-runtime";
@@ -1870,7 +2062,7 @@ function History({ rows = 24 }) {
1870
2062
  const maxVisible = Math.max(5, rows - 8);
1871
2063
  const start = Math.max(0, Math.min(sel - Math.floor(maxVisible / 2), history.length - maxVisible));
1872
2064
  const visible = history.slice(start, start + maxVisible);
1873
- useEffect10(() => {
2065
+ useEffect11(() => {
1874
2066
  loadHistory();
1875
2067
  }, []);
1876
2068
  const loadHistory = () => {
@@ -1981,7 +2173,7 @@ function History({ rows = 24 }) {
1981
2173
  }
1982
2174
 
1983
2175
  // src/screens/Marketplace.tsx
1984
- import { useState as useState15, useEffect as useEffect11 } from "react";
2176
+ import { useState as useState15, useEffect as useEffect12 } from "react";
1985
2177
  import { Box as Box13, Text as Text13, useInput as useInput11 } from "ink";
1986
2178
  import { jsx as jsx13, jsxs as jsxs13 } from "react/jsx-runtime";
1987
2179
  var SKILL_SOURCES = [
@@ -2001,7 +2193,7 @@ function Marketplace({ rows = 24 }) {
2001
2193
  const maxVisible = Math.max(5, rows - 10);
2002
2194
  const start = Math.max(0, Math.min(sel - Math.floor(maxVisible / 2), filtered.length - maxVisible));
2003
2195
  const visible = filtered.slice(start, start + maxVisible);
2004
- useEffect11(() => {
2196
+ useEffect12(() => {
2005
2197
  loadMarketplace();
2006
2198
  }, []);
2007
2199
  const loadMarketplace = async () => {
@@ -2140,7 +2332,7 @@ function Marketplace({ rows = 24 }) {
2140
2332
  }
2141
2333
 
2142
2334
  // src/screens/Memory.tsx
2143
- import { useState as useState16, useEffect as useEffect12 } from "react";
2335
+ import { useState as useState16, useEffect as useEffect13 } from "react";
2144
2336
  import { Box as Box14, Text as Text14, useInput as useInput12 } from "ink";
2145
2337
  import {
2146
2338
  ObservationStore,
@@ -2165,7 +2357,7 @@ function Memory({ rows = 24 }) {
2165
2357
  const currentList = tab === "search" ? searchResults : learnings;
2166
2358
  const start = Math.max(0, Math.min(sel - Math.floor(maxVisible / 2), currentList.length - maxVisible));
2167
2359
  const visible = currentList.slice(start, start + maxVisible);
2168
- useEffect12(() => {
2360
+ useEffect13(() => {
2169
2361
  loadMemory();
2170
2362
  }, [isGlobal]);
2171
2363
  const loadMemory = () => {
@@ -2400,10 +2592,806 @@ function Memory({ rows = 24 }) {
2400
2592
  ] });
2401
2593
  }
2402
2594
 
2403
- // src/App.tsx
2595
+ // src/screens/Team.tsx
2596
+ import { useState as useState17, useEffect as useEffect14 } from "react";
2597
+ import { Box as Box15, Text as Text15, useInput as useInput13 } from "ink";
2404
2598
  import { jsx as jsx15, jsxs as jsxs15 } from "react/jsx-runtime";
2599
+ function Team({ rows = 24 }) {
2600
+ const [config, setConfig] = useState17(null);
2601
+ const [skills, setSkills] = useState17([]);
2602
+ const [loading, setLoading] = useState17(true);
2603
+ const [error, setError] = useState17(null);
2604
+ const [sel, setSel] = useState17(0);
2605
+ const [message, setMessage] = useState17(null);
2606
+ const maxVisible = Math.max(5, rows - 12);
2607
+ const start = Math.max(0, Math.min(sel - Math.floor(maxVisible / 2), skills.length - maxVisible));
2608
+ const visible = skills.slice(start, start + maxVisible);
2609
+ useEffect14(() => {
2610
+ loadTeam();
2611
+ }, []);
2612
+ const loadTeam = async () => {
2613
+ setLoading(true);
2614
+ setError(null);
2615
+ try {
2616
+ const { createTeamManager } = await import("@skillkit/core");
2617
+ const manager = createTeamManager(process.cwd());
2618
+ const teamConfig = manager.load();
2619
+ if (!teamConfig) {
2620
+ setConfig(null);
2621
+ setSkills([]);
2622
+ setError("Team not initialized. Run `skillkit team init` first.");
2623
+ } else {
2624
+ setConfig(teamConfig);
2625
+ const sharedSkills = manager.listSharedSkills();
2626
+ setSkills(sharedSkills);
2627
+ setSel((s) => Math.min(s, Math.max(0, sharedSkills.length - 1)));
2628
+ }
2629
+ } catch (e) {
2630
+ setError(e instanceof Error ? e.message : "Failed to load team");
2631
+ }
2632
+ setLoading(false);
2633
+ };
2634
+ const syncTeam = async () => {
2635
+ if (!config) return;
2636
+ setLoading(true);
2637
+ setMessage(null);
2638
+ try {
2639
+ const { createTeamManager } = await import("@skillkit/core");
2640
+ const manager = createTeamManager(process.cwd());
2641
+ manager.load();
2642
+ const result = await manager.sync();
2643
+ const changes = [...result.added, ...result.updated];
2644
+ if (changes.length > 0) {
2645
+ setMessage(`Synced: ${changes.join(", ")}`);
2646
+ } else {
2647
+ setMessage("Already up to date");
2648
+ }
2649
+ const sharedSkills = manager.listSharedSkills();
2650
+ setSkills(sharedSkills);
2651
+ setSel((s) => Math.min(s, Math.max(0, sharedSkills.length - 1)));
2652
+ } catch (e) {
2653
+ setError(e instanceof Error ? e.message : "Sync failed");
2654
+ }
2655
+ setLoading(false);
2656
+ };
2657
+ const importSkill = async (skillName) => {
2658
+ if (!config) return;
2659
+ setLoading(true);
2660
+ setMessage(null);
2661
+ try {
2662
+ const { createTeamManager } = await import("@skillkit/core");
2663
+ const manager = createTeamManager(process.cwd());
2664
+ manager.load();
2665
+ const result = await manager.importSkill(skillName, { overwrite: false });
2666
+ if (result.success) {
2667
+ setMessage(`Imported: ${skillName}`);
2668
+ } else {
2669
+ setError(result.error || "Import failed");
2670
+ }
2671
+ } catch (e) {
2672
+ setError(e instanceof Error ? e.message : "Import failed");
2673
+ }
2674
+ setLoading(false);
2675
+ };
2676
+ useInput13((input, key) => {
2677
+ if (loading) return;
2678
+ if (skills.length === 0 && (key.upArrow || key.downArrow)) return;
2679
+ if (key.upArrow) setSel((i) => Math.max(0, i - 1));
2680
+ else if (key.downArrow) setSel((i) => Math.min(Math.max(0, skills.length - 1), i + 1));
2681
+ else if (input === "r") loadTeam();
2682
+ else if (input === "s") syncTeam();
2683
+ else if (key.return && skills[sel]) {
2684
+ importSkill(skills[sel].name);
2685
+ }
2686
+ });
2687
+ if (loading) {
2688
+ return /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", padding: 1, children: [
2689
+ /* @__PURE__ */ jsx15(Text15, { color: colors.primary, bold: true, children: "Team Collaboration" }),
2690
+ /* @__PURE__ */ jsx15(Box15, { marginTop: 1, children: /* @__PURE__ */ jsxs15(Text15, { color: colors.secondaryDim, children: [
2691
+ symbols.spinner[0],
2692
+ " Loading..."
2693
+ ] }) })
2694
+ ] });
2695
+ }
2696
+ if (!config) {
2697
+ return /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", padding: 1, children: [
2698
+ /* @__PURE__ */ jsx15(Text15, { color: colors.primary, bold: true, children: "Team Collaboration" }),
2699
+ /* @__PURE__ */ jsxs15(Box15, { marginTop: 1, flexDirection: "column", children: [
2700
+ /* @__PURE__ */ jsxs15(Text15, { color: colors.secondaryDim, children: [
2701
+ symbols.warning,
2702
+ " Team not initialized"
2703
+ ] }),
2704
+ /* @__PURE__ */ jsx15(Text15, { color: colors.secondaryDim, dimColor: true, children: 'Run: skillkit team init --name "Team Name" --registry <url>' })
2705
+ ] }),
2706
+ /* @__PURE__ */ jsx15(Box15, { marginTop: 1, children: /* @__PURE__ */ jsx15(Text15, { dimColor: true, children: "[r] Refresh" }) })
2707
+ ] });
2708
+ }
2709
+ return /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", padding: 1, children: [
2710
+ /* @__PURE__ */ jsxs15(Text15, { color: colors.primary, bold: true, children: [
2711
+ "Team: ",
2712
+ config.teamName
2713
+ ] }),
2714
+ /* @__PURE__ */ jsxs15(Text15, { color: colors.secondaryDim, dimColor: true, children: [
2715
+ "Registry: ",
2716
+ config.registryUrl
2717
+ ] }),
2718
+ error && /* @__PURE__ */ jsx15(Box15, { marginTop: 1, children: /* @__PURE__ */ jsxs15(Text15, { color: "red", children: [
2719
+ symbols.error,
2720
+ " ",
2721
+ error
2722
+ ] }) }),
2723
+ message && /* @__PURE__ */ jsx15(Box15, { marginTop: 1, children: /* @__PURE__ */ jsxs15(Text15, { color: "green", children: [
2724
+ symbols.success,
2725
+ " ",
2726
+ message
2727
+ ] }) }),
2728
+ /* @__PURE__ */ jsxs15(Box15, { marginTop: 1, flexDirection: "column", children: [
2729
+ /* @__PURE__ */ jsxs15(Text15, { color: colors.secondaryDim, bold: true, children: [
2730
+ "Shared Skills (",
2731
+ skills.length,
2732
+ ")"
2733
+ ] }),
2734
+ skills.length === 0 ? /* @__PURE__ */ jsx15(Text15, { color: colors.secondaryDim, dimColor: true, children: "No shared skills. Use `skillkit team share --name <skill>` to share." }) : /* @__PURE__ */ jsx15(Box15, { flexDirection: "column", marginTop: 1, children: visible.map((skill, i) => {
2735
+ const actualIndex = start + i;
2736
+ const isSelected = actualIndex === sel;
2737
+ return /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", children: [
2738
+ /* @__PURE__ */ jsxs15(Text15, { children: [
2739
+ isSelected ? symbols.pointer : " ",
2740
+ " ",
2741
+ /* @__PURE__ */ jsx15(Text15, { color: isSelected ? colors.primary : colors.secondaryDim, bold: isSelected, children: skill.name }),
2742
+ /* @__PURE__ */ jsxs15(Text15, { dimColor: true, children: [
2743
+ " v",
2744
+ skill.version
2745
+ ] }),
2746
+ /* @__PURE__ */ jsxs15(Text15, { dimColor: true, children: [
2747
+ " by ",
2748
+ skill.author
2749
+ ] }),
2750
+ skill.downloads !== void 0 && /* @__PURE__ */ jsxs15(Text15, { dimColor: true, children: [
2751
+ " | ",
2752
+ skill.downloads,
2753
+ " downloads"
2754
+ ] })
2755
+ ] }),
2756
+ skill.description && isSelected && /* @__PURE__ */ jsxs15(Text15, { color: colors.secondaryDim, dimColor: true, children: [
2757
+ " ",
2758
+ skill.description
2759
+ ] })
2760
+ ] }, skill.name);
2761
+ }) })
2762
+ ] }),
2763
+ /* @__PURE__ */ jsx15(Box15, { marginTop: 1, borderStyle: "single", borderColor: colors.borderDim, paddingX: 1, children: /* @__PURE__ */ jsx15(Text15, { dimColor: true, children: "[\u2191\u2193] Navigate [Enter] Import [s] Sync [r] Refresh" }) })
2764
+ ] });
2765
+ }
2766
+
2767
+ // src/screens/Plugins.tsx
2768
+ import { useState as useState18, useEffect as useEffect15 } from "react";
2769
+ import { Box as Box16, Text as Text16, useInput as useInput14 } from "ink";
2770
+ import { jsx as jsx16, jsxs as jsxs16 } from "react/jsx-runtime";
2771
+ function Plugins({ rows = 24 }) {
2772
+ const [plugins, setPlugins] = useState18([]);
2773
+ const [loading, setLoading] = useState18(true);
2774
+ const [error, setError] = useState18(null);
2775
+ const [sel, setSel] = useState18(0);
2776
+ const [message, setMessage] = useState18(null);
2777
+ const maxVisible = Math.max(5, rows - 12);
2778
+ const start = Math.max(0, Math.min(sel - Math.floor(maxVisible / 2), plugins.length - maxVisible));
2779
+ const visible = plugins.slice(start, start + maxVisible);
2780
+ useEffect15(() => {
2781
+ loadPlugins();
2782
+ }, []);
2783
+ const loadPlugins = async () => {
2784
+ setLoading(true);
2785
+ setError(null);
2786
+ try {
2787
+ const { createPluginManager, loadPluginsFromDirectory } = await import("@skillkit/core");
2788
+ const { join: join7 } = await import("path");
2789
+ const manager = createPluginManager(process.cwd());
2790
+ const pluginsDir = join7(process.cwd(), ".skillkit", "plugins");
2791
+ try {
2792
+ const loadedPlugins = await loadPluginsFromDirectory(pluginsDir);
2793
+ for (const plugin of loadedPlugins) {
2794
+ if (!manager.getPlugin(plugin.metadata.name)) {
2795
+ await manager.register(plugin);
2796
+ }
2797
+ }
2798
+ } catch (err) {
2799
+ if (err && typeof err === "object" && "code" in err && err.code !== "ENOENT") {
2800
+ throw err;
2801
+ }
2802
+ }
2803
+ const allPlugins = manager.listPlugins();
2804
+ const pluginInfos = allPlugins.map((p) => {
2805
+ const plugin = manager.getPlugin(p.name);
2806
+ return {
2807
+ name: p.name,
2808
+ version: p.version,
2809
+ description: p.description,
2810
+ author: p.author,
2811
+ enabled: manager.isPluginEnabled(p.name),
2812
+ translators: plugin?.translators?.map((t) => t.agentType),
2813
+ providers: plugin?.providers?.map((pr) => pr.providerName),
2814
+ commands: plugin?.commands?.map((c) => c.name)
2815
+ };
2816
+ });
2817
+ setPlugins(pluginInfos);
2818
+ } catch (e) {
2819
+ setError(e instanceof Error ? e.message : "Failed to load plugins");
2820
+ }
2821
+ setLoading(false);
2822
+ };
2823
+ const togglePlugin = async (pluginName, currentEnabled) => {
2824
+ setLoading(true);
2825
+ setMessage(null);
2826
+ try {
2827
+ const { createPluginManager, loadPluginsFromDirectory } = await import("@skillkit/core");
2828
+ const { join: join7 } = await import("path");
2829
+ const manager = createPluginManager(process.cwd());
2830
+ const pluginsDir = join7(process.cwd(), ".skillkit", "plugins");
2831
+ try {
2832
+ const loadedPlugins = await loadPluginsFromDirectory(pluginsDir);
2833
+ for (const plugin of loadedPlugins) {
2834
+ if (!manager.getPlugin(plugin.metadata.name)) {
2835
+ await manager.register(plugin);
2836
+ }
2837
+ }
2838
+ } catch (err) {
2839
+ if (err && typeof err === "object" && "code" in err && err.code !== "ENOENT") {
2840
+ throw err;
2841
+ }
2842
+ }
2843
+ if (currentEnabled) {
2844
+ manager.disablePlugin(pluginName);
2845
+ setMessage(`Disabled: ${pluginName}`);
2846
+ } else {
2847
+ manager.enablePlugin(pluginName);
2848
+ setMessage(`Enabled: ${pluginName}`);
2849
+ }
2850
+ await loadPlugins();
2851
+ } catch (e) {
2852
+ setError(e instanceof Error ? e.message : "Toggle failed");
2853
+ setLoading(false);
2854
+ }
2855
+ };
2856
+ useInput14((input, key) => {
2857
+ if (loading) return;
2858
+ if (plugins.length === 0 && (key.upArrow || key.downArrow)) return;
2859
+ if (key.upArrow) setSel((i) => Math.max(0, i - 1));
2860
+ else if (key.downArrow) setSel((i) => Math.min(Math.max(0, plugins.length - 1), i + 1));
2861
+ else if (input === "r") loadPlugins();
2862
+ else if (input === "e" && plugins[sel]) {
2863
+ togglePlugin(plugins[sel].name, plugins[sel].enabled);
2864
+ } else if (key.return && plugins[sel]) {
2865
+ togglePlugin(plugins[sel].name, plugins[sel].enabled);
2866
+ }
2867
+ });
2868
+ if (loading) {
2869
+ return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", padding: 1, children: [
2870
+ /* @__PURE__ */ jsx16(Text16, { color: colors.primary, bold: true, children: "Plugin Manager" }),
2871
+ /* @__PURE__ */ jsx16(Box16, { marginTop: 1, children: /* @__PURE__ */ jsxs16(Text16, { color: colors.secondaryDim, children: [
2872
+ symbols.spinner[0],
2873
+ " Loading..."
2874
+ ] }) })
2875
+ ] });
2876
+ }
2877
+ return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", padding: 1, children: [
2878
+ /* @__PURE__ */ jsx16(Text16, { color: colors.primary, bold: true, children: "Plugin Manager" }),
2879
+ /* @__PURE__ */ jsx16(Text16, { color: colors.secondaryDim, dimColor: true, children: "Manage SkillKit extensions" }),
2880
+ error && /* @__PURE__ */ jsx16(Box16, { marginTop: 1, children: /* @__PURE__ */ jsxs16(Text16, { color: "red", children: [
2881
+ symbols.error,
2882
+ " ",
2883
+ error
2884
+ ] }) }),
2885
+ message && /* @__PURE__ */ jsx16(Box16, { marginTop: 1, children: /* @__PURE__ */ jsxs16(Text16, { color: "green", children: [
2886
+ symbols.success,
2887
+ " ",
2888
+ message
2889
+ ] }) }),
2890
+ /* @__PURE__ */ jsxs16(Box16, { marginTop: 1, flexDirection: "column", children: [
2891
+ /* @__PURE__ */ jsxs16(Text16, { color: colors.secondaryDim, bold: true, children: [
2892
+ "Installed Plugins (",
2893
+ plugins.length,
2894
+ ")"
2895
+ ] }),
2896
+ plugins.length === 0 ? /* @__PURE__ */ jsxs16(Box16, { marginTop: 1, flexDirection: "column", children: [
2897
+ /* @__PURE__ */ jsx16(Text16, { color: colors.secondaryDim, dimColor: true, children: "No plugins installed." }),
2898
+ /* @__PURE__ */ jsx16(Text16, { color: colors.secondaryDim, dimColor: true, children: "Use: skillkit plugin install --source <path-or-package>" })
2899
+ ] }) : /* @__PURE__ */ jsx16(Box16, { flexDirection: "column", marginTop: 1, children: visible.map((plugin, i) => {
2900
+ const actualIndex = start + i;
2901
+ const isSelected = actualIndex === sel;
2902
+ const statusColor = plugin.enabled ? "green" : "gray";
2903
+ const statusText = plugin.enabled ? "enabled" : "disabled";
2904
+ return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", children: [
2905
+ /* @__PURE__ */ jsxs16(Text16, { children: [
2906
+ isSelected ? symbols.pointer : " ",
2907
+ " ",
2908
+ /* @__PURE__ */ jsx16(Text16, { color: isSelected ? colors.primary : colors.secondaryDim, bold: isSelected, children: plugin.name }),
2909
+ /* @__PURE__ */ jsxs16(Text16, { dimColor: true, children: [
2910
+ " v",
2911
+ plugin.version
2912
+ ] }),
2913
+ /* @__PURE__ */ jsxs16(Text16, { color: statusColor, children: [
2914
+ " [",
2915
+ statusText,
2916
+ "]"
2917
+ ] })
2918
+ ] }),
2919
+ isSelected && /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", marginLeft: 3, children: [
2920
+ plugin.description && /* @__PURE__ */ jsx16(Text16, { color: colors.secondaryDim, dimColor: true, children: plugin.description }),
2921
+ plugin.author && /* @__PURE__ */ jsxs16(Text16, { dimColor: true, children: [
2922
+ "Author: ",
2923
+ plugin.author
2924
+ ] }),
2925
+ plugin.translators && plugin.translators.length > 0 && /* @__PURE__ */ jsxs16(Text16, { dimColor: true, children: [
2926
+ "Translators: ",
2927
+ plugin.translators.join(", ")
2928
+ ] }),
2929
+ plugin.providers && plugin.providers.length > 0 && /* @__PURE__ */ jsxs16(Text16, { dimColor: true, children: [
2930
+ "Providers: ",
2931
+ plugin.providers.join(", ")
2932
+ ] }),
2933
+ plugin.commands && plugin.commands.length > 0 && /* @__PURE__ */ jsxs16(Text16, { dimColor: true, children: [
2934
+ "Commands: ",
2935
+ plugin.commands.join(", ")
2936
+ ] })
2937
+ ] })
2938
+ ] }, plugin.name);
2939
+ }) })
2940
+ ] }),
2941
+ /* @__PURE__ */ jsx16(Box16, { marginTop: 1, borderStyle: "single", borderColor: colors.borderDim, paddingX: 1, children: /* @__PURE__ */ jsx16(Text16, { dimColor: true, children: "[\u2191\u2193] Navigate [e/Enter] Toggle Enable/Disable [r] Refresh" }) })
2942
+ ] });
2943
+ }
2944
+
2945
+ // src/screens/Methodology.tsx
2946
+ import { useState as useState19, useEffect as useEffect16, useMemo } from "react";
2947
+ import { Box as Box17, Text as Text17, useInput as useInput15 } from "ink";
2948
+ import {
2949
+ MethodologyManager
2950
+ } from "@skillkit/core";
2951
+ import { Fragment as Fragment2, jsx as jsx17, jsxs as jsxs17 } from "react/jsx-runtime";
2952
+ function Methodology({ rows = 24 }) {
2953
+ const [packs, setPacks] = useState19([]);
2954
+ const [selectedPack, setSelectedPack] = useState19(null);
2955
+ const [skills, setSkills] = useState19([]);
2956
+ const [loading, setLoading] = useState19(true);
2957
+ const [view, setView] = useState19("packs");
2958
+ const [sel, setSel] = useState19(0);
2959
+ const [error, setError] = useState19(null);
2960
+ const [message, setMessage] = useState19(null);
2961
+ const manager = useMemo(() => new MethodologyManager({
2962
+ projectPath: process.cwd()
2963
+ }), []);
2964
+ const maxVisible = Math.max(5, rows - 10);
2965
+ useEffect16(() => {
2966
+ loadPacks();
2967
+ }, []);
2968
+ const loadPacks = async () => {
2969
+ setLoading(true);
2970
+ setError(null);
2971
+ try {
2972
+ const loadedPacks = await manager.listAvailablePacks();
2973
+ setPacks(loadedPacks);
2974
+ } catch (e) {
2975
+ setError(e instanceof Error ? e.message : "Failed to load methodology packs");
2976
+ }
2977
+ setLoading(false);
2978
+ };
2979
+ const loadSkills = async (pack) => {
2980
+ setLoading(true);
2981
+ setError(null);
2982
+ try {
2983
+ const loader = manager.getLoader();
2984
+ const loadedSkills = await loader.loadPackSkills(pack.name);
2985
+ setSkills(loadedSkills);
2986
+ setSelectedPack(pack);
2987
+ setView("skills");
2988
+ setSel(0);
2989
+ } catch (e) {
2990
+ setError(e instanceof Error ? e.message : "Failed to load skills");
2991
+ }
2992
+ setLoading(false);
2993
+ };
2994
+ const installPack = async (pack) => {
2995
+ setLoading(true);
2996
+ setMessage(null);
2997
+ try {
2998
+ await manager.installPack(pack.name);
2999
+ setMessage(`Installed ${pack.name} methodology pack`);
3000
+ await loadPacks();
3001
+ } catch (e) {
3002
+ setError(e instanceof Error ? e.message : "Failed to install pack");
3003
+ }
3004
+ setLoading(false);
3005
+ };
3006
+ const items = view === "packs" ? packs : skills;
3007
+ const start = Math.max(0, Math.min(sel - Math.floor(maxVisible / 2), items.length - maxVisible));
3008
+ const visible = items.slice(start, start + maxVisible);
3009
+ useInput15((input, key) => {
3010
+ if (loading) return;
3011
+ if (key.upArrow) setSel((i) => Math.max(0, i - 1));
3012
+ else if (key.downArrow) setSel((i) => Math.min(items.length - 1, i + 1));
3013
+ else if (input === "r") {
3014
+ if (view === "packs") loadPacks();
3015
+ else if (selectedPack) loadSkills(selectedPack);
3016
+ } else if (key.escape || input === "b") {
3017
+ if (view === "skills") {
3018
+ setView("packs");
3019
+ setSel(0);
3020
+ setSelectedPack(null);
3021
+ }
3022
+ } else if (key.return) {
3023
+ if (view === "packs" && packs[sel]) {
3024
+ loadSkills(packs[sel]);
3025
+ }
3026
+ } else if (input === "i" && view === "packs" && packs[sel]) {
3027
+ installPack(packs[sel]);
3028
+ }
3029
+ });
3030
+ const renderPackItem = (pack, idx) => {
3031
+ const isSel = idx === sel;
3032
+ return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", children: [
3033
+ /* @__PURE__ */ jsxs17(Text17, { inverse: isSel, children: [
3034
+ isSel ? symbols.pointer : " ",
3035
+ " ",
3036
+ pack.name,
3037
+ " ",
3038
+ /* @__PURE__ */ jsxs17(Text17, { dimColor: true, children: [
3039
+ "v",
3040
+ pack.version
3041
+ ] })
3042
+ ] }),
3043
+ isSel && /* @__PURE__ */ jsxs17(Fragment2, { children: [
3044
+ /* @__PURE__ */ jsxs17(Text17, { dimColor: true, children: [
3045
+ " ",
3046
+ pack.description
3047
+ ] }),
3048
+ /* @__PURE__ */ jsxs17(Text17, { dimColor: true, children: [
3049
+ " ",
3050
+ pack.skills.length,
3051
+ " skill(s) | Tags: ",
3052
+ pack.tags?.join(", ") || "none"
3053
+ ] })
3054
+ ] })
3055
+ ] }, pack.name);
3056
+ };
3057
+ const renderSkillItem = (skill, idx) => {
3058
+ const isSel = idx === sel;
3059
+ return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", children: [
3060
+ /* @__PURE__ */ jsxs17(Text17, { inverse: isSel, children: [
3061
+ isSel ? symbols.pointer : " ",
3062
+ " ",
3063
+ skill.name
3064
+ ] }),
3065
+ isSel && skill.description && /* @__PURE__ */ jsxs17(Text17, { dimColor: true, children: [
3066
+ " ",
3067
+ skill.description
3068
+ ] }),
3069
+ isSel && skill.tags && /* @__PURE__ */ jsxs17(Text17, { dimColor: true, children: [
3070
+ " Tags: ",
3071
+ skill.tags.join(", ")
3072
+ ] })
3073
+ ] }, skill.name);
3074
+ };
3075
+ return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", children: [
3076
+ /* @__PURE__ */ jsx17(Text17, { bold: true, color: colors.primary, children: view === "packs" ? "METHODOLOGY PACKS" : `${selectedPack?.name.toUpperCase()} SKILLS` }),
3077
+ /* @__PURE__ */ jsx17(Text17, { dimColor: true, children: view === "packs" ? `${packs.length} pack(s) available` : `${skills.length} skill(s) in pack` }),
3078
+ loading && /* @__PURE__ */ jsx17(Text17, { color: "yellow", children: "Loading..." }),
3079
+ error && /* @__PURE__ */ jsxs17(Text17, { color: "red", children: [
3080
+ symbols.error,
3081
+ " ",
3082
+ error
3083
+ ] }),
3084
+ message && /* @__PURE__ */ jsxs17(Text17, { color: "green", children: [
3085
+ symbols.success,
3086
+ " ",
3087
+ message
3088
+ ] }),
3089
+ !loading && items.length === 0 && /* @__PURE__ */ jsx17(Box17, { marginTop: 1, children: /* @__PURE__ */ jsxs17(Text17, { dimColor: true, children: [
3090
+ "No ",
3091
+ view === "packs" ? "methodology packs" : "skills",
3092
+ " found."
3093
+ ] }) }),
3094
+ !loading && items.length > 0 && /* @__PURE__ */ jsxs17(Box17, { marginTop: 1, flexDirection: "column", children: [
3095
+ start > 0 && /* @__PURE__ */ jsxs17(Text17, { dimColor: true, children: [
3096
+ " ",
3097
+ symbols.arrowUp,
3098
+ " ",
3099
+ start,
3100
+ " more"
3101
+ ] }),
3102
+ view === "packs" ? visible.map((pack, i) => renderPackItem(pack, start + i)) : visible.map((skill, i) => renderSkillItem(skill, start + i)),
3103
+ start + maxVisible < items.length && /* @__PURE__ */ jsxs17(Text17, { dimColor: true, children: [
3104
+ " ",
3105
+ symbols.arrowDown,
3106
+ " ",
3107
+ items.length - start - maxVisible,
3108
+ " more"
3109
+ ] })
3110
+ ] }),
3111
+ /* @__PURE__ */ jsx17(Box17, { marginTop: 1, flexDirection: "column", children: view === "packs" ? /* @__PURE__ */ jsx17(Text17, { dimColor: true, children: "Enter=view skills i=install r=refresh q=quit" }) : /* @__PURE__ */ jsx17(Text17, { dimColor: true, children: "b/Esc=back r=refresh q=quit" }) })
3112
+ ] });
3113
+ }
3114
+
3115
+ // src/screens/Plan.tsx
3116
+ import { useState as useState20, useEffect as useEffect17, useMemo as useMemo2 } from "react";
3117
+ import { Box as Box18, Text as Text18, useInput as useInput16 } from "ink";
3118
+ import {
3119
+ PlanParser,
3120
+ PlanValidator,
3121
+ PlanExecutor
3122
+ } from "@skillkit/core";
3123
+ import * as fs from "fs";
3124
+ import * as path from "path";
3125
+ import { Fragment as Fragment3, jsx as jsx18, jsxs as jsxs18 } from "react/jsx-runtime";
3126
+ function Plan({ rows = 24 }) {
3127
+ const [planFiles, setPlanFiles] = useState20([]);
3128
+ const [selectedPlan, setSelectedPlan] = useState20(null);
3129
+ const [selectedTask, setSelectedTask] = useState20(null);
3130
+ const [loading, setLoading] = useState20(true);
3131
+ const [view, setView] = useState20("plans");
3132
+ const [sel, setSel] = useState20(0);
3133
+ const [error, setError] = useState20(null);
3134
+ const [executing, setExecuting] = useState20(false);
3135
+ const [message, setMessage] = useState20(null);
3136
+ const parser = useMemo2(() => new PlanParser(), []);
3137
+ const validator = useMemo2(() => new PlanValidator(), []);
3138
+ const maxVisible = Math.max(5, rows - 10);
3139
+ useEffect17(() => {
3140
+ loadPlans();
3141
+ }, []);
3142
+ const loadPlans = async () => {
3143
+ setLoading(true);
3144
+ setError(null);
3145
+ try {
3146
+ const cwd = process.cwd();
3147
+ const files = [];
3148
+ const searchPaths = [
3149
+ cwd,
3150
+ path.join(cwd, "plans"),
3151
+ path.join(cwd, ".skillkit", "plans")
3152
+ ];
3153
+ for (const searchPath of searchPaths) {
3154
+ if (fs.existsSync(searchPath)) {
3155
+ const entries = fs.readdirSync(searchPath, { withFileTypes: true });
3156
+ for (const entry of entries) {
3157
+ if (entry.isFile() && (entry.name.endsWith(".plan.md") || entry.name.endsWith("-plan.md"))) {
3158
+ const filePath = path.join(searchPath, entry.name);
3159
+ const content = fs.readFileSync(filePath, "utf-8");
3160
+ try {
3161
+ const plan = parser.parse(content);
3162
+ const validation = validator.validate(plan);
3163
+ const errorIssue = validation.issues.find((i) => i.type === "error");
3164
+ files.push({
3165
+ name: entry.name,
3166
+ path: filePath,
3167
+ plan,
3168
+ valid: validation.valid,
3169
+ error: errorIssue?.message
3170
+ });
3171
+ } catch {
3172
+ files.push({
3173
+ name: entry.name,
3174
+ path: filePath,
3175
+ valid: false,
3176
+ error: "Failed to parse plan"
3177
+ });
3178
+ }
3179
+ }
3180
+ }
3181
+ }
3182
+ }
3183
+ setPlanFiles(files);
3184
+ } catch (e) {
3185
+ setError(e instanceof Error ? e.message : "Failed to load plans");
3186
+ }
3187
+ setLoading(false);
3188
+ };
3189
+ const selectPlan = (planFile) => {
3190
+ if (planFile.plan) {
3191
+ setSelectedPlan(planFile);
3192
+ setView("tasks");
3193
+ setSel(0);
3194
+ }
3195
+ };
3196
+ const selectTask = (task) => {
3197
+ setSelectedTask(task);
3198
+ setView("steps");
3199
+ setSel(0);
3200
+ };
3201
+ const executePlan = async (planFile) => {
3202
+ if (!planFile.plan) return;
3203
+ setExecuting(true);
3204
+ setMessage(null);
3205
+ try {
3206
+ const executor = new PlanExecutor();
3207
+ await executor.execute(planFile.plan, { dryRun: true });
3208
+ setMessage(`Executed plan: ${planFile.plan.name} (dry run)`);
3209
+ } catch (e) {
3210
+ setError(e instanceof Error ? e.message : "Failed to execute plan");
3211
+ }
3212
+ setExecuting(false);
3213
+ };
3214
+ const getItems = () => {
3215
+ if (view === "plans") return planFiles;
3216
+ if (view === "tasks" && selectedPlan?.plan) return selectedPlan.plan.tasks;
3217
+ if (view === "steps" && selectedTask) return selectedTask.steps;
3218
+ return [];
3219
+ };
3220
+ const items = getItems();
3221
+ const start = Math.max(0, Math.min(sel - Math.floor(maxVisible / 2), items.length - maxVisible));
3222
+ const visible = items.slice(start, start + maxVisible);
3223
+ useInput16((input, key) => {
3224
+ if (loading || executing) return;
3225
+ if (key.upArrow) setSel((i) => Math.max(0, i - 1));
3226
+ else if (key.downArrow) setSel((i) => Math.min(items.length - 1, i + 1));
3227
+ else if (input === "r") loadPlans();
3228
+ else if (key.escape || input === "b") {
3229
+ if (view === "steps") {
3230
+ setView("tasks");
3231
+ setSelectedTask(null);
3232
+ setSel(0);
3233
+ } else if (view === "tasks") {
3234
+ setView("plans");
3235
+ setSelectedPlan(null);
3236
+ setSel(0);
3237
+ }
3238
+ } else if (key.return) {
3239
+ if (view === "plans" && planFiles[sel]) {
3240
+ selectPlan(planFiles[sel]);
3241
+ } else if (view === "tasks" && selectedPlan?.plan?.tasks[sel]) {
3242
+ selectTask(selectedPlan.plan.tasks[sel]);
3243
+ }
3244
+ } else if (input === "x" && view === "plans" && planFiles[sel]?.plan) {
3245
+ executePlan(planFiles[sel]);
3246
+ }
3247
+ });
3248
+ const renderPlanItem = (planFile, idx) => {
3249
+ const isSel = idx === sel;
3250
+ const statusIcon = planFile.valid ? symbols.success : symbols.error;
3251
+ const statusColor = planFile.valid ? "green" : "red";
3252
+ return /* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", children: [
3253
+ /* @__PURE__ */ jsxs18(Text18, { inverse: isSel, children: [
3254
+ isSel ? symbols.pointer : " ",
3255
+ " ",
3256
+ /* @__PURE__ */ jsx18(Text18, { color: statusColor, children: statusIcon }),
3257
+ " ",
3258
+ planFile.name
3259
+ ] }),
3260
+ isSel && planFile.plan && /* @__PURE__ */ jsxs18(Fragment3, { children: [
3261
+ /* @__PURE__ */ jsxs18(Text18, { dimColor: true, children: [
3262
+ " ",
3263
+ planFile.plan.goal
3264
+ ] }),
3265
+ /* @__PURE__ */ jsxs18(Text18, { dimColor: true, children: [
3266
+ " ",
3267
+ planFile.plan.tasks.length,
3268
+ " task(s) | ",
3269
+ planFile.plan.techStack?.join(", ") || "No stack"
3270
+ ] })
3271
+ ] }),
3272
+ isSel && planFile.error && /* @__PURE__ */ jsxs18(Text18, { color: "red", children: [
3273
+ " ",
3274
+ planFile.error
3275
+ ] })
3276
+ ] }, planFile.path);
3277
+ };
3278
+ const renderTaskItem = (task, idx) => {
3279
+ const isSel = idx === sel;
3280
+ return /* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", children: [
3281
+ /* @__PURE__ */ jsxs18(Text18, { inverse: isSel, children: [
3282
+ isSel ? symbols.pointer : " ",
3283
+ " [",
3284
+ task.id,
3285
+ "] ",
3286
+ task.name
3287
+ ] }),
3288
+ isSel && /* @__PURE__ */ jsxs18(Fragment3, { children: [
3289
+ /* @__PURE__ */ jsxs18(Text18, { dimColor: true, children: [
3290
+ " ",
3291
+ task.steps.length,
3292
+ " step(s)"
3293
+ ] }),
3294
+ task.files?.create && /* @__PURE__ */ jsxs18(Text18, { dimColor: true, children: [
3295
+ " Create: ",
3296
+ task.files.create.join(", ")
3297
+ ] }),
3298
+ task.files?.modify && /* @__PURE__ */ jsxs18(Text18, { dimColor: true, children: [
3299
+ " Modify: ",
3300
+ task.files.modify.join(", ")
3301
+ ] }),
3302
+ task.files?.test && /* @__PURE__ */ jsxs18(Text18, { dimColor: true, children: [
3303
+ " Test: ",
3304
+ task.files.test.join(", ")
3305
+ ] })
3306
+ ] })
3307
+ ] }, task.id);
3308
+ };
3309
+ const renderStepItem = (step, idx) => {
3310
+ const isSel = idx === sel;
3311
+ const typeColors = {
3312
+ test: "yellow",
3313
+ verify: "cyan",
3314
+ implement: "green",
3315
+ commit: "magenta"
3316
+ };
3317
+ return /* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", children: [
3318
+ /* @__PURE__ */ jsxs18(Text18, { inverse: isSel, children: [
3319
+ isSel ? symbols.pointer : " ",
3320
+ " ",
3321
+ /* @__PURE__ */ jsxs18(Text18, { color: typeColors[step.type] || "white", children: [
3322
+ "[",
3323
+ step.type,
3324
+ "]"
3325
+ ] }),
3326
+ " Step ",
3327
+ step.number
3328
+ ] }),
3329
+ isSel && /* @__PURE__ */ jsxs18(Text18, { dimColor: true, children: [
3330
+ " ",
3331
+ step.description
3332
+ ] })
3333
+ ] }, step.number);
3334
+ };
3335
+ const getTitle = () => {
3336
+ if (view === "plans") return "PLANS";
3337
+ if (view === "tasks") return `TASKS: ${selectedPlan?.plan?.name || ""}`;
3338
+ if (view === "steps") return `STEPS: Task ${selectedTask?.id}`;
3339
+ return "PLANS";
3340
+ };
3341
+ return /* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", children: [
3342
+ /* @__PURE__ */ jsx18(Text18, { bold: true, color: colors.primary, children: getTitle() }),
3343
+ /* @__PURE__ */ jsxs18(Text18, { dimColor: true, children: [
3344
+ view === "plans" && `${planFiles.length} plan(s) found`,
3345
+ view === "tasks" && selectedPlan?.plan && `${selectedPlan.plan.tasks.length} task(s)`,
3346
+ view === "steps" && selectedTask && `${selectedTask.steps.length} step(s)`
3347
+ ] }),
3348
+ loading && /* @__PURE__ */ jsx18(Text18, { color: "yellow", children: "Loading plans..." }),
3349
+ executing && /* @__PURE__ */ jsx18(Text18, { color: "yellow", children: "Executing plan..." }),
3350
+ error && /* @__PURE__ */ jsxs18(Text18, { color: "red", children: [
3351
+ symbols.error,
3352
+ " ",
3353
+ error
3354
+ ] }),
3355
+ message && /* @__PURE__ */ jsxs18(Text18, { color: "green", children: [
3356
+ symbols.success,
3357
+ " ",
3358
+ message
3359
+ ] }),
3360
+ !loading && !executing && items.length === 0 && /* @__PURE__ */ jsxs18(Box18, { marginTop: 1, flexDirection: "column", children: [
3361
+ /* @__PURE__ */ jsxs18(Text18, { dimColor: true, children: [
3362
+ "No ",
3363
+ view,
3364
+ " found."
3365
+ ] }),
3366
+ view === "plans" && /* @__PURE__ */ jsx18(Text18, { dimColor: true, children: "Create a plan file: *.plan.md or *-plan.md" })
3367
+ ] }),
3368
+ !loading && !executing && items.length > 0 && /* @__PURE__ */ jsxs18(Box18, { marginTop: 1, flexDirection: "column", children: [
3369
+ start > 0 && /* @__PURE__ */ jsxs18(Text18, { dimColor: true, children: [
3370
+ " \u2191 ",
3371
+ start,
3372
+ " more"
3373
+ ] }),
3374
+ view === "plans" && visible.map((pf, i) => renderPlanItem(pf, start + i)),
3375
+ view === "tasks" && visible.map((t, i) => renderTaskItem(t, start + i)),
3376
+ view === "steps" && visible.map((s, i) => renderStepItem(s, start + i)),
3377
+ start + maxVisible < items.length && /* @__PURE__ */ jsxs18(Text18, { dimColor: true, children: [
3378
+ " \u2193 ",
3379
+ items.length - start - maxVisible,
3380
+ " more"
3381
+ ] })
3382
+ ] }),
3383
+ /* @__PURE__ */ jsxs18(Box18, { marginTop: 1, children: [
3384
+ view === "plans" && /* @__PURE__ */ jsx18(Text18, { dimColor: true, children: "Enter=view tasks x=execute (dry-run) r=refresh q=quit" }),
3385
+ view === "tasks" && /* @__PURE__ */ jsx18(Text18, { dimColor: true, children: "Enter=view steps b/Esc=back q=quit" }),
3386
+ view === "steps" && /* @__PURE__ */ jsx18(Text18, { dimColor: true, children: "b/Esc=back q=quit" })
3387
+ ] })
3388
+ ] });
3389
+ }
3390
+
3391
+ // src/App.tsx
3392
+ import { jsx as jsx19, jsxs as jsxs19 } from "react/jsx-runtime";
2405
3393
  function App() {
2406
- const [screen, setScreen] = useState17("home");
3394
+ const [screen, setScreen] = useState21("home");
2407
3395
  const { exit } = useApp();
2408
3396
  const { stdout } = useStdout();
2409
3397
  const cols = stdout?.columns || 80;
@@ -2422,9 +3410,13 @@ function App() {
2422
3410
  e: "memory",
2423
3411
  i: "installed",
2424
3412
  s: "sync",
3413
+ a: "team",
3414
+ p: "plugins",
3415
+ o: "methodology",
3416
+ n: "plan",
2425
3417
  ",": "settings"
2426
3418
  };
2427
- useInput13((input, key) => {
3419
+ useInput17((input, key) => {
2428
3420
  if (input === "q") {
2429
3421
  exit();
2430
3422
  return;
@@ -2441,63 +3433,71 @@ function App() {
2441
3433
  const renderScreen = () => {
2442
3434
  switch (screen) {
2443
3435
  case "home":
2444
- return /* @__PURE__ */ jsx15(Home, { onNavigate: setScreen, cols, rows });
3436
+ return /* @__PURE__ */ jsx19(Home, { onNavigate: setScreen, cols, rows });
2445
3437
  case "browse":
2446
- return /* @__PURE__ */ jsx15(Browse, { cols, rows });
3438
+ return /* @__PURE__ */ jsx19(Browse, { cols, rows });
2447
3439
  case "installed":
2448
- return /* @__PURE__ */ jsx15(Installed, { cols, rows });
3440
+ return /* @__PURE__ */ jsx19(Installed, { cols, rows });
2449
3441
  case "sync":
2450
- return /* @__PURE__ */ jsx15(Sync, { cols, rows });
3442
+ return /* @__PURE__ */ jsx19(Sync, { cols, rows });
2451
3443
  case "settings":
2452
- return /* @__PURE__ */ jsx15(Settings, { cols, rows });
3444
+ return /* @__PURE__ */ jsx19(Settings, { cols, rows });
2453
3445
  case "recommend":
2454
- return /* @__PURE__ */ jsx15(Recommend, { cols, rows });
3446
+ return /* @__PURE__ */ jsx19(Recommend, { cols, rows });
2455
3447
  case "translate":
2456
- return /* @__PURE__ */ jsx15(Translate, { cols, rows });
3448
+ return /* @__PURE__ */ jsx19(Translate, { cols, rows });
2457
3449
  case "context":
2458
- return /* @__PURE__ */ jsx15(Context, { cols, rows });
3450
+ return /* @__PURE__ */ jsx19(Context, { cols, rows });
2459
3451
  case "workflow":
2460
- return /* @__PURE__ */ jsx15(Workflow, { cols, rows });
3452
+ return /* @__PURE__ */ jsx19(Workflow, { cols, rows });
2461
3453
  case "execute":
2462
- return /* @__PURE__ */ jsx15(Execute, { cols, rows });
3454
+ return /* @__PURE__ */ jsx19(Execute, { cols, rows });
2463
3455
  case "history":
2464
- return /* @__PURE__ */ jsx15(History, { cols, rows });
3456
+ return /* @__PURE__ */ jsx19(History, { cols, rows });
2465
3457
  case "marketplace":
2466
- return /* @__PURE__ */ jsx15(Marketplace, { cols, rows });
3458
+ return /* @__PURE__ */ jsx19(Marketplace, { cols, rows });
2467
3459
  case "memory":
2468
- return /* @__PURE__ */ jsx15(Memory, { cols, rows });
3460
+ return /* @__PURE__ */ jsx19(Memory, { cols, rows });
3461
+ case "team":
3462
+ return /* @__PURE__ */ jsx19(Team, { cols, rows });
3463
+ case "plugins":
3464
+ return /* @__PURE__ */ jsx19(Plugins, { cols, rows });
3465
+ case "methodology":
3466
+ return /* @__PURE__ */ jsx19(Methodology, { cols, rows });
3467
+ case "plan":
3468
+ return /* @__PURE__ */ jsx19(Plan, { cols, rows });
2469
3469
  }
2470
3470
  };
2471
3471
  const contentHeight = rows - 2;
2472
- return /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", height: rows, children: [
2473
- /* @__PURE__ */ jsxs15(Box15, { flexDirection: "row", height: contentHeight, children: [
2474
- showSidebar && /* @__PURE__ */ jsx15(Sidebar, { screen, onNavigate: setScreen }),
2475
- /* @__PURE__ */ jsx15(Box15, { flexDirection: "column", flexGrow: 1, marginLeft: 1, children: renderScreen() })
3472
+ return /* @__PURE__ */ jsxs19(Box19, { flexDirection: "column", height: rows, children: [
3473
+ /* @__PURE__ */ jsxs19(Box19, { flexDirection: "row", height: contentHeight, children: [
3474
+ showSidebar && /* @__PURE__ */ jsx19(Sidebar, { screen, onNavigate: setScreen }),
3475
+ /* @__PURE__ */ jsx19(Box19, { flexDirection: "column", flexGrow: 1, marginLeft: 1, children: renderScreen() })
2476
3476
  ] }),
2477
- /* @__PURE__ */ jsx15(Box15, { children: /* @__PURE__ */ jsx15(Text15, { dimColor: true, children: "h Home m Market b Browse i Inst w Wflow x Exec y Hist r Rec t Trans c Ctx e Mem s Sync , Cfg q Quit" }) })
3477
+ /* @__PURE__ */ jsx19(Box19, { children: /* @__PURE__ */ jsx19(Text19, { dimColor: true, children: "h Home m Market b Browse w Wflow x Exec a Team p Plug o Meth n Plan r Rec t Trans c Ctx e Mem i Inst s Sync q Quit" }) })
2478
3478
  ] });
2479
3479
  }
2480
3480
 
2481
3481
  // src/components/Header.tsx
2482
- import { Box as Box16, Text as Text16 } from "ink";
2483
- import { jsx as jsx16, jsxs as jsxs16 } from "react/jsx-runtime";
3482
+ import { Box as Box20, Text as Text20 } from "ink";
3483
+ import { jsx as jsx20, jsxs as jsxs20 } from "react/jsx-runtime";
2484
3484
  function Header({ title, subtitle, count }) {
2485
- return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", marginBottom: 1, children: [
2486
- /* @__PURE__ */ jsxs16(Box16, { justifyContent: "space-between", children: [
2487
- /* @__PURE__ */ jsx16(Text16, { color: colors.primary, bold: true, children: title.toUpperCase() }),
2488
- count !== void 0 && /* @__PURE__ */ jsxs16(Text16, { color: colors.secondaryDim, children: [
3485
+ return /* @__PURE__ */ jsxs20(Box20, { flexDirection: "column", marginBottom: 1, children: [
3486
+ /* @__PURE__ */ jsxs20(Box20, { justifyContent: "space-between", children: [
3487
+ /* @__PURE__ */ jsx20(Text20, { color: colors.primary, bold: true, children: title.toUpperCase() }),
3488
+ count !== void 0 && /* @__PURE__ */ jsxs20(Text20, { color: colors.secondaryDim, children: [
2489
3489
  symbols.star,
2490
3490
  " ",
2491
3491
  count
2492
3492
  ] })
2493
3493
  ] }),
2494
- subtitle && /* @__PURE__ */ jsx16(Text16, { color: colors.secondaryDim, dimColor: true, children: subtitle })
3494
+ subtitle && /* @__PURE__ */ jsx20(Text20, { color: colors.secondaryDim, dimColor: true, children: subtitle })
2495
3495
  ] });
2496
3496
  }
2497
3497
 
2498
3498
  // src/components/SkillList.tsx
2499
- import { Box as Box17, Text as Text17 } from "ink";
2500
- import { jsx as jsx17, jsxs as jsxs17 } from "react/jsx-runtime";
3499
+ import { Box as Box21, Text as Text21 } from "ink";
3500
+ import { jsx as jsx21, jsxs as jsxs21 } from "react/jsx-runtime";
2501
3501
  function formatInstalls(count) {
2502
3502
  if (count >= 1e3) {
2503
3503
  return `${(count / 1e3).toFixed(1)}K`;
@@ -2513,13 +3513,13 @@ function SkillList({
2513
3513
  maxVisible = 10
2514
3514
  }) {
2515
3515
  if (skills.length === 0) {
2516
- return /* @__PURE__ */ jsx17(Box17, { children: /* @__PURE__ */ jsx17(Text17, { color: colors.secondaryDim, dimColor: true, children: "No skills found" }) });
3516
+ return /* @__PURE__ */ jsx21(Box21, { children: /* @__PURE__ */ jsx21(Text21, { color: colors.secondaryDim, dimColor: true, children: "No skills found" }) });
2517
3517
  }
2518
3518
  const startIndex = Math.max(0, selectedIndex - Math.floor(maxVisible / 2));
2519
3519
  const visibleSkills = skills.slice(startIndex, startIndex + maxVisible);
2520
3520
  const actualStartIndex = startIndex;
2521
- return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", children: [
2522
- showRank && /* @__PURE__ */ jsx17(Box17, { marginBottom: 1, children: /* @__PURE__ */ jsxs17(Text17, { color: colors.secondaryDim, children: [
3521
+ return /* @__PURE__ */ jsxs21(Box21, { flexDirection: "column", children: [
3522
+ showRank && /* @__PURE__ */ jsx21(Box21, { marginBottom: 1, children: /* @__PURE__ */ jsxs21(Text21, { color: colors.secondaryDim, children: [
2523
3523
  " # SKILL",
2524
3524
  showSource && " SOURCE",
2525
3525
  showInstalls && " INSTALLS"
@@ -2529,9 +3529,9 @@ function SkillList({
2529
3529
  const isSelected = realIndex === selectedIndex;
2530
3530
  const skillName = skill.name.padEnd(28).slice(0, 28);
2531
3531
  const sourceName = skill.source ? skill.source.slice(0, 25) : "";
2532
- return /* @__PURE__ */ jsxs17(Box17, { children: [
2533
- /* @__PURE__ */ jsxs17(
2534
- Text17,
3532
+ return /* @__PURE__ */ jsxs21(Box21, { children: [
3533
+ /* @__PURE__ */ jsxs21(
3534
+ Text21,
2535
3535
  {
2536
3536
  color: isSelected ? colors.primary : colors.secondary,
2537
3537
  bold: isSelected,
@@ -2544,14 +3544,14 @@ function SkillList({
2544
3544
  ]
2545
3545
  }
2546
3546
  ),
2547
- showSource && /* @__PURE__ */ jsxs17(Text17, { color: colors.secondaryDim, dimColor: !isSelected, children: [
3547
+ showSource && /* @__PURE__ */ jsxs21(Text21, { color: colors.secondaryDim, dimColor: !isSelected, children: [
2548
3548
  " ",
2549
3549
  sourceName
2550
3550
  ] }),
2551
- showInstalls && skill.installs !== void 0 && /* @__PURE__ */ jsx17(Text17, { color: colors.secondaryDim, children: formatInstalls(skill.installs).padStart(8) })
3551
+ showInstalls && skill.installs !== void 0 && /* @__PURE__ */ jsx21(Text21, { color: colors.secondaryDim, children: formatInstalls(skill.installs).padStart(8) })
2552
3552
  ] }, `${skill.source}-${skill.name}`);
2553
3553
  }),
2554
- skills.length > maxVisible && /* @__PURE__ */ jsx17(Box17, { marginTop: 1, children: /* @__PURE__ */ jsxs17(Text17, { color: colors.secondaryDim, dimColor: true, children: [
3554
+ skills.length > maxVisible && /* @__PURE__ */ jsx21(Box21, { marginTop: 1, children: /* @__PURE__ */ jsxs21(Text21, { color: colors.secondaryDim, dimColor: true, children: [
2555
3555
  "Showing ",
2556
3556
  startIndex + 1,
2557
3557
  "-",
@@ -2563,11 +3563,11 @@ function SkillList({
2563
3563
  }
2564
3564
 
2565
3565
  // src/components/StatusBar.tsx
2566
- import { Box as Box18, Text as Text18 } from "ink";
2567
- import { jsx as jsx18, jsxs as jsxs18 } from "react/jsx-runtime";
3566
+ import { Box as Box22, Text as Text22 } from "ink";
3567
+ import { jsx as jsx22, jsxs as jsxs22 } from "react/jsx-runtime";
2568
3568
  function StatusBar({ shortcuts, message }) {
2569
- return /* @__PURE__ */ jsxs18(
2570
- Box18,
3569
+ return /* @__PURE__ */ jsxs22(
3570
+ Box22,
2571
3571
  {
2572
3572
  borderStyle: "single",
2573
3573
  borderColor: colors.borderDim,
@@ -2578,11 +3578,11 @@ function StatusBar({ shortcuts, message }) {
2578
3578
  paddingX: 1,
2579
3579
  justifyContent: "space-between",
2580
3580
  children: [
2581
- /* @__PURE__ */ jsx18(Box18, { gap: 2, children: shortcuts.map((shortcut, idx) => /* @__PURE__ */ jsxs18(Box18, { gap: 1, children: [
2582
- /* @__PURE__ */ jsx18(Text18, { color: colors.primary, bold: true, children: shortcut.key }),
2583
- /* @__PURE__ */ jsx18(Text18, { color: colors.secondaryDim, children: shortcut.label })
3581
+ /* @__PURE__ */ jsx22(Box22, { gap: 2, children: shortcuts.map((shortcut, idx) => /* @__PURE__ */ jsxs22(Box22, { gap: 1, children: [
3582
+ /* @__PURE__ */ jsx22(Text22, { color: colors.primary, bold: true, children: shortcut.key }),
3583
+ /* @__PURE__ */ jsx22(Text22, { color: colors.secondaryDim, children: shortcut.label })
2584
3584
  ] }, idx)) }),
2585
- message && /* @__PURE__ */ jsxs18(Text18, { color: colors.success, children: [
3585
+ message && /* @__PURE__ */ jsxs22(Text22, { color: colors.success, children: [
2586
3586
  symbols.check,
2587
3587
  " ",
2588
3588
  message
@@ -2593,44 +3593,44 @@ function StatusBar({ shortcuts, message }) {
2593
3593
  }
2594
3594
 
2595
3595
  // src/components/SearchInput.tsx
2596
- import { Box as Box19, Text as Text19 } from "ink";
2597
- import TextInput from "ink-text-input";
2598
- import { jsx as jsx19, jsxs as jsxs19 } from "react/jsx-runtime";
3596
+ import { Box as Box23, Text as Text23 } from "ink";
3597
+ import TextInput2 from "ink-text-input";
3598
+ import { jsx as jsx23, jsxs as jsxs23 } from "react/jsx-runtime";
2599
3599
  function SearchInput({
2600
3600
  value,
2601
3601
  onChange,
2602
3602
  placeholder = "Search skills...",
2603
3603
  isFocused = false
2604
3604
  }) {
2605
- return /* @__PURE__ */ jsxs19(
2606
- Box19,
3605
+ return /* @__PURE__ */ jsxs23(
3606
+ Box23,
2607
3607
  {
2608
3608
  borderStyle: "single",
2609
3609
  borderColor: isFocused ? colors.primary : colors.borderDim,
2610
3610
  paddingX: 1,
2611
3611
  children: [
2612
- /* @__PURE__ */ jsx19(Text19, { color: colors.secondaryDim, children: "/ " }),
2613
- isFocused ? /* @__PURE__ */ jsx19(
2614
- TextInput,
3612
+ /* @__PURE__ */ jsx23(Text23, { color: colors.secondaryDim, children: "/ " }),
3613
+ isFocused ? /* @__PURE__ */ jsx23(
3614
+ TextInput2,
2615
3615
  {
2616
3616
  value,
2617
3617
  onChange,
2618
3618
  placeholder
2619
3619
  }
2620
- ) : /* @__PURE__ */ jsx19(Text19, { color: value ? colors.secondary : colors.secondaryDim, children: value || placeholder }),
2621
- /* @__PURE__ */ jsx19(Box19, { flexGrow: 1 }),
2622
- /* @__PURE__ */ jsx19(Text19, { color: colors.secondaryDim, children: "/" })
3620
+ ) : /* @__PURE__ */ jsx23(Text23, { color: value ? colors.secondary : colors.secondaryDim, children: value || placeholder }),
3621
+ /* @__PURE__ */ jsx23(Box23, { flexGrow: 1 }),
3622
+ /* @__PURE__ */ jsx23(Text23, { color: colors.secondaryDim, children: "/" })
2623
3623
  ]
2624
3624
  }
2625
3625
  );
2626
3626
  }
2627
3627
 
2628
3628
  // src/hooks/useKeyboard.ts
2629
- import { useState as useState18, useCallback as useCallback3, useEffect as useEffect13 } from "react";
2630
- import { useInput as useInput14, useApp as useApp2 } from "ink";
3629
+ import { useState as useState22, useCallback as useCallback3, useEffect as useEffect18 } from "react";
3630
+ import { useInput as useInput18, useApp as useApp2 } from "ink";
2631
3631
  function useKeyboard(options = {}) {
2632
3632
  const { exit } = useApp2();
2633
- useInput14((input, key) => {
3633
+ useInput18((input, key) => {
2634
3634
  if (options.disabled) return;
2635
3635
  if (input === "q" || key.ctrl && input === "c") {
2636
3636
  exit();
@@ -2674,8 +3674,8 @@ function useKeyboard(options = {}) {
2674
3674
  });
2675
3675
  }
2676
3676
  function useListNavigation(listLength, initialIndex = 0) {
2677
- const [selectedIndex, setSelectedIndex] = useState18(initialIndex);
2678
- useEffect13(() => {
3677
+ const [selectedIndex, setSelectedIndex] = useState22(initialIndex);
3678
+ useEffect18(() => {
2679
3679
  if (selectedIndex >= listLength && listLength > 0) {
2680
3680
  setSelectedIndex(listLength - 1);
2681
3681
  }
@@ -2693,7 +3693,7 @@ function useListNavigation(listLength, initialIndex = 0) {
2693
3693
  }
2694
3694
 
2695
3695
  // src/hooks/useMemory.ts
2696
- import { useState as useState19, useEffect as useEffect14, useCallback as useCallback4 } from "react";
3696
+ import { useState as useState23, useEffect as useEffect19, useCallback as useCallback4 } from "react";
2697
3697
  import {
2698
3698
  LearningStore as LearningStore2,
2699
3699
  ObservationStore as ObservationStore2,
@@ -2701,12 +3701,12 @@ import {
2701
3701
  createMemoryInjector as createMemoryInjector2
2702
3702
  } from "@skillkit/core";
2703
3703
  function useMemory() {
2704
- const [learnings, setLearnings] = useState19([]);
2705
- const [observations, setObservations] = useState19([]);
2706
- const [status, setStatus] = useState19(null);
2707
- const [loading, setLoading] = useState19(true);
2708
- const [error, setError] = useState19(null);
2709
- const [isGlobal, setIsGlobal] = useState19(false);
3704
+ const [learnings, setLearnings] = useState23([]);
3705
+ const [observations, setObservations] = useState23([]);
3706
+ const [status, setStatus] = useState23(null);
3707
+ const [loading, setLoading] = useState23(true);
3708
+ const [error, setError] = useState23(null);
3709
+ const [isGlobal, setIsGlobal] = useState23(false);
2710
3710
  const projectPath = process.cwd();
2711
3711
  const refresh = useCallback4(() => {
2712
3712
  setLoading(true);
@@ -2785,7 +3785,7 @@ function useMemory() {
2785
3785
  },
2786
3786
  [projectPath, refresh]
2787
3787
  );
2788
- useEffect14(() => {
3788
+ useEffect19(() => {
2789
3789
  refresh();
2790
3790
  }, [refresh]);
2791
3791
  return {
@@ -2804,10 +3804,10 @@ function useMemory() {
2804
3804
  }
2805
3805
 
2806
3806
  // src/index.tsx
2807
- import { jsx as jsx20 } from "react/jsx-runtime";
3807
+ import { jsx as jsx24 } from "react/jsx-runtime";
2808
3808
  function startTUI() {
2809
3809
  process.stdout.write("\x1B[2J\x1B[0f");
2810
- const { waitUntilExit, clear } = render(/* @__PURE__ */ jsx20(App, {}), {
3810
+ const { waitUntilExit, clear } = render(/* @__PURE__ */ jsx24(App, {}), {
2811
3811
  exitOnCtrlC: true
2812
3812
  });
2813
3813
  return waitUntilExit().then(() => {
@@ -2825,6 +3825,9 @@ export {
2825
3825
  Installed,
2826
3826
  Marketplace,
2827
3827
  Memory,
3828
+ Methodology,
3829
+ Plan,
3830
+ Plugins,
2828
3831
  Recommend,
2829
3832
  SearchInput,
2830
3833
  Settings,
@@ -2832,6 +3835,7 @@ export {
2832
3835
  SkillList,
2833
3836
  StatusBar,
2834
3837
  Sync,
3838
+ Team,
2835
3839
  Translate,
2836
3840
  Workflow,
2837
3841
  colors,