@skillkit/tui 1.4.0 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/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 useState19 } from "react";
6
+ import { Box as Box17, Text as Text17, useInput as useInput15, useApp, useStdout } from "ink";
7
7
 
8
8
  // src/components/Sidebar.tsx
9
9
  import { Box, Text } from "ink";
@@ -55,6 +55,9 @@ 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" },
58
61
  // Tools
59
62
  { id: "recommend", label: "Recommend", key: "r" },
60
63
  { id: "translate", label: "Translate", key: "t" },
@@ -78,12 +81,17 @@ function Sidebar({ screen }) {
78
81
  item.label
79
82
  ] }, item.id)),
80
83
  /* @__PURE__ */ jsx(Text, { children: " " }),
81
- NAV.slice(6, 10).map((item) => /* @__PURE__ */ jsxs(Text, { inverse: screen === item.id, children: [
84
+ NAV.slice(6, 8).map((item) => /* @__PURE__ */ jsxs(Text, { inverse: screen === item.id, children: [
82
85
  screen === item.id ? symbols.bullet : " ",
83
86
  item.label
84
87
  ] }, item.id)),
85
88
  /* @__PURE__ */ jsx(Text, { children: " " }),
86
- NAV.slice(10).map((item) => /* @__PURE__ */ jsxs(Text, { inverse: screen === item.id, children: [
89
+ NAV.slice(8, 12).map((item) => /* @__PURE__ */ jsxs(Text, { inverse: screen === item.id, children: [
90
+ screen === item.id ? symbols.bullet : " ",
91
+ item.label
92
+ ] }, item.id)),
93
+ /* @__PURE__ */ jsx(Text, { children: " " }),
94
+ NAV.slice(12).map((item) => /* @__PURE__ */ jsxs(Text, { inverse: screen === item.id, children: [
87
95
  screen === item.id ? symbols.bullet : " ",
88
96
  item.label
89
97
  ] }, item.id)),
@@ -174,14 +182,16 @@ function Home({ cols = 80, rows = 24 }) {
174
182
 
175
183
  // src/screens/Browse.tsx
176
184
  import { useState as useState3 } from "react";
177
- import { existsSync, mkdirSync, cpSync, rmSync } from "fs";
178
- import { join as join2 } from "path";
185
+ import { existsSync as existsSync2, mkdirSync, cpSync, rmSync } from "fs";
186
+ import { join as join3 } from "path";
179
187
  import { Box as Box3, Text as Text3, useInput } from "ink";
180
188
 
181
189
  // src/hooks/useMarketplace.ts
182
190
  import { useState as useState2, useCallback, useEffect as useEffect2 } from "react";
183
- import { detectProvider } from "@skillkit/core";
184
- var POPULAR_REPOS = [
191
+ import { detectProvider, loadConfig, extractFrontmatter } from "@skillkit/core";
192
+ import { readFileSync as readFileSync2, existsSync } from "fs";
193
+ import { join as join2 } from "path";
194
+ var DEFAULT_REPOS = [
185
195
  { source: "anthropics/skills", name: "Anthropic Official" },
186
196
  { source: "vercel-labs/agent-skills", name: "Vercel Labs" },
187
197
  { source: "expo/skills", name: "Expo / React Native" },
@@ -213,6 +223,41 @@ var POPULAR_REPOS = [
213
223
  { source: "openrouterteam/agent-skills", name: "OpenRouter SDK" },
214
224
  { source: "intellectronica/agent-skills", name: "Context7" }
215
225
  ];
226
+ function getMarketplaceRepos() {
227
+ try {
228
+ const config = loadConfig();
229
+ if (config.marketplaceSources?.length) {
230
+ const configRepos = config.marketplaceSources.map((source) => ({
231
+ source,
232
+ name: source.split("/").pop() || source
233
+ }));
234
+ const existingSources = new Set(configRepos.map((r) => r.source));
235
+ for (const repo of DEFAULT_REPOS) {
236
+ if (!existingSources.has(repo.source)) {
237
+ configRepos.push(repo);
238
+ }
239
+ }
240
+ return configRepos;
241
+ }
242
+ } catch {
243
+ }
244
+ return DEFAULT_REPOS;
245
+ }
246
+ function readSkillDescription(skillPath) {
247
+ const skillMdPath = join2(skillPath, "SKILL.md");
248
+ if (!existsSync(skillMdPath)) {
249
+ return void 0;
250
+ }
251
+ try {
252
+ const content = readFileSync2(skillMdPath, "utf-8");
253
+ const frontmatter = extractFrontmatter(content);
254
+ if (frontmatter && typeof frontmatter.description === "string") {
255
+ return frontmatter.description;
256
+ }
257
+ } catch {
258
+ }
259
+ return void 0;
260
+ }
216
261
  function useMarketplace() {
217
262
  const [allSkills, setAllSkills] = useState2([]);
218
263
  const [filteredSkills, setFilteredSkills] = useState2([]);
@@ -220,6 +265,8 @@ function useMarketplace() {
220
265
  const [error, setError] = useState2(null);
221
266
  const [currentRepo, setCurrentRepo] = useState2(null);
222
267
  const [fetchedRepos, setFetchedRepos] = useState2(/* @__PURE__ */ new Set());
268
+ const [failedRepos, setFailedRepos] = useState2([]);
269
+ const [repos] = useState2(() => getMarketplaceRepos());
223
270
  const fetchRepo = useCallback(async (source) => {
224
271
  if (fetchedRepos.has(source)) return;
225
272
  setLoading(true);
@@ -234,12 +281,13 @@ function useMarketplace() {
234
281
  if (!result.success || !result.discoveredSkills) {
235
282
  throw new Error(result.error || "Failed to fetch skills");
236
283
  }
237
- const repoName = POPULAR_REPOS.find((r) => r.source === source)?.name || source;
284
+ const repoName = repos.find((r) => r.source === source)?.name || source;
238
285
  const newSkills = result.discoveredSkills.map((skill) => ({
239
286
  name: skill.name,
240
287
  source,
241
288
  repoName,
242
- description: void 0
289
+ // Try to read description from skill frontmatter
290
+ description: readSkillDescription(skill.path)
243
291
  }));
244
292
  setAllSkills((prev) => {
245
293
  const updated = [...prev, ...newSkills];
@@ -251,27 +299,37 @@ function useMarketplace() {
251
299
  rmSync3(result.tempRoot, { recursive: true, force: true });
252
300
  }
253
301
  } catch (err) {
254
- setError(err instanceof Error ? err.message : "Failed to fetch repository");
302
+ const errorMsg = err instanceof Error ? err.message : "Failed to fetch repository";
303
+ setError(errorMsg);
304
+ setFailedRepos((prev) => prev.includes(source) ? prev : [...prev, source]);
255
305
  } finally {
256
306
  setLoading(false);
257
307
  setCurrentRepo(null);
258
308
  }
259
- }, [fetchedRepos]);
309
+ }, [fetchedRepos, repos]);
260
310
  const fetchAllRepos = useCallback(async () => {
261
311
  setLoading(true);
262
312
  setError(null);
263
- for (const repo of POPULAR_REPOS) {
313
+ const failures = [];
314
+ for (const repo of repos) {
264
315
  if (!fetchedRepos.has(repo.source)) {
265
316
  setCurrentRepo(repo.source);
266
317
  try {
267
318
  await fetchRepo(repo.source);
268
- } catch {
319
+ } catch (err) {
320
+ failures.push(repo.source);
269
321
  }
270
322
  }
271
323
  }
324
+ if (failures.length > 0) {
325
+ setFailedRepos((prev) => {
326
+ const combined = [...prev, ...failures];
327
+ return [...new Set(combined)];
328
+ });
329
+ }
272
330
  setLoading(false);
273
331
  setCurrentRepo(null);
274
- }, [fetchRepo, fetchedRepos]);
332
+ }, [fetchRepo, fetchedRepos, repos]);
275
333
  const search = useCallback((query) => {
276
334
  if (!query.trim()) {
277
335
  setFilteredSkills(allSkills);
@@ -288,6 +346,8 @@ function useMarketplace() {
288
346
  setFetchedRepos(/* @__PURE__ */ new Set());
289
347
  setAllSkills([]);
290
348
  setFilteredSkills([]);
349
+ setFailedRepos([]);
350
+ setError(null);
291
351
  }, []);
292
352
  useEffect2(() => {
293
353
  setFilteredSkills(allSkills);
@@ -302,8 +362,9 @@ function useMarketplace() {
302
362
  loading,
303
363
  error,
304
364
  totalCount: allSkills.length,
305
- repos: POPULAR_REPOS,
365
+ repos,
306
366
  currentRepo,
367
+ failedRepos,
307
368
  refresh,
308
369
  search,
309
370
  fetchRepo,
@@ -317,14 +378,14 @@ import { detectAgent, getAdapter as getAdapter2, getAllAdapters } from "@skillki
317
378
 
318
379
  // src/helpers.ts
319
380
  import {
320
- loadConfig,
381
+ loadConfig as loadConfig2,
321
382
  getSearchDirs as coreGetSearchDirs,
322
383
  getInstallDir as coreGetInstallDir,
323
384
  saveSkillMetadata as coreSaveSkillMetadata
324
385
  } from "@skillkit/core";
325
386
  import { getAdapter } from "@skillkit/agents";
326
387
  function getSearchDirs(agentType) {
327
- const type = agentType || loadConfig().agent;
388
+ const type = agentType || loadConfig2().agent;
328
389
  const adapter = getAdapter(type);
329
390
  const adapterInfo = {
330
391
  type: adapter.type,
@@ -335,7 +396,7 @@ function getSearchDirs(agentType) {
335
396
  return coreGetSearchDirs(adapterInfo);
336
397
  }
337
398
  function getInstallDir(global = false, agentType) {
338
- const type = agentType || loadConfig().agent;
399
+ const type = agentType || loadConfig2().agent;
339
400
  const adapter = getAdapter(type);
340
401
  const adapterInfo = {
341
402
  type: adapter.type,
@@ -400,11 +461,11 @@ function Browse({ rows = 24 }) {
400
461
  const targetAgentType = agentType || await detectAgent();
401
462
  const adapter = getAdapter2(targetAgentType);
402
463
  const installDir = getInstallDir(false, targetAgentType);
403
- if (!existsSync(installDir)) {
464
+ if (!existsSync2(installDir)) {
404
465
  mkdirSync(installDir, { recursive: true });
405
466
  }
406
- const targetPath = join2(installDir, skillName);
407
- if (existsSync(targetPath)) {
467
+ const targetPath = join3(installDir, skillName);
468
+ if (existsSync2(targetPath)) {
408
469
  rmSync(targetPath, { recursive: true, force: true });
409
470
  }
410
471
  cpSync(skill.path, targetPath, { recursive: true, dereference: true });
@@ -710,44 +771,167 @@ function Sync({ rows = 24 }) {
710
771
  }
711
772
 
712
773
  // src/screens/Settings.tsx
713
- import { useState as useState7 } from "react";
774
+ import { useState as useState7, useEffect as useEffect5 } from "react";
714
775
  import { Box as Box6, Text as Text6, useInput as useInput4 } from "ink";
776
+ import TextInput from "ink-text-input";
777
+ import { loadConfig as loadConfig3, saveConfig, AgentType as AgentTypeSchema } from "@skillkit/core";
715
778
  import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
779
+ var ALL_AGENTS = AgentTypeSchema.options;
716
780
  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" }
781
+ { id: "agent", label: "Default Agent", type: "select", options: ["auto-detect", ...ALL_AGENTS] },
782
+ { id: "autoSync", label: "Auto Sync", type: "toggle" },
783
+ { id: "cacheDir", label: "Cache Dir", type: "text" }
720
784
  ];
721
- function Settings({}) {
785
+ function Settings(_props) {
786
+ const [config, setConfig] = useState7(null);
722
787
  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));
788
+ const [editing, setEditing] = useState7(false);
789
+ const [editValue, setEditValue] = useState7("");
790
+ const [saved, setSaved] = useState7(false);
791
+ const [error, setError] = useState7(null);
792
+ useEffect5(() => {
793
+ try {
794
+ const loaded = loadConfig3();
795
+ setConfig(loaded);
796
+ } catch (err) {
797
+ setError(`Failed to load config: ${err}`);
798
+ }
799
+ }, []);
800
+ const getCurrentValue = (setting) => {
801
+ if (!config) return "";
802
+ switch (setting.id) {
803
+ case "agent":
804
+ return config.agent === "universal" ? "auto-detect" : config.agent || "auto-detect";
805
+ case "autoSync":
806
+ return config.autoSync ? "enabled" : "disabled";
807
+ case "cacheDir":
808
+ return config.cacheDir || "~/.skillkit/cache";
809
+ default:
810
+ return "";
811
+ }
812
+ };
813
+ const handleSave = (setting, value) => {
814
+ if (!config) return;
815
+ const newConfig = { ...config };
816
+ switch (setting.id) {
817
+ case "agent":
818
+ if (value === "auto-detect") {
819
+ newConfig.agent = "universal";
820
+ } else {
821
+ newConfig.agent = value;
822
+ }
823
+ break;
824
+ case "autoSync":
825
+ newConfig.autoSync = value === "enabled";
826
+ break;
827
+ case "cacheDir":
828
+ newConfig.cacheDir = value || void 0;
829
+ break;
830
+ }
831
+ try {
832
+ saveConfig(newConfig, false);
833
+ setConfig(newConfig);
834
+ setSaved(true);
835
+ setTimeout(() => setSaved(false), 2e3);
836
+ } catch (err) {
837
+ setError(`Failed to save: ${err}`);
838
+ setTimeout(() => setError(null), 3e3);
839
+ }
840
+ };
841
+ useInput4((input, key) => {
842
+ if (editing) {
843
+ if (key.return) {
844
+ handleSave(SETTINGS[sel], editValue);
845
+ setEditing(false);
846
+ } else if (key.escape) {
847
+ setEditing(false);
848
+ }
849
+ return;
850
+ }
851
+ if (key.upArrow) {
852
+ setSel((i) => Math.max(0, i - 1));
853
+ } else if (key.downArrow) {
854
+ setSel((i) => Math.min(SETTINGS.length - 1, i + 1));
855
+ } else if (key.return || input === " ") {
856
+ const setting = SETTINGS[sel];
857
+ if (setting.type === "toggle") {
858
+ const current = getCurrentValue(setting);
859
+ const newValue = current === "enabled" ? "disabled" : "enabled";
860
+ handleSave(setting, newValue);
861
+ } else if (setting.type === "select" && setting.options) {
862
+ const current = getCurrentValue(setting);
863
+ const idx = setting.options.indexOf(current);
864
+ const nextIdx = (idx + 1) % setting.options.length;
865
+ handleSave(setting, setting.options[nextIdx]);
866
+ } else if (setting.type === "text") {
867
+ setEditValue(getCurrentValue(setting));
868
+ setEditing(true);
869
+ }
870
+ }
726
871
  });
872
+ if (!config) {
873
+ return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
874
+ /* @__PURE__ */ jsx6(Text6, { bold: true, color: colors.primary, children: "SETTINGS" }),
875
+ error ? /* @__PURE__ */ jsxs6(Text6, { color: colors.danger, children: [
876
+ symbols.error,
877
+ " ",
878
+ error
879
+ ] }) : /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: "Loading..." })
880
+ ] });
881
+ }
727
882
  return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
728
883
  /* @__PURE__ */ jsx6(Text6, { bold: true, color: colors.primary, children: "SETTINGS" }),
729
- /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: "Configure SkillKit" }),
884
+ /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: "Configure SkillKit (changes save automatically)" }),
730
885
  /* @__PURE__ */ jsx6(Box6, { marginTop: 1, flexDirection: "column", children: SETTINGS.map((s, i) => {
731
886
  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 })
887
+ const value = getCurrentValue(s);
888
+ const isEditing = editing && isSel;
889
+ return /* @__PURE__ */ jsxs6(Box6, { children: [
890
+ /* @__PURE__ */ jsxs6(Text6, { inverse: isSel && !isEditing, children: [
891
+ isSel ? symbols.pointer : " ",
892
+ s.label.padEnd(16)
893
+ ] }),
894
+ isEditing ? /* @__PURE__ */ jsx6(Box6, { marginLeft: 1, children: /* @__PURE__ */ jsx6(
895
+ TextInput,
896
+ {
897
+ value: editValue,
898
+ onChange: setEditValue,
899
+ onSubmit: () => {
900
+ handleSave(s, editValue);
901
+ setEditing(false);
902
+ }
903
+ }
904
+ ) }) : /* @__PURE__ */ jsxs6(Text6, { color: colors.secondaryDim, children: [
905
+ " ",
906
+ value
907
+ ] }),
908
+ s.type === "toggle" && isSel && !isEditing && /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: " (space to toggle)" }),
909
+ s.type === "select" && isSel && !isEditing && /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: " (enter to cycle)" })
737
910
  ] }, s.id);
738
911
  }) }),
739
- /* @__PURE__ */ jsx6(Box6, { marginTop: 1, children: /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: "Enter=edit q=quit" }) })
912
+ /* @__PURE__ */ jsxs6(Box6, { marginTop: 1, children: [
913
+ saved && /* @__PURE__ */ jsxs6(Text6, { color: colors.success, children: [
914
+ symbols.check,
915
+ " Settings saved"
916
+ ] }),
917
+ error && /* @__PURE__ */ jsxs6(Text6, { color: colors.danger, children: [
918
+ symbols.error,
919
+ " ",
920
+ error
921
+ ] }),
922
+ !saved && !error && /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: editing ? "Enter=save Esc=cancel" : "Enter/Space=edit q=quit" })
923
+ ] })
740
924
  ] });
741
925
  }
742
926
 
743
927
  // src/screens/Recommend.tsx
744
928
  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";
929
+ import { existsSync as existsSync3, mkdirSync as mkdirSync2, cpSync as cpSync2, rmSync as rmSync2 } from "fs";
930
+ import { join as join4 } from "path";
747
931
  import { Box as Box7, Text as Text7, useInput as useInput5 } from "ink";
748
932
 
749
933
  // src/hooks/useRecommend.ts
750
- import { useState as useState8, useCallback as useCallback2, useEffect as useEffect5 } from "react";
934
+ import { useState as useState8, useCallback as useCallback2, useEffect as useEffect6 } from "react";
751
935
  import {
752
936
  RecommendationEngine,
753
937
  ContextManager,
@@ -875,7 +1059,7 @@ function useRecommend(projectPath = process.cwd()) {
875
1059
  const refresh = useCallback2(() => {
876
1060
  loadRecommendations();
877
1061
  }, [loadRecommendations]);
878
- useEffect5(() => {
1062
+ useEffect6(() => {
879
1063
  loadRecommendations();
880
1064
  }, [loadRecommendations]);
881
1065
  return {
@@ -965,11 +1149,11 @@ function Recommend({ rows = 24 }) {
965
1149
  const targetAgentType = agentType || await detectAgent2();
966
1150
  const adapter = getAdapter3(targetAgentType);
967
1151
  const installDir = getInstallDir(false, targetAgentType);
968
- if (!existsSync2(installDir)) {
1152
+ if (!existsSync3(installDir)) {
969
1153
  mkdirSync2(installDir, { recursive: true });
970
1154
  }
971
- const targetPath = join3(installDir, skillName);
972
- if (existsSync2(targetPath)) {
1155
+ const targetPath = join4(installDir, skillName);
1156
+ if (existsSync3(targetPath)) {
973
1157
  rmSync2(targetPath, { recursive: true, force: true });
974
1158
  }
975
1159
  cpSync2(skill.path, targetPath, { recursive: true, dereference: true });
@@ -1172,9 +1356,9 @@ function Recommend({ rows = 24 }) {
1172
1356
  }
1173
1357
 
1174
1358
  // 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";
1359
+ import { useState as useState10, useEffect as useEffect7 } from "react";
1360
+ import { existsSync as existsSync4, readdirSync, readFileSync as readFileSync3, writeFileSync, mkdirSync as mkdirSync3 } from "fs";
1361
+ import { join as join5 } from "path";
1178
1362
  import { Box as Box8, Text as Text8, useInput as useInput6 } from "ink";
1179
1363
  import {
1180
1364
  translateSkill,
@@ -1192,17 +1376,17 @@ function Translate({ rows = 24 }) {
1192
1376
  const [preview, setPreview] = useState10("");
1193
1377
  const [result, setResult] = useState10(null);
1194
1378
  const [loading, setLoading] = useState10(false);
1195
- useEffect6(() => {
1379
+ useEffect7(() => {
1196
1380
  const loadSkills = () => {
1197
1381
  const installDir = getInstallDir(false);
1198
1382
  const foundSkills = [];
1199
- if (existsSync3(installDir)) {
1383
+ if (existsSync4(installDir)) {
1200
1384
  const dirs = readdirSync(installDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
1201
1385
  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");
1386
+ const skillPath = join5(installDir, dir);
1387
+ const skillMdPath = join5(skillPath, "SKILL.md");
1388
+ if (existsSync4(skillMdPath)) {
1389
+ const content = readFileSync3(skillMdPath, "utf-8");
1206
1390
  foundSkills.push({
1207
1391
  name: dir,
1208
1392
  path: skillPath,
@@ -1215,7 +1399,7 @@ function Translate({ rows = 24 }) {
1215
1399
  };
1216
1400
  loadSkills();
1217
1401
  }, []);
1218
- useEffect6(() => {
1402
+ useEffect7(() => {
1219
1403
  const adapters = getAllAdapters4();
1220
1404
  const supportedAgents = getSupportedTranslationAgents();
1221
1405
  const agentList = adapters.filter((a) => supportedAgents.includes(a.type)).map((a) => ({
@@ -1252,12 +1436,12 @@ function Translate({ rows = 24 }) {
1252
1436
  return;
1253
1437
  }
1254
1438
  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)) {
1439
+ const targetDir = adapter?.skillsDir ? join5(process.cwd(), adapter.skillsDir) : join5(process.cwd(), `.${selectedAgent.type}/skills/`);
1440
+ if (!existsSync4(targetDir)) {
1257
1441
  mkdirSync3(targetDir, { recursive: true });
1258
1442
  }
1259
1443
  const filename = translationResult.filename || `${selectedSkill.name}.md`;
1260
- const targetPath = join4(targetDir, filename);
1444
+ const targetPath = join5(targetDir, filename);
1261
1445
  writeFileSync(targetPath, translationResult.content, "utf-8");
1262
1446
  setResult({
1263
1447
  success: true,
@@ -1403,7 +1587,7 @@ function Translate({ rows = 24 }) {
1403
1587
  }
1404
1588
 
1405
1589
  // src/screens/Context.tsx
1406
- import { useState as useState11, useEffect as useEffect7 } from "react";
1590
+ import { useState as useState11, useEffect as useEffect8 } from "react";
1407
1591
  import { Box as Box9, Text as Text9, useInput as useInput7 } from "ink";
1408
1592
  import {
1409
1593
  loadContext,
@@ -1423,7 +1607,7 @@ function Context({ rows = 24 }) {
1423
1607
  const [message, setMessage] = useState11(null);
1424
1608
  const [error, setError] = useState11(null);
1425
1609
  const projectPath = process.cwd();
1426
- useEffect7(() => {
1610
+ useEffect8(() => {
1427
1611
  const load = async () => {
1428
1612
  setLoading(true);
1429
1613
  try {
@@ -1652,7 +1836,7 @@ function Context({ rows = 24 }) {
1652
1836
  }
1653
1837
 
1654
1838
  // src/screens/Workflow.tsx
1655
- import { useState as useState12, useEffect as useEffect8 } from "react";
1839
+ import { useState as useState12, useEffect as useEffect9 } from "react";
1656
1840
  import { Box as Box10, Text as Text10, useInput as useInput8 } from "ink";
1657
1841
  import { listWorkflows } from "@skillkit/core";
1658
1842
  import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
@@ -1665,7 +1849,7 @@ function Workflow({ rows = 24 }) {
1665
1849
  const maxVisible = Math.max(5, rows - 8);
1666
1850
  const start = Math.max(0, Math.min(sel - Math.floor(maxVisible / 2), workflows.length - maxVisible));
1667
1851
  const visible = workflows.slice(start, start + maxVisible);
1668
- useEffect8(() => {
1852
+ useEffect9(() => {
1669
1853
  loadWorkflows();
1670
1854
  }, []);
1671
1855
  const loadWorkflows = () => {
@@ -1745,7 +1929,7 @@ function Workflow({ rows = 24 }) {
1745
1929
  }
1746
1930
 
1747
1931
  // src/screens/Execute.tsx
1748
- import { useState as useState13, useEffect as useEffect9 } from "react";
1932
+ import { useState as useState13, useEffect as useEffect10 } from "react";
1749
1933
  import { Box as Box11, Text as Text11, useInput as useInput9 } from "ink";
1750
1934
  import { createSessionManager } from "@skillkit/core";
1751
1935
  import { jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
@@ -1753,7 +1937,7 @@ function Execute({ rows = 24 }) {
1753
1937
  const [session, setSession] = useState13(null);
1754
1938
  const [loading, setLoading] = useState13(true);
1755
1939
  const maxVisible = Math.max(5, rows - 10);
1756
- useEffect9(() => {
1940
+ useEffect10(() => {
1757
1941
  loadSession();
1758
1942
  const interval = setInterval(loadSession, 1e3);
1759
1943
  return () => clearInterval(interval);
@@ -1858,7 +2042,7 @@ function Execute({ rows = 24 }) {
1858
2042
  }
1859
2043
 
1860
2044
  // src/screens/History.tsx
1861
- import { useState as useState14, useEffect as useEffect10 } from "react";
2045
+ import { useState as useState14, useEffect as useEffect11 } from "react";
1862
2046
  import { Box as Box12, Text as Text12, useInput as useInput10 } from "ink";
1863
2047
  import { createSessionManager as createSessionManager2 } from "@skillkit/core";
1864
2048
  import { jsx as jsx12, jsxs as jsxs12 } from "react/jsx-runtime";
@@ -1870,7 +2054,7 @@ function History({ rows = 24 }) {
1870
2054
  const maxVisible = Math.max(5, rows - 8);
1871
2055
  const start = Math.max(0, Math.min(sel - Math.floor(maxVisible / 2), history.length - maxVisible));
1872
2056
  const visible = history.slice(start, start + maxVisible);
1873
- useEffect10(() => {
2057
+ useEffect11(() => {
1874
2058
  loadHistory();
1875
2059
  }, []);
1876
2060
  const loadHistory = () => {
@@ -1981,7 +2165,7 @@ function History({ rows = 24 }) {
1981
2165
  }
1982
2166
 
1983
2167
  // src/screens/Marketplace.tsx
1984
- import { useState as useState15, useEffect as useEffect11 } from "react";
2168
+ import { useState as useState15, useEffect as useEffect12 } from "react";
1985
2169
  import { Box as Box13, Text as Text13, useInput as useInput11 } from "ink";
1986
2170
  import { jsx as jsx13, jsxs as jsxs13 } from "react/jsx-runtime";
1987
2171
  var SKILL_SOURCES = [
@@ -2001,7 +2185,7 @@ function Marketplace({ rows = 24 }) {
2001
2185
  const maxVisible = Math.max(5, rows - 10);
2002
2186
  const start = Math.max(0, Math.min(sel - Math.floor(maxVisible / 2), filtered.length - maxVisible));
2003
2187
  const visible = filtered.slice(start, start + maxVisible);
2004
- useEffect11(() => {
2188
+ useEffect12(() => {
2005
2189
  loadMarketplace();
2006
2190
  }, []);
2007
2191
  const loadMarketplace = async () => {
@@ -2140,7 +2324,7 @@ function Marketplace({ rows = 24 }) {
2140
2324
  }
2141
2325
 
2142
2326
  // src/screens/Memory.tsx
2143
- import { useState as useState16, useEffect as useEffect12 } from "react";
2327
+ import { useState as useState16, useEffect as useEffect13 } from "react";
2144
2328
  import { Box as Box14, Text as Text14, useInput as useInput12 } from "ink";
2145
2329
  import {
2146
2330
  ObservationStore,
@@ -2165,7 +2349,7 @@ function Memory({ rows = 24 }) {
2165
2349
  const currentList = tab === "search" ? searchResults : learnings;
2166
2350
  const start = Math.max(0, Math.min(sel - Math.floor(maxVisible / 2), currentList.length - maxVisible));
2167
2351
  const visible = currentList.slice(start, start + maxVisible);
2168
- useEffect12(() => {
2352
+ useEffect13(() => {
2169
2353
  loadMemory();
2170
2354
  }, [isGlobal]);
2171
2355
  const loadMemory = () => {
@@ -2400,10 +2584,360 @@ function Memory({ rows = 24 }) {
2400
2584
  ] });
2401
2585
  }
2402
2586
 
2403
- // src/App.tsx
2587
+ // src/screens/Team.tsx
2588
+ import { useState as useState17, useEffect as useEffect14 } from "react";
2589
+ import { Box as Box15, Text as Text15, useInput as useInput13 } from "ink";
2404
2590
  import { jsx as jsx15, jsxs as jsxs15 } from "react/jsx-runtime";
2591
+ function Team({ rows = 24 }) {
2592
+ const [config, setConfig] = useState17(null);
2593
+ const [skills, setSkills] = useState17([]);
2594
+ const [loading, setLoading] = useState17(true);
2595
+ const [error, setError] = useState17(null);
2596
+ const [sel, setSel] = useState17(0);
2597
+ const [message, setMessage] = useState17(null);
2598
+ const maxVisible = Math.max(5, rows - 12);
2599
+ const start = Math.max(0, Math.min(sel - Math.floor(maxVisible / 2), skills.length - maxVisible));
2600
+ const visible = skills.slice(start, start + maxVisible);
2601
+ useEffect14(() => {
2602
+ loadTeam();
2603
+ }, []);
2604
+ const loadTeam = async () => {
2605
+ setLoading(true);
2606
+ setError(null);
2607
+ try {
2608
+ const { createTeamManager } = await import("@skillkit/core");
2609
+ const manager = createTeamManager(process.cwd());
2610
+ const teamConfig = manager.load();
2611
+ if (!teamConfig) {
2612
+ setConfig(null);
2613
+ setSkills([]);
2614
+ setError("Team not initialized. Run `skillkit team init` first.");
2615
+ } else {
2616
+ setConfig(teamConfig);
2617
+ const sharedSkills = manager.listSharedSkills();
2618
+ setSkills(sharedSkills);
2619
+ setSel((s) => Math.min(s, Math.max(0, sharedSkills.length - 1)));
2620
+ }
2621
+ } catch (e) {
2622
+ setError(e instanceof Error ? e.message : "Failed to load team");
2623
+ }
2624
+ setLoading(false);
2625
+ };
2626
+ const syncTeam = async () => {
2627
+ if (!config) return;
2628
+ setLoading(true);
2629
+ setMessage(null);
2630
+ try {
2631
+ const { createTeamManager } = await import("@skillkit/core");
2632
+ const manager = createTeamManager(process.cwd());
2633
+ manager.load();
2634
+ const result = await manager.sync();
2635
+ const changes = [...result.added, ...result.updated];
2636
+ if (changes.length > 0) {
2637
+ setMessage(`Synced: ${changes.join(", ")}`);
2638
+ } else {
2639
+ setMessage("Already up to date");
2640
+ }
2641
+ const sharedSkills = manager.listSharedSkills();
2642
+ setSkills(sharedSkills);
2643
+ setSel((s) => Math.min(s, Math.max(0, sharedSkills.length - 1)));
2644
+ } catch (e) {
2645
+ setError(e instanceof Error ? e.message : "Sync failed");
2646
+ }
2647
+ setLoading(false);
2648
+ };
2649
+ const importSkill = async (skillName) => {
2650
+ if (!config) return;
2651
+ setLoading(true);
2652
+ setMessage(null);
2653
+ try {
2654
+ const { createTeamManager } = await import("@skillkit/core");
2655
+ const manager = createTeamManager(process.cwd());
2656
+ manager.load();
2657
+ const result = await manager.importSkill(skillName, { overwrite: false });
2658
+ if (result.success) {
2659
+ setMessage(`Imported: ${skillName}`);
2660
+ } else {
2661
+ setError(result.error || "Import failed");
2662
+ }
2663
+ } catch (e) {
2664
+ setError(e instanceof Error ? e.message : "Import failed");
2665
+ }
2666
+ setLoading(false);
2667
+ };
2668
+ useInput13((input, key) => {
2669
+ if (loading) return;
2670
+ if (skills.length === 0 && (key.upArrow || key.downArrow)) return;
2671
+ if (key.upArrow) setSel((i) => Math.max(0, i - 1));
2672
+ else if (key.downArrow) setSel((i) => Math.min(Math.max(0, skills.length - 1), i + 1));
2673
+ else if (input === "r") loadTeam();
2674
+ else if (input === "s") syncTeam();
2675
+ else if (key.return && skills[sel]) {
2676
+ importSkill(skills[sel].name);
2677
+ }
2678
+ });
2679
+ if (loading) {
2680
+ return /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", padding: 1, children: [
2681
+ /* @__PURE__ */ jsx15(Text15, { color: colors.primary, bold: true, children: "Team Collaboration" }),
2682
+ /* @__PURE__ */ jsx15(Box15, { marginTop: 1, children: /* @__PURE__ */ jsxs15(Text15, { color: colors.secondaryDim, children: [
2683
+ symbols.spinner[0],
2684
+ " Loading..."
2685
+ ] }) })
2686
+ ] });
2687
+ }
2688
+ if (!config) {
2689
+ return /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", padding: 1, children: [
2690
+ /* @__PURE__ */ jsx15(Text15, { color: colors.primary, bold: true, children: "Team Collaboration" }),
2691
+ /* @__PURE__ */ jsxs15(Box15, { marginTop: 1, flexDirection: "column", children: [
2692
+ /* @__PURE__ */ jsxs15(Text15, { color: colors.secondaryDim, children: [
2693
+ symbols.warning,
2694
+ " Team not initialized"
2695
+ ] }),
2696
+ /* @__PURE__ */ jsx15(Text15, { color: colors.secondaryDim, dimColor: true, children: 'Run: skillkit team init --name "Team Name" --registry <url>' })
2697
+ ] }),
2698
+ /* @__PURE__ */ jsx15(Box15, { marginTop: 1, children: /* @__PURE__ */ jsx15(Text15, { dimColor: true, children: "[r] Refresh" }) })
2699
+ ] });
2700
+ }
2701
+ return /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", padding: 1, children: [
2702
+ /* @__PURE__ */ jsxs15(Text15, { color: colors.primary, bold: true, children: [
2703
+ "Team: ",
2704
+ config.teamName
2705
+ ] }),
2706
+ /* @__PURE__ */ jsxs15(Text15, { color: colors.secondaryDim, dimColor: true, children: [
2707
+ "Registry: ",
2708
+ config.registryUrl
2709
+ ] }),
2710
+ error && /* @__PURE__ */ jsx15(Box15, { marginTop: 1, children: /* @__PURE__ */ jsxs15(Text15, { color: "red", children: [
2711
+ symbols.error,
2712
+ " ",
2713
+ error
2714
+ ] }) }),
2715
+ message && /* @__PURE__ */ jsx15(Box15, { marginTop: 1, children: /* @__PURE__ */ jsxs15(Text15, { color: "green", children: [
2716
+ symbols.success,
2717
+ " ",
2718
+ message
2719
+ ] }) }),
2720
+ /* @__PURE__ */ jsxs15(Box15, { marginTop: 1, flexDirection: "column", children: [
2721
+ /* @__PURE__ */ jsxs15(Text15, { color: colors.secondaryDim, bold: true, children: [
2722
+ "Shared Skills (",
2723
+ skills.length,
2724
+ ")"
2725
+ ] }),
2726
+ 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) => {
2727
+ const actualIndex = start + i;
2728
+ const isSelected = actualIndex === sel;
2729
+ return /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", children: [
2730
+ /* @__PURE__ */ jsxs15(Text15, { children: [
2731
+ isSelected ? symbols.pointer : " ",
2732
+ " ",
2733
+ /* @__PURE__ */ jsx15(Text15, { color: isSelected ? colors.primary : colors.secondaryDim, bold: isSelected, children: skill.name }),
2734
+ /* @__PURE__ */ jsxs15(Text15, { dimColor: true, children: [
2735
+ " v",
2736
+ skill.version
2737
+ ] }),
2738
+ /* @__PURE__ */ jsxs15(Text15, { dimColor: true, children: [
2739
+ " by ",
2740
+ skill.author
2741
+ ] }),
2742
+ skill.downloads !== void 0 && /* @__PURE__ */ jsxs15(Text15, { dimColor: true, children: [
2743
+ " | ",
2744
+ skill.downloads,
2745
+ " downloads"
2746
+ ] })
2747
+ ] }),
2748
+ skill.description && isSelected && /* @__PURE__ */ jsxs15(Text15, { color: colors.secondaryDim, dimColor: true, children: [
2749
+ " ",
2750
+ skill.description
2751
+ ] })
2752
+ ] }, skill.name);
2753
+ }) })
2754
+ ] }),
2755
+ /* @__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" }) })
2756
+ ] });
2757
+ }
2758
+
2759
+ // src/screens/Plugins.tsx
2760
+ import { useState as useState18, useEffect as useEffect15 } from "react";
2761
+ import { Box as Box16, Text as Text16, useInput as useInput14 } from "ink";
2762
+ import { jsx as jsx16, jsxs as jsxs16 } from "react/jsx-runtime";
2763
+ function Plugins({ rows = 24 }) {
2764
+ const [plugins, setPlugins] = useState18([]);
2765
+ const [loading, setLoading] = useState18(true);
2766
+ const [error, setError] = useState18(null);
2767
+ const [sel, setSel] = useState18(0);
2768
+ const [message, setMessage] = useState18(null);
2769
+ const maxVisible = Math.max(5, rows - 12);
2770
+ const start = Math.max(0, Math.min(sel - Math.floor(maxVisible / 2), plugins.length - maxVisible));
2771
+ const visible = plugins.slice(start, start + maxVisible);
2772
+ useEffect15(() => {
2773
+ loadPlugins();
2774
+ }, []);
2775
+ const loadPlugins = async () => {
2776
+ setLoading(true);
2777
+ setError(null);
2778
+ try {
2779
+ const { createPluginManager, loadPluginsFromDirectory } = await import("@skillkit/core");
2780
+ const { join: join6 } = await import("path");
2781
+ const manager = createPluginManager(process.cwd());
2782
+ const pluginsDir = join6(process.cwd(), ".skillkit", "plugins");
2783
+ try {
2784
+ const loadedPlugins = await loadPluginsFromDirectory(pluginsDir);
2785
+ for (const plugin of loadedPlugins) {
2786
+ if (!manager.getPlugin(plugin.metadata.name)) {
2787
+ await manager.register(plugin);
2788
+ }
2789
+ }
2790
+ } catch (err) {
2791
+ if (err && typeof err === "object" && "code" in err && err.code !== "ENOENT") {
2792
+ throw err;
2793
+ }
2794
+ }
2795
+ const allPlugins = manager.listPlugins();
2796
+ const pluginInfos = allPlugins.map((p) => {
2797
+ const plugin = manager.getPlugin(p.name);
2798
+ return {
2799
+ name: p.name,
2800
+ version: p.version,
2801
+ description: p.description,
2802
+ author: p.author,
2803
+ enabled: manager.isPluginEnabled(p.name),
2804
+ translators: plugin?.translators?.map((t) => t.agentType),
2805
+ providers: plugin?.providers?.map((pr) => pr.providerName),
2806
+ commands: plugin?.commands?.map((c) => c.name)
2807
+ };
2808
+ });
2809
+ setPlugins(pluginInfos);
2810
+ } catch (e) {
2811
+ setError(e instanceof Error ? e.message : "Failed to load plugins");
2812
+ }
2813
+ setLoading(false);
2814
+ };
2815
+ const togglePlugin = async (pluginName, currentEnabled) => {
2816
+ setLoading(true);
2817
+ setMessage(null);
2818
+ try {
2819
+ const { createPluginManager, loadPluginsFromDirectory } = await import("@skillkit/core");
2820
+ const { join: join6 } = await import("path");
2821
+ const manager = createPluginManager(process.cwd());
2822
+ const pluginsDir = join6(process.cwd(), ".skillkit", "plugins");
2823
+ try {
2824
+ const loadedPlugins = await loadPluginsFromDirectory(pluginsDir);
2825
+ for (const plugin of loadedPlugins) {
2826
+ if (!manager.getPlugin(plugin.metadata.name)) {
2827
+ await manager.register(plugin);
2828
+ }
2829
+ }
2830
+ } catch (err) {
2831
+ if (err && typeof err === "object" && "code" in err && err.code !== "ENOENT") {
2832
+ throw err;
2833
+ }
2834
+ }
2835
+ if (currentEnabled) {
2836
+ manager.disablePlugin(pluginName);
2837
+ setMessage(`Disabled: ${pluginName}`);
2838
+ } else {
2839
+ manager.enablePlugin(pluginName);
2840
+ setMessage(`Enabled: ${pluginName}`);
2841
+ }
2842
+ await loadPlugins();
2843
+ } catch (e) {
2844
+ setError(e instanceof Error ? e.message : "Toggle failed");
2845
+ setLoading(false);
2846
+ }
2847
+ };
2848
+ useInput14((input, key) => {
2849
+ if (loading) return;
2850
+ if (plugins.length === 0 && (key.upArrow || key.downArrow)) return;
2851
+ if (key.upArrow) setSel((i) => Math.max(0, i - 1));
2852
+ else if (key.downArrow) setSel((i) => Math.min(Math.max(0, plugins.length - 1), i + 1));
2853
+ else if (input === "r") loadPlugins();
2854
+ else if (input === "e" && plugins[sel]) {
2855
+ togglePlugin(plugins[sel].name, plugins[sel].enabled);
2856
+ } else if (key.return && plugins[sel]) {
2857
+ togglePlugin(plugins[sel].name, plugins[sel].enabled);
2858
+ }
2859
+ });
2860
+ if (loading) {
2861
+ return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", padding: 1, children: [
2862
+ /* @__PURE__ */ jsx16(Text16, { color: colors.primary, bold: true, children: "Plugin Manager" }),
2863
+ /* @__PURE__ */ jsx16(Box16, { marginTop: 1, children: /* @__PURE__ */ jsxs16(Text16, { color: colors.secondaryDim, children: [
2864
+ symbols.spinner[0],
2865
+ " Loading..."
2866
+ ] }) })
2867
+ ] });
2868
+ }
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(Text16, { color: colors.secondaryDim, dimColor: true, children: "Manage SkillKit extensions" }),
2872
+ error && /* @__PURE__ */ jsx16(Box16, { marginTop: 1, children: /* @__PURE__ */ jsxs16(Text16, { color: "red", children: [
2873
+ symbols.error,
2874
+ " ",
2875
+ error
2876
+ ] }) }),
2877
+ message && /* @__PURE__ */ jsx16(Box16, { marginTop: 1, children: /* @__PURE__ */ jsxs16(Text16, { color: "green", children: [
2878
+ symbols.success,
2879
+ " ",
2880
+ message
2881
+ ] }) }),
2882
+ /* @__PURE__ */ jsxs16(Box16, { marginTop: 1, flexDirection: "column", children: [
2883
+ /* @__PURE__ */ jsxs16(Text16, { color: colors.secondaryDim, bold: true, children: [
2884
+ "Installed Plugins (",
2885
+ plugins.length,
2886
+ ")"
2887
+ ] }),
2888
+ plugins.length === 0 ? /* @__PURE__ */ jsxs16(Box16, { marginTop: 1, flexDirection: "column", children: [
2889
+ /* @__PURE__ */ jsx16(Text16, { color: colors.secondaryDim, dimColor: true, children: "No plugins installed." }),
2890
+ /* @__PURE__ */ jsx16(Text16, { color: colors.secondaryDim, dimColor: true, children: "Use: skillkit plugin install --source <path-or-package>" })
2891
+ ] }) : /* @__PURE__ */ jsx16(Box16, { flexDirection: "column", marginTop: 1, children: visible.map((plugin, i) => {
2892
+ const actualIndex = start + i;
2893
+ const isSelected = actualIndex === sel;
2894
+ const statusColor = plugin.enabled ? "green" : "gray";
2895
+ const statusText = plugin.enabled ? "enabled" : "disabled";
2896
+ return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", children: [
2897
+ /* @__PURE__ */ jsxs16(Text16, { children: [
2898
+ isSelected ? symbols.pointer : " ",
2899
+ " ",
2900
+ /* @__PURE__ */ jsx16(Text16, { color: isSelected ? colors.primary : colors.secondaryDim, bold: isSelected, children: plugin.name }),
2901
+ /* @__PURE__ */ jsxs16(Text16, { dimColor: true, children: [
2902
+ " v",
2903
+ plugin.version
2904
+ ] }),
2905
+ /* @__PURE__ */ jsxs16(Text16, { color: statusColor, children: [
2906
+ " [",
2907
+ statusText,
2908
+ "]"
2909
+ ] })
2910
+ ] }),
2911
+ isSelected && /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", marginLeft: 3, children: [
2912
+ plugin.description && /* @__PURE__ */ jsx16(Text16, { color: colors.secondaryDim, dimColor: true, children: plugin.description }),
2913
+ plugin.author && /* @__PURE__ */ jsxs16(Text16, { dimColor: true, children: [
2914
+ "Author: ",
2915
+ plugin.author
2916
+ ] }),
2917
+ plugin.translators && plugin.translators.length > 0 && /* @__PURE__ */ jsxs16(Text16, { dimColor: true, children: [
2918
+ "Translators: ",
2919
+ plugin.translators.join(", ")
2920
+ ] }),
2921
+ plugin.providers && plugin.providers.length > 0 && /* @__PURE__ */ jsxs16(Text16, { dimColor: true, children: [
2922
+ "Providers: ",
2923
+ plugin.providers.join(", ")
2924
+ ] }),
2925
+ plugin.commands && plugin.commands.length > 0 && /* @__PURE__ */ jsxs16(Text16, { dimColor: true, children: [
2926
+ "Commands: ",
2927
+ plugin.commands.join(", ")
2928
+ ] })
2929
+ ] })
2930
+ ] }, plugin.name);
2931
+ }) })
2932
+ ] }),
2933
+ /* @__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" }) })
2934
+ ] });
2935
+ }
2936
+
2937
+ // src/App.tsx
2938
+ import { jsx as jsx17, jsxs as jsxs17 } from "react/jsx-runtime";
2405
2939
  function App() {
2406
- const [screen, setScreen] = useState17("home");
2940
+ const [screen, setScreen] = useState19("home");
2407
2941
  const { exit } = useApp();
2408
2942
  const { stdout } = useStdout();
2409
2943
  const cols = stdout?.columns || 80;
@@ -2422,9 +2956,11 @@ function App() {
2422
2956
  e: "memory",
2423
2957
  i: "installed",
2424
2958
  s: "sync",
2959
+ a: "team",
2960
+ p: "plugins",
2425
2961
  ",": "settings"
2426
2962
  };
2427
- useInput13((input, key) => {
2963
+ useInput15((input, key) => {
2428
2964
  if (input === "q") {
2429
2965
  exit();
2430
2966
  return;
@@ -2441,63 +2977,67 @@ function App() {
2441
2977
  const renderScreen = () => {
2442
2978
  switch (screen) {
2443
2979
  case "home":
2444
- return /* @__PURE__ */ jsx15(Home, { onNavigate: setScreen, cols, rows });
2980
+ return /* @__PURE__ */ jsx17(Home, { onNavigate: setScreen, cols, rows });
2445
2981
  case "browse":
2446
- return /* @__PURE__ */ jsx15(Browse, { cols, rows });
2982
+ return /* @__PURE__ */ jsx17(Browse, { cols, rows });
2447
2983
  case "installed":
2448
- return /* @__PURE__ */ jsx15(Installed, { cols, rows });
2984
+ return /* @__PURE__ */ jsx17(Installed, { cols, rows });
2449
2985
  case "sync":
2450
- return /* @__PURE__ */ jsx15(Sync, { cols, rows });
2986
+ return /* @__PURE__ */ jsx17(Sync, { cols, rows });
2451
2987
  case "settings":
2452
- return /* @__PURE__ */ jsx15(Settings, { cols, rows });
2988
+ return /* @__PURE__ */ jsx17(Settings, { cols, rows });
2453
2989
  case "recommend":
2454
- return /* @__PURE__ */ jsx15(Recommend, { cols, rows });
2990
+ return /* @__PURE__ */ jsx17(Recommend, { cols, rows });
2455
2991
  case "translate":
2456
- return /* @__PURE__ */ jsx15(Translate, { cols, rows });
2992
+ return /* @__PURE__ */ jsx17(Translate, { cols, rows });
2457
2993
  case "context":
2458
- return /* @__PURE__ */ jsx15(Context, { cols, rows });
2994
+ return /* @__PURE__ */ jsx17(Context, { cols, rows });
2459
2995
  case "workflow":
2460
- return /* @__PURE__ */ jsx15(Workflow, { cols, rows });
2996
+ return /* @__PURE__ */ jsx17(Workflow, { cols, rows });
2461
2997
  case "execute":
2462
- return /* @__PURE__ */ jsx15(Execute, { cols, rows });
2998
+ return /* @__PURE__ */ jsx17(Execute, { cols, rows });
2463
2999
  case "history":
2464
- return /* @__PURE__ */ jsx15(History, { cols, rows });
3000
+ return /* @__PURE__ */ jsx17(History, { cols, rows });
2465
3001
  case "marketplace":
2466
- return /* @__PURE__ */ jsx15(Marketplace, { cols, rows });
3002
+ return /* @__PURE__ */ jsx17(Marketplace, { cols, rows });
2467
3003
  case "memory":
2468
- return /* @__PURE__ */ jsx15(Memory, { cols, rows });
3004
+ return /* @__PURE__ */ jsx17(Memory, { cols, rows });
3005
+ case "team":
3006
+ return /* @__PURE__ */ jsx17(Team, { cols, rows });
3007
+ case "plugins":
3008
+ return /* @__PURE__ */ jsx17(Plugins, { cols, rows });
2469
3009
  }
2470
3010
  };
2471
3011
  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() })
3012
+ return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", height: rows, children: [
3013
+ /* @__PURE__ */ jsxs17(Box17, { flexDirection: "row", height: contentHeight, children: [
3014
+ showSidebar && /* @__PURE__ */ jsx17(Sidebar, { screen, onNavigate: setScreen }),
3015
+ /* @__PURE__ */ jsx17(Box17, { flexDirection: "column", flexGrow: 1, marginLeft: 1, children: renderScreen() })
2476
3016
  ] }),
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" }) })
3017
+ /* @__PURE__ */ jsx17(Box17, { children: /* @__PURE__ */ jsx17(Text17, { dimColor: true, children: "h Home m Market b Browse i Inst w Wflow x Exec a Team p Plug r Rec t Trans c Ctx e Mem s Sync , Cfg q Quit" }) })
2478
3018
  ] });
2479
3019
  }
2480
3020
 
2481
3021
  // 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";
3022
+ import { Box as Box18, Text as Text18 } from "ink";
3023
+ import { jsx as jsx18, jsxs as jsxs18 } from "react/jsx-runtime";
2484
3024
  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: [
3025
+ return /* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", marginBottom: 1, children: [
3026
+ /* @__PURE__ */ jsxs18(Box18, { justifyContent: "space-between", children: [
3027
+ /* @__PURE__ */ jsx18(Text18, { color: colors.primary, bold: true, children: title.toUpperCase() }),
3028
+ count !== void 0 && /* @__PURE__ */ jsxs18(Text18, { color: colors.secondaryDim, children: [
2489
3029
  symbols.star,
2490
3030
  " ",
2491
3031
  count
2492
3032
  ] })
2493
3033
  ] }),
2494
- subtitle && /* @__PURE__ */ jsx16(Text16, { color: colors.secondaryDim, dimColor: true, children: subtitle })
3034
+ subtitle && /* @__PURE__ */ jsx18(Text18, { color: colors.secondaryDim, dimColor: true, children: subtitle })
2495
3035
  ] });
2496
3036
  }
2497
3037
 
2498
3038
  // 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";
3039
+ import { Box as Box19, Text as Text19 } from "ink";
3040
+ import { jsx as jsx19, jsxs as jsxs19 } from "react/jsx-runtime";
2501
3041
  function formatInstalls(count) {
2502
3042
  if (count >= 1e3) {
2503
3043
  return `${(count / 1e3).toFixed(1)}K`;
@@ -2513,13 +3053,13 @@ function SkillList({
2513
3053
  maxVisible = 10
2514
3054
  }) {
2515
3055
  if (skills.length === 0) {
2516
- return /* @__PURE__ */ jsx17(Box17, { children: /* @__PURE__ */ jsx17(Text17, { color: colors.secondaryDim, dimColor: true, children: "No skills found" }) });
3056
+ return /* @__PURE__ */ jsx19(Box19, { children: /* @__PURE__ */ jsx19(Text19, { color: colors.secondaryDim, dimColor: true, children: "No skills found" }) });
2517
3057
  }
2518
3058
  const startIndex = Math.max(0, selectedIndex - Math.floor(maxVisible / 2));
2519
3059
  const visibleSkills = skills.slice(startIndex, startIndex + maxVisible);
2520
3060
  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: [
3061
+ return /* @__PURE__ */ jsxs19(Box19, { flexDirection: "column", children: [
3062
+ showRank && /* @__PURE__ */ jsx19(Box19, { marginBottom: 1, children: /* @__PURE__ */ jsxs19(Text19, { color: colors.secondaryDim, children: [
2523
3063
  " # SKILL",
2524
3064
  showSource && " SOURCE",
2525
3065
  showInstalls && " INSTALLS"
@@ -2529,9 +3069,9 @@ function SkillList({
2529
3069
  const isSelected = realIndex === selectedIndex;
2530
3070
  const skillName = skill.name.padEnd(28).slice(0, 28);
2531
3071
  const sourceName = skill.source ? skill.source.slice(0, 25) : "";
2532
- return /* @__PURE__ */ jsxs17(Box17, { children: [
2533
- /* @__PURE__ */ jsxs17(
2534
- Text17,
3072
+ return /* @__PURE__ */ jsxs19(Box19, { children: [
3073
+ /* @__PURE__ */ jsxs19(
3074
+ Text19,
2535
3075
  {
2536
3076
  color: isSelected ? colors.primary : colors.secondary,
2537
3077
  bold: isSelected,
@@ -2544,14 +3084,14 @@ function SkillList({
2544
3084
  ]
2545
3085
  }
2546
3086
  ),
2547
- showSource && /* @__PURE__ */ jsxs17(Text17, { color: colors.secondaryDim, dimColor: !isSelected, children: [
3087
+ showSource && /* @__PURE__ */ jsxs19(Text19, { color: colors.secondaryDim, dimColor: !isSelected, children: [
2548
3088
  " ",
2549
3089
  sourceName
2550
3090
  ] }),
2551
- showInstalls && skill.installs !== void 0 && /* @__PURE__ */ jsx17(Text17, { color: colors.secondaryDim, children: formatInstalls(skill.installs).padStart(8) })
3091
+ showInstalls && skill.installs !== void 0 && /* @__PURE__ */ jsx19(Text19, { color: colors.secondaryDim, children: formatInstalls(skill.installs).padStart(8) })
2552
3092
  ] }, `${skill.source}-${skill.name}`);
2553
3093
  }),
2554
- skills.length > maxVisible && /* @__PURE__ */ jsx17(Box17, { marginTop: 1, children: /* @__PURE__ */ jsxs17(Text17, { color: colors.secondaryDim, dimColor: true, children: [
3094
+ skills.length > maxVisible && /* @__PURE__ */ jsx19(Box19, { marginTop: 1, children: /* @__PURE__ */ jsxs19(Text19, { color: colors.secondaryDim, dimColor: true, children: [
2555
3095
  "Showing ",
2556
3096
  startIndex + 1,
2557
3097
  "-",
@@ -2563,11 +3103,11 @@ function SkillList({
2563
3103
  }
2564
3104
 
2565
3105
  // 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";
3106
+ import { Box as Box20, Text as Text20 } from "ink";
3107
+ import { jsx as jsx20, jsxs as jsxs20 } from "react/jsx-runtime";
2568
3108
  function StatusBar({ shortcuts, message }) {
2569
- return /* @__PURE__ */ jsxs18(
2570
- Box18,
3109
+ return /* @__PURE__ */ jsxs20(
3110
+ Box20,
2571
3111
  {
2572
3112
  borderStyle: "single",
2573
3113
  borderColor: colors.borderDim,
@@ -2578,11 +3118,11 @@ function StatusBar({ shortcuts, message }) {
2578
3118
  paddingX: 1,
2579
3119
  justifyContent: "space-between",
2580
3120
  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 })
3121
+ /* @__PURE__ */ jsx20(Box20, { gap: 2, children: shortcuts.map((shortcut, idx) => /* @__PURE__ */ jsxs20(Box20, { gap: 1, children: [
3122
+ /* @__PURE__ */ jsx20(Text20, { color: colors.primary, bold: true, children: shortcut.key }),
3123
+ /* @__PURE__ */ jsx20(Text20, { color: colors.secondaryDim, children: shortcut.label })
2584
3124
  ] }, idx)) }),
2585
- message && /* @__PURE__ */ jsxs18(Text18, { color: colors.success, children: [
3125
+ message && /* @__PURE__ */ jsxs20(Text20, { color: colors.success, children: [
2586
3126
  symbols.check,
2587
3127
  " ",
2588
3128
  message
@@ -2593,44 +3133,44 @@ function StatusBar({ shortcuts, message }) {
2593
3133
  }
2594
3134
 
2595
3135
  // 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";
3136
+ import { Box as Box21, Text as Text21 } from "ink";
3137
+ import TextInput2 from "ink-text-input";
3138
+ import { jsx as jsx21, jsxs as jsxs21 } from "react/jsx-runtime";
2599
3139
  function SearchInput({
2600
3140
  value,
2601
3141
  onChange,
2602
3142
  placeholder = "Search skills...",
2603
3143
  isFocused = false
2604
3144
  }) {
2605
- return /* @__PURE__ */ jsxs19(
2606
- Box19,
3145
+ return /* @__PURE__ */ jsxs21(
3146
+ Box21,
2607
3147
  {
2608
3148
  borderStyle: "single",
2609
3149
  borderColor: isFocused ? colors.primary : colors.borderDim,
2610
3150
  paddingX: 1,
2611
3151
  children: [
2612
- /* @__PURE__ */ jsx19(Text19, { color: colors.secondaryDim, children: "/ " }),
2613
- isFocused ? /* @__PURE__ */ jsx19(
2614
- TextInput,
3152
+ /* @__PURE__ */ jsx21(Text21, { color: colors.secondaryDim, children: "/ " }),
3153
+ isFocused ? /* @__PURE__ */ jsx21(
3154
+ TextInput2,
2615
3155
  {
2616
3156
  value,
2617
3157
  onChange,
2618
3158
  placeholder
2619
3159
  }
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: "/" })
3160
+ ) : /* @__PURE__ */ jsx21(Text21, { color: value ? colors.secondary : colors.secondaryDim, children: value || placeholder }),
3161
+ /* @__PURE__ */ jsx21(Box21, { flexGrow: 1 }),
3162
+ /* @__PURE__ */ jsx21(Text21, { color: colors.secondaryDim, children: "/" })
2623
3163
  ]
2624
3164
  }
2625
3165
  );
2626
3166
  }
2627
3167
 
2628
3168
  // 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";
3169
+ import { useState as useState20, useCallback as useCallback3, useEffect as useEffect16 } from "react";
3170
+ import { useInput as useInput16, useApp as useApp2 } from "ink";
2631
3171
  function useKeyboard(options = {}) {
2632
3172
  const { exit } = useApp2();
2633
- useInput14((input, key) => {
3173
+ useInput16((input, key) => {
2634
3174
  if (options.disabled) return;
2635
3175
  if (input === "q" || key.ctrl && input === "c") {
2636
3176
  exit();
@@ -2674,8 +3214,8 @@ function useKeyboard(options = {}) {
2674
3214
  });
2675
3215
  }
2676
3216
  function useListNavigation(listLength, initialIndex = 0) {
2677
- const [selectedIndex, setSelectedIndex] = useState18(initialIndex);
2678
- useEffect13(() => {
3217
+ const [selectedIndex, setSelectedIndex] = useState20(initialIndex);
3218
+ useEffect16(() => {
2679
3219
  if (selectedIndex >= listLength && listLength > 0) {
2680
3220
  setSelectedIndex(listLength - 1);
2681
3221
  }
@@ -2693,7 +3233,7 @@ function useListNavigation(listLength, initialIndex = 0) {
2693
3233
  }
2694
3234
 
2695
3235
  // src/hooks/useMemory.ts
2696
- import { useState as useState19, useEffect as useEffect14, useCallback as useCallback4 } from "react";
3236
+ import { useState as useState21, useEffect as useEffect17, useCallback as useCallback4 } from "react";
2697
3237
  import {
2698
3238
  LearningStore as LearningStore2,
2699
3239
  ObservationStore as ObservationStore2,
@@ -2701,12 +3241,12 @@ import {
2701
3241
  createMemoryInjector as createMemoryInjector2
2702
3242
  } from "@skillkit/core";
2703
3243
  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);
3244
+ const [learnings, setLearnings] = useState21([]);
3245
+ const [observations, setObservations] = useState21([]);
3246
+ const [status, setStatus] = useState21(null);
3247
+ const [loading, setLoading] = useState21(true);
3248
+ const [error, setError] = useState21(null);
3249
+ const [isGlobal, setIsGlobal] = useState21(false);
2710
3250
  const projectPath = process.cwd();
2711
3251
  const refresh = useCallback4(() => {
2712
3252
  setLoading(true);
@@ -2785,7 +3325,7 @@ function useMemory() {
2785
3325
  },
2786
3326
  [projectPath, refresh]
2787
3327
  );
2788
- useEffect14(() => {
3328
+ useEffect17(() => {
2789
3329
  refresh();
2790
3330
  }, [refresh]);
2791
3331
  return {
@@ -2804,10 +3344,10 @@ function useMemory() {
2804
3344
  }
2805
3345
 
2806
3346
  // src/index.tsx
2807
- import { jsx as jsx20 } from "react/jsx-runtime";
3347
+ import { jsx as jsx22 } from "react/jsx-runtime";
2808
3348
  function startTUI() {
2809
3349
  process.stdout.write("\x1B[2J\x1B[0f");
2810
- const { waitUntilExit, clear } = render(/* @__PURE__ */ jsx20(App, {}), {
3350
+ const { waitUntilExit, clear } = render(/* @__PURE__ */ jsx22(App, {}), {
2811
3351
  exitOnCtrlC: true
2812
3352
  });
2813
3353
  return waitUntilExit().then(() => {
@@ -2825,6 +3365,7 @@ export {
2825
3365
  Installed,
2826
3366
  Marketplace,
2827
3367
  Memory,
3368
+ Plugins,
2828
3369
  Recommend,
2829
3370
  SearchInput,
2830
3371
  Settings,
@@ -2832,6 +3373,7 @@ export {
2832
3373
  SkillList,
2833
3374
  StatusBar,
2834
3375
  Sync,
3376
+ Team,
2835
3377
  Translate,
2836
3378
  Workflow,
2837
3379
  colors,