@m14i/sith 1.14.1 → 1.15.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.
@@ -1 +1 @@
1
- {"version":3,"file":"docker.d.ts","sourceRoot":"","sources":["file:///home/runner/work/sith/sith/src/commands/docker.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAkC,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAmRxF,wBAAsB,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAoBhF;AAED,wBAAsB,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,CAEpD"}
1
+ {"version":3,"file":"docker.d.ts","sourceRoot":"","sources":["file:///home/runner/work/sith/sith/src/commands/docker.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAkC,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAoTxF,wBAAsB,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAoBhF;AAED,wBAAsB,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,CAEpD"}
@@ -0,0 +1,7 @@
1
+ import type { NixCommandOptions } from "../types.js";
2
+ export declare function checkNixInstalled(): Promise<boolean>;
3
+ export declare function installNix(): Promise<void>;
4
+ export declare function copyNixFiles(): Promise<void>;
5
+ export declare function runNixShell(): Promise<void>;
6
+ export declare function nixCommand(options: NixCommandOptions): Promise<void>;
7
+ //# sourceMappingURL=nix.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nix.d.ts","sourceRoot":"","sources":["file:///home/runner/work/sith/sith/src/commands/nix.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAsBrD,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,OAAO,CAAC,CAc1D;AAED,wBAAsB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAkChD;AAED,wBAAsB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAuClD;AAED,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAoDjD;AAED,wBAAsB,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAc1E"}
@@ -0,0 +1,2 @@
1
+ export declare function skillsCommand(): void;
2
+ //# sourceMappingURL=skills.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["file:///home/runner/work/sith/sith/src/commands/skills.tsx"],"names":[],"mappings":"AA6FA,wBAAgB,aAAa,IAAI,IAAI,CAEpC"}
@@ -1 +1 @@
1
- {"version":3,"file":"TerminalUI.d.ts","sourceRoot":"","sources":["file:///home/runner/work/sith/sith/src/components/TerminalUI.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAgC,MAAM,OAAO,CAAC;AA0JrD,wBAAgB,UAAU,IAAI,KAAK,CAAC,YAAY,CAkL/C;AAED,wBAAgB,gBAAgB,IAAI,IAAI,CAEvC"}
1
+ {"version":3,"file":"TerminalUI.d.ts","sourceRoot":"","sources":["file:///home/runner/work/sith/sith/src/components/TerminalUI.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAgC,MAAM,OAAO,CAAC;AAiKrD,wBAAgB,UAAU,IAAI,KAAK,CAAC,YAAY,CAuL/C;AAED,wBAAgB,gBAAgB,IAAI,IAAI,CAEvC"}
package/dist/config.d.ts CHANGED
@@ -1,11 +1,21 @@
1
+ import type { SkillEntry } from "./types.js";
2
+ export declare const SKILLS_CATALOG: SkillEntry[];
1
3
  export declare const DOCKER_CONFIG: {
2
4
  readonly imageName: "sith:latest";
3
5
  readonly prebuiltImage: "ghcr.io/merzoukemansouri/sith:latest";
4
6
  readonly folderName: "docker";
5
7
  readonly dockerfileName: "Dockerfile";
6
8
  readonly workspaceMount: "/workspace";
9
+ readonly skillsMount: "/opt/sith/external-skills";
7
10
  readonly shellEntrypoint: "/opt/sith/nix/shell.nix";
8
11
  };
12
+ export declare const NIX_CONFIG: {
13
+ readonly shellPath: "docker/nix/shell.nix";
14
+ readonly flakePath: "docker/nix/flake.nix";
15
+ readonly installerUrl: "https://nixos.org/nix/install";
16
+ readonly requiredVersion: "2.19";
17
+ readonly localConfigDir: ".sith/nix";
18
+ };
9
19
  export declare const SPINNER_CONFIG: {
10
20
  readonly frames: readonly ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
11
21
  readonly interval: 80;
@@ -1 +1 @@
1
- {"version":3,"file":"","sourceRoot":"","sources":["file:///home/runner/work/sith/sith/src/config.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,aAAa;;;;;;;CAOhB,CAAC;AAGX,eAAO,MAAM,cAAc;;;CAGjB,CAAC;AAGX,eAAO,MAAM,UAAU,mOAOb,CAAC"}
1
+ {"version":3,"file":"","sourceRoot":"","sources":["file:///home/runner/work/sith/sith/src/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAG7C,eAAO,MAAM,cAAc,EAAE,UAAU,EAOtC,CAAC;AAGF,eAAO,MAAM,aAAa;;;;;;;;CAQhB,CAAC;AAGX,eAAO,MAAM,UAAU;;;;;;CAMb,CAAC;AAGX,eAAO,MAAM,cAAc;;;CAGjB,CAAC;AAGX,eAAO,MAAM,UAAU,mOAOb,CAAC"}
package/dist/index.js CHANGED
@@ -42972,7 +42972,7 @@ __nccwpck_require__.a(module, async (__webpack_handle_async_dependencies__, __we
42972
42972
  /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __nccwpck_require__(2864);
42973
42973
  /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__nccwpck_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
42974
42974
  /* harmony import */ var ink__WEBPACK_IMPORTED_MODULE_1__ = __nccwpck_require__(3816);
42975
- /* harmony import */ var execa__WEBPACK_IMPORTED_MODULE_6__ = __nccwpck_require__(6181);
42975
+ /* harmony import */ var execa__WEBPACK_IMPORTED_MODULE_9__ = __nccwpck_require__(6181);
42976
42976
  /* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_2__ = __nccwpck_require__(9896);
42977
42977
  /* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__nccwpck_require__.n(fs__WEBPACK_IMPORTED_MODULE_2__);
42978
42978
  /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3__ = __nccwpck_require__(6928);
@@ -42980,8 +42980,14 @@ __nccwpck_require__.a(module, async (__webpack_handle_async_dependencies__, __we
42980
42980
  /* harmony import */ var url__WEBPACK_IMPORTED_MODULE_4__ = __nccwpck_require__(7016);
42981
42981
  /* harmony import */ var url__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__nccwpck_require__.n(url__WEBPACK_IMPORTED_MODULE_4__);
42982
42982
  /* harmony import */ var _config_js__WEBPACK_IMPORTED_MODULE_5__ = __nccwpck_require__(6878);
42983
- var __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([ink__WEBPACK_IMPORTED_MODULE_1__]);
42984
- ink__WEBPACK_IMPORTED_MODULE_1__ = (__webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__)[0];
42983
+ /* harmony import */ var _nix_js__WEBPACK_IMPORTED_MODULE_6__ = __nccwpck_require__(9922);
42984
+ /* harmony import */ var _utils_skills_js__WEBPACK_IMPORTED_MODULE_7__ = __nccwpck_require__(6400);
42985
+ /* harmony import */ var _skills_js__WEBPACK_IMPORTED_MODULE_8__ = __nccwpck_require__(9805);
42986
+ var __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([ink__WEBPACK_IMPORTED_MODULE_1__, _skills_js__WEBPACK_IMPORTED_MODULE_8__]);
42987
+ ([ink__WEBPACK_IMPORTED_MODULE_1__, _skills_js__WEBPACK_IMPORTED_MODULE_8__] = __webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__);
42988
+
42989
+
42990
+
42985
42991
 
42986
42992
 
42987
42993
 
@@ -43006,11 +43012,13 @@ function findProjectRoot(startDir) {
43006
43012
  const rootDir = findProjectRoot(__dirname);
43007
43013
  const menuItems = [
43008
43014
  { label: "Enter Shell", value: "shell", icon: "🚀" },
43015
+ { label: "Manage Skills", value: "skills", icon: "🧠" },
43009
43016
  { label: "Configuration", value: "config", icon: "⚙️" },
43010
43017
  ];
43011
43018
  const configMenuItems = [
43012
43019
  { label: "Pull prebuilt image (recommended)", value: "pull", icon: "📦" },
43013
43020
  { label: "Build Docker image from scratch", value: "build", icon: "🔨" },
43021
+ { label: "Install Nix locally (no Docker)", value: "nix", icon: "❄️" },
43014
43022
  { label: "Back", value: "back", icon: "◀️" },
43015
43023
  ];
43016
43024
  function Logo() {
@@ -43067,6 +43075,10 @@ function Menu() {
43067
43075
  exit();
43068
43076
  await runShell();
43069
43077
  return;
43078
+ case "skills":
43079
+ exit();
43080
+ (0,_skills_js__WEBPACK_IMPORTED_MODULE_8__/* .skillsCommand */ .a)();
43081
+ return;
43070
43082
  case "config":
43071
43083
  setCurrentMenu("config");
43072
43084
  setSelectedIndex(0);
@@ -43081,6 +43093,9 @@ function Menu() {
43081
43093
  case "build":
43082
43094
  await handleBuildCommand();
43083
43095
  break;
43096
+ case "nix":
43097
+ await handleNixCommand();
43098
+ break;
43084
43099
  default:
43085
43100
  break;
43086
43101
  }
@@ -43089,11 +43104,11 @@ function Menu() {
43089
43104
  setIsProcessing(true);
43090
43105
  setProcessStep("Pulling prebuilt Docker image...");
43091
43106
  try {
43092
- await (0,execa__WEBPACK_IMPORTED_MODULE_6__/* .execa */ .Ho)("docker", ["pull", _config_js__WEBPACK_IMPORTED_MODULE_5__/* .DOCKER_CONFIG */ .e6.prebuiltImage], {
43107
+ await (0,execa__WEBPACK_IMPORTED_MODULE_9__/* .execa */ .Ho)("docker", ["pull", _config_js__WEBPACK_IMPORTED_MODULE_5__/* .DOCKER_CONFIG */ .e6.prebuiltImage], {
43093
43108
  stdio: "inherit",
43094
43109
  });
43095
43110
  // Tag the pulled image with local name for compatibility
43096
- await (0,execa__WEBPACK_IMPORTED_MODULE_6__/* .execa */ .Ho)("docker", ["tag", _config_js__WEBPACK_IMPORTED_MODULE_5__/* .DOCKER_CONFIG */ .e6.prebuiltImage, _config_js__WEBPACK_IMPORTED_MODULE_5__/* .DOCKER_CONFIG */ .e6.imageName], {
43111
+ await (0,execa__WEBPACK_IMPORTED_MODULE_9__/* .execa */ .Ho)("docker", ["tag", _config_js__WEBPACK_IMPORTED_MODULE_5__/* .DOCKER_CONFIG */ .e6.prebuiltImage, _config_js__WEBPACK_IMPORTED_MODULE_5__/* .DOCKER_CONFIG */ .e6.imageName], {
43097
43112
  stdio: "inherit",
43098
43113
  });
43099
43114
  setIsProcessing(false);
@@ -43105,6 +43120,21 @@ function Menu() {
43105
43120
  setProcessError(error instanceof Error ? error.message : "Pull failed");
43106
43121
  }
43107
43122
  }
43123
+ async function handleNixCommand() {
43124
+ setIsProcessing(true);
43125
+ setProcessStep("Installing Nix locally...");
43126
+ try {
43127
+ await (0,_nix_js__WEBPACK_IMPORTED_MODULE_6__/* .installNix */ .Fh)();
43128
+ await (0,_nix_js__WEBPACK_IMPORTED_MODULE_6__/* .copyNixFiles */ .Qi)();
43129
+ setIsProcessing(false);
43130
+ setProcessComplete(true);
43131
+ setProcessStep("");
43132
+ }
43133
+ catch (error) {
43134
+ setIsProcessing(false);
43135
+ setProcessError(error instanceof Error ? error.message : "Nix installation failed");
43136
+ }
43137
+ }
43108
43138
  async function handleBuildCommand() {
43109
43139
  setIsProcessing(true);
43110
43140
  setProcessStep("Building Docker image from scratch...");
@@ -43113,7 +43143,7 @@ function Menu() {
43113
43143
  if (!fs__WEBPACK_IMPORTED_MODULE_2___default().existsSync(dockerfilePath)) {
43114
43144
  throw new Error(`Dockerfile not found at: ${dockerfilePath}`);
43115
43145
  }
43116
- await (0,execa__WEBPACK_IMPORTED_MODULE_6__/* .execa */ .Ho)("docker", ["build", "-f", dockerfilePath, "-t", _config_js__WEBPACK_IMPORTED_MODULE_5__/* .DOCKER_CONFIG */ .e6.imageName, rootDir], {
43146
+ await (0,execa__WEBPACK_IMPORTED_MODULE_9__/* .execa */ .Ho)("docker", ["build", "-f", dockerfilePath, "-t", _config_js__WEBPACK_IMPORTED_MODULE_5__/* .DOCKER_CONFIG */ .e6.imageName, rootDir], {
43117
43147
  stdio: "inherit",
43118
43148
  });
43119
43149
  setIsProcessing(false);
@@ -43208,12 +43238,12 @@ async function pullDocker() {
43208
43238
  console.log(`Source: ${_config_js__WEBPACK_IMPORTED_MODULE_5__/* .DOCKER_CONFIG */ .e6.prebuiltImage}`);
43209
43239
  console.log(`Target: ${_config_js__WEBPACK_IMPORTED_MODULE_5__/* .DOCKER_CONFIG */ .e6.imageName}`);
43210
43240
  console.log();
43211
- await (0,execa__WEBPACK_IMPORTED_MODULE_6__/* .execa */ .Ho)("docker", ["pull", _config_js__WEBPACK_IMPORTED_MODULE_5__/* .DOCKER_CONFIG */ .e6.prebuiltImage], {
43241
+ await (0,execa__WEBPACK_IMPORTED_MODULE_9__/* .execa */ .Ho)("docker", ["pull", _config_js__WEBPACK_IMPORTED_MODULE_5__/* .DOCKER_CONFIG */ .e6.prebuiltImage], {
43212
43242
  stdio: "inherit",
43213
43243
  });
43214
43244
  console.log();
43215
43245
  console.log("🏷️ Tagging image for local use...");
43216
- await (0,execa__WEBPACK_IMPORTED_MODULE_6__/* .execa */ .Ho)("docker", ["tag", _config_js__WEBPACK_IMPORTED_MODULE_5__/* .DOCKER_CONFIG */ .e6.prebuiltImage, _config_js__WEBPACK_IMPORTED_MODULE_5__/* .DOCKER_CONFIG */ .e6.imageName], {
43246
+ await (0,execa__WEBPACK_IMPORTED_MODULE_9__/* .execa */ .Ho)("docker", ["tag", _config_js__WEBPACK_IMPORTED_MODULE_5__/* .DOCKER_CONFIG */ .e6.prebuiltImage, _config_js__WEBPACK_IMPORTED_MODULE_5__/* .DOCKER_CONFIG */ .e6.imageName], {
43217
43247
  stdio: "inherit",
43218
43248
  });
43219
43249
  console.log();
@@ -43241,7 +43271,7 @@ async function buildDocker() {
43241
43271
  console.log(`Root: ${rootDir}`);
43242
43272
  console.log(`Dockerfile: ${dockerfilePath}`);
43243
43273
  console.log();
43244
- await (0,execa__WEBPACK_IMPORTED_MODULE_6__/* .execa */ .Ho)("docker", ["build", "-f", dockerfilePath, "-t", _config_js__WEBPACK_IMPORTED_MODULE_5__/* .DOCKER_CONFIG */ .e6.imageName, rootDir], {
43274
+ await (0,execa__WEBPACK_IMPORTED_MODULE_9__/* .execa */ .Ho)("docker", ["build", "-f", dockerfilePath, "-t", _config_js__WEBPACK_IMPORTED_MODULE_5__/* .DOCKER_CONFIG */ .e6.imageName, rootDir], {
43245
43275
  stdio: "inherit",
43246
43276
  });
43247
43277
  console.log();
@@ -43260,14 +43290,15 @@ async function buildDocker() {
43260
43290
  }
43261
43291
  async function runShell() {
43262
43292
  console.log("🚀 Starting interactive shell...");
43263
- console.log(`Mounting current directory to ${_config_js__WEBPACK_IMPORTED_MODULE_5__/* .DOCKER_CONFIG */ .e6.workspaceMount}`);
43293
+ console.log(`Mounting workspace to ${_config_js__WEBPACK_IMPORTED_MODULE_5__/* .DOCKER_CONFIG */ .e6.workspaceMount}`);
43294
+ console.log(`Mounting skills from ${(0,_utils_skills_js__WEBPACK_IMPORTED_MODULE_7__/* .getSkillsDir */ .YJ)()} to ${_config_js__WEBPACK_IMPORTED_MODULE_5__/* .DOCKER_CONFIG */ .e6.skillsMount}`);
43264
43295
  console.log('Press Ctrl+D or type "exit" to leave');
43265
43296
  console.log();
43266
43297
  // Try to get GitHub token from gh CLI if not in env
43267
43298
  let githubToken = process.env.GITHUB_TOKEN || "";
43268
43299
  if (!githubToken) {
43269
43300
  try {
43270
- const { stdout } = await (0,execa__WEBPACK_IMPORTED_MODULE_6__/* .execa */ .Ho)("gh", ["auth", "token"]);
43301
+ const { stdout } = await (0,execa__WEBPACK_IMPORTED_MODULE_9__/* .execa */ .Ho)("gh", ["auth", "token"]);
43271
43302
  githubToken = stdout.trim();
43272
43303
  }
43273
43304
  catch {
@@ -43280,6 +43311,8 @@ async function runShell() {
43280
43311
  "-it",
43281
43312
  "-v",
43282
43313
  `${process.cwd()}:${_config_js__WEBPACK_IMPORTED_MODULE_5__/* .DOCKER_CONFIG */ .e6.workspaceMount}`,
43314
+ "-v",
43315
+ `${(0,_utils_skills_js__WEBPACK_IMPORTED_MODULE_7__/* .getSkillsDir */ .YJ)()}:${_config_js__WEBPACK_IMPORTED_MODULE_5__/* .DOCKER_CONFIG */ .e6.skillsMount}`,
43283
43316
  "-e",
43284
43317
  `GITHUB_TOKEN=${githubToken}`,
43285
43318
  "--entrypoint",
@@ -43288,7 +43321,7 @@ async function runShell() {
43288
43321
  _config_js__WEBPACK_IMPORTED_MODULE_5__/* .DOCKER_CONFIG */ .e6.shellEntrypoint,
43289
43322
  ];
43290
43323
  try {
43291
- await (0,execa__WEBPACK_IMPORTED_MODULE_6__/* .execa */ .Ho)("docker", dockerArgs, {
43324
+ await (0,execa__WEBPACK_IMPORTED_MODULE_9__/* .execa */ .Ho)("docker", dockerArgs, {
43292
43325
  stdio: "inherit",
43293
43326
  });
43294
43327
  }
@@ -43306,6 +43339,291 @@ __webpack_async_result__();
43306
43339
 
43307
43340
  /***/ }),
43308
43341
 
43342
+ /***/ 9922:
43343
+ /***/ ((__unused_webpack_module, __webpack_exports__, __nccwpck_require__) => {
43344
+
43345
+ /* harmony export */ __nccwpck_require__.d(__webpack_exports__, {
43346
+ /* harmony export */ Dv: () => (/* binding */ nixCommand),
43347
+ /* harmony export */ Fh: () => (/* binding */ installNix),
43348
+ /* harmony export */ Qi: () => (/* binding */ copyNixFiles),
43349
+ /* harmony export */ nb: () => (/* binding */ runNixShell)
43350
+ /* harmony export */ });
43351
+ /* unused harmony export checkNixInstalled */
43352
+ /* harmony import */ var execa__WEBPACK_IMPORTED_MODULE_5__ = __nccwpck_require__(6181);
43353
+ /* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_0__ = __nccwpck_require__(9896);
43354
+ /* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__nccwpck_require__.n(fs__WEBPACK_IMPORTED_MODULE_0__);
43355
+ /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1__ = __nccwpck_require__(6928);
43356
+ /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__nccwpck_require__.n(path__WEBPACK_IMPORTED_MODULE_1__);
43357
+ /* harmony import */ var os__WEBPACK_IMPORTED_MODULE_2__ = __nccwpck_require__(857);
43358
+ /* harmony import */ var os__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__nccwpck_require__.n(os__WEBPACK_IMPORTED_MODULE_2__);
43359
+ /* harmony import */ var url__WEBPACK_IMPORTED_MODULE_3__ = __nccwpck_require__(7016);
43360
+ /* harmony import */ var url__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__nccwpck_require__.n(url__WEBPACK_IMPORTED_MODULE_3__);
43361
+ /* harmony import */ var _config_js__WEBPACK_IMPORTED_MODULE_4__ = __nccwpck_require__(6878);
43362
+
43363
+
43364
+
43365
+
43366
+
43367
+
43368
+ const __dirname = path__WEBPACK_IMPORTED_MODULE_1___default().dirname((0,url__WEBPACK_IMPORTED_MODULE_3__.fileURLToPath)(import.meta.url));
43369
+ // Find project root by looking for docker/ folder
43370
+ function findProjectRoot(startDir) {
43371
+ let currentDir = startDir;
43372
+ const rootPath = path__WEBPACK_IMPORTED_MODULE_1___default().parse(currentDir).root;
43373
+ while (currentDir !== rootPath) {
43374
+ const dockerPath = path__WEBPACK_IMPORTED_MODULE_1___default().join(currentDir, "docker");
43375
+ if (fs__WEBPACK_IMPORTED_MODULE_0___default().existsSync(dockerPath) && fs__WEBPACK_IMPORTED_MODULE_0___default().statSync(dockerPath).isDirectory()) {
43376
+ return currentDir;
43377
+ }
43378
+ currentDir = path__WEBPACK_IMPORTED_MODULE_1___default().dirname(currentDir);
43379
+ }
43380
+ throw new Error("Could not find project root (docker/ folder not found)");
43381
+ }
43382
+ const rootDir = findProjectRoot(__dirname);
43383
+ async function checkNixInstalled() {
43384
+ try {
43385
+ const { stdout } = await (0,execa__WEBPACK_IMPORTED_MODULE_5__/* .execa */ .Ho)("nix", ["--version"]);
43386
+ const versionMatch = stdout.match(/nix \(Nix\) (\d+\.\d+)/);
43387
+ if (versionMatch) {
43388
+ const version = versionMatch[1];
43389
+ const [major, minor] = version.split(".").map(Number);
43390
+ const [reqMajor, reqMinor] = _config_js__WEBPACK_IMPORTED_MODULE_4__/* .NIX_CONFIG */ .Z3.requiredVersion.split(".").map(Number);
43391
+ return major > reqMajor || (major === reqMajor && minor >= reqMinor);
43392
+ }
43393
+ return false;
43394
+ }
43395
+ catch {
43396
+ return false;
43397
+ }
43398
+ }
43399
+ async function installNix() {
43400
+ console.log("🔧 Installing Nix package manager...");
43401
+ console.log();
43402
+ // Check if already installed
43403
+ if (await checkNixInstalled()) {
43404
+ console.log("✅ Nix is already installed and meets version requirements");
43405
+ return;
43406
+ }
43407
+ // Detect OS
43408
+ const platform = os__WEBPACK_IMPORTED_MODULE_2___default().platform();
43409
+ if (platform !== "darwin" && platform !== "linux") {
43410
+ throw new Error(`Unsupported platform: ${platform}. Nix only supports macOS and Linux.`);
43411
+ }
43412
+ console.log(`Platform: ${platform}`);
43413
+ console.log(`Installer: ${_config_js__WEBPACK_IMPORTED_MODULE_4__/* .NIX_CONFIG */ .Z3.installerUrl}`);
43414
+ console.log();
43415
+ // Download and run installer
43416
+ console.log("📥 Downloading Nix installer...");
43417
+ try {
43418
+ await (0,execa__WEBPACK_IMPORTED_MODULE_5__/* .execa */ .Ho)("sh", ["-c", `curl -L ${_config_js__WEBPACK_IMPORTED_MODULE_4__/* .NIX_CONFIG */ .Z3.installerUrl} | sh -s -- --daemon`], {
43419
+ stdio: "inherit",
43420
+ });
43421
+ }
43422
+ catch (error) {
43423
+ console.error("❌ Failed to install Nix");
43424
+ throw error;
43425
+ }
43426
+ console.log();
43427
+ console.log("✅ Nix installed successfully!");
43428
+ console.log("⚠️ Please restart your shell or run: source ~/.nix-profile/etc/profile.d/nix.sh");
43429
+ }
43430
+ async function copyNixFiles() {
43431
+ const homeDir = os__WEBPACK_IMPORTED_MODULE_2___default().homedir();
43432
+ const localConfigDir = path__WEBPACK_IMPORTED_MODULE_1___default().join(homeDir, _config_js__WEBPACK_IMPORTED_MODULE_4__/* .NIX_CONFIG */ .Z3.localConfigDir);
43433
+ console.log(`📁 Copying Nix configuration to ${localConfigDir}...`);
43434
+ // Create directory if it doesn't exist
43435
+ if (!fs__WEBPACK_IMPORTED_MODULE_0___default().existsSync(localConfigDir)) {
43436
+ fs__WEBPACK_IMPORTED_MODULE_0___default().mkdirSync(localConfigDir, { recursive: true });
43437
+ }
43438
+ // Copy shell.nix and flake files
43439
+ const sourcePath = path__WEBPACK_IMPORTED_MODULE_1___default().join(rootDir, "docker", "nix");
43440
+ const filesToCopy = ["shell.nix", "flake.nix", "flake.lock"];
43441
+ for (const file of filesToCopy) {
43442
+ const src = path__WEBPACK_IMPORTED_MODULE_1___default().join(sourcePath, file);
43443
+ const dest = path__WEBPACK_IMPORTED_MODULE_1___default().join(localConfigDir, file);
43444
+ if (fs__WEBPACK_IMPORTED_MODULE_0___default().existsSync(src)) {
43445
+ fs__WEBPACK_IMPORTED_MODULE_0___default().copyFileSync(src, dest);
43446
+ console.log(` ✓ Copied ${file}`);
43447
+ }
43448
+ }
43449
+ // Copy nix-config directory
43450
+ const configSrc = path__WEBPACK_IMPORTED_MODULE_1___default().join(sourcePath, "nix-config");
43451
+ const configDest = path__WEBPACK_IMPORTED_MODULE_1___default().join(localConfigDir, "nix-config");
43452
+ if (!fs__WEBPACK_IMPORTED_MODULE_0___default().existsSync(configDest)) {
43453
+ fs__WEBPACK_IMPORTED_MODULE_0___default().mkdirSync(configDest, { recursive: true });
43454
+ }
43455
+ const configFiles = fs__WEBPACK_IMPORTED_MODULE_0___default().readdirSync(configSrc);
43456
+ for (const file of configFiles) {
43457
+ fs__WEBPACK_IMPORTED_MODULE_0___default().copyFileSync(path__WEBPACK_IMPORTED_MODULE_1___default().join(configSrc, file), path__WEBPACK_IMPORTED_MODULE_1___default().join(configDest, file));
43458
+ console.log(` ✓ Copied nix-config/${file}`);
43459
+ }
43460
+ console.log();
43461
+ console.log("✅ Nix files copied successfully!");
43462
+ }
43463
+ async function runNixShell() {
43464
+ // Check if Nix is installed
43465
+ if (!(await checkNixInstalled())) {
43466
+ console.error("❌ Nix is not installed");
43467
+ console.error("Run: sith --nix-install");
43468
+ process.exit(1);
43469
+ }
43470
+ // Copy files if not already present
43471
+ const homeDir = os__WEBPACK_IMPORTED_MODULE_2___default().homedir();
43472
+ const localConfigDir = path__WEBPACK_IMPORTED_MODULE_1___default().join(homeDir, _config_js__WEBPACK_IMPORTED_MODULE_4__/* .NIX_CONFIG */ .Z3.localConfigDir);
43473
+ const shellNixPath = path__WEBPACK_IMPORTED_MODULE_1___default().join(localConfigDir, "shell.nix");
43474
+ if (!fs__WEBPACK_IMPORTED_MODULE_0___default().existsSync(shellNixPath)) {
43475
+ await copyNixFiles();
43476
+ }
43477
+ console.log("🚀 Starting Nix shell...");
43478
+ console.log(`Configuration: ${shellNixPath}`);
43479
+ console.log('Press Ctrl+D or type "exit" to leave');
43480
+ console.log();
43481
+ // Set environment variables
43482
+ const env = {
43483
+ ...process.env,
43484
+ OPENCODE_MODEL: "claude-sonnet-4-5-20241022",
43485
+ };
43486
+ // Try to get GitHub token from gh CLI if not in env
43487
+ if (!env.GITHUB_TOKEN) {
43488
+ try {
43489
+ const { stdout } = await (0,execa__WEBPACK_IMPORTED_MODULE_5__/* .execa */ .Ho)("gh", ["auth", "token"]);
43490
+ env.GITHUB_TOKEN = stdout.trim();
43491
+ }
43492
+ catch {
43493
+ // Ignore if gh CLI not available or not authenticated
43494
+ }
43495
+ }
43496
+ // Run nix-shell
43497
+ try {
43498
+ await (0,execa__WEBPACK_IMPORTED_MODULE_5__/* .execa */ .Ho)("nix-shell", [shellNixPath], {
43499
+ stdio: "inherit",
43500
+ env,
43501
+ cwd: process.cwd(),
43502
+ });
43503
+ }
43504
+ catch (error) {
43505
+ console.error("❌ Failed to start Nix shell");
43506
+ if (error instanceof Error) {
43507
+ console.error(error.message);
43508
+ }
43509
+ process.exit(1);
43510
+ }
43511
+ }
43512
+ async function nixCommand(options) {
43513
+ if (options.install) {
43514
+ await installNix();
43515
+ await copyNixFiles();
43516
+ return;
43517
+ }
43518
+ if (options.shell) {
43519
+ await runNixShell();
43520
+ return;
43521
+ }
43522
+ // Default: run shell
43523
+ await runNixShell();
43524
+ }
43525
+
43526
+
43527
+ /***/ }),
43528
+
43529
+ /***/ 9805:
43530
+ /***/ ((module, __webpack_exports__, __nccwpck_require__) => {
43531
+
43532
+ __nccwpck_require__.a(module, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try {
43533
+ /* harmony export */ __nccwpck_require__.d(__webpack_exports__, {
43534
+ /* harmony export */ a: () => (/* binding */ skillsCommand)
43535
+ /* harmony export */ });
43536
+ /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __nccwpck_require__(2864);
43537
+ /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__nccwpck_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
43538
+ /* harmony import */ var ink__WEBPACK_IMPORTED_MODULE_1__ = __nccwpck_require__(3816);
43539
+ /* harmony import */ var _config_js__WEBPACK_IMPORTED_MODULE_2__ = __nccwpck_require__(6878);
43540
+ /* harmony import */ var _utils_skills_js__WEBPACK_IMPORTED_MODULE_3__ = __nccwpck_require__(6400);
43541
+ var __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([ink__WEBPACK_IMPORTED_MODULE_1__]);
43542
+ ink__WEBPACK_IMPORTED_MODULE_1__ = (__webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__)[0];
43543
+
43544
+
43545
+
43546
+
43547
+ function SkillsMenu() {
43548
+ const { exit } = (0,ink__WEBPACK_IMPORTED_MODULE_1__/* .useApp */ .nm)();
43549
+ const [selectedIndex, setSelectedIndex] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(0);
43550
+ const [rows, setRows] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(_config_js__WEBPACK_IMPORTED_MODULE_2__/* .SKILLS_CATALOG */ .XI.map((s) => ({ installed: (0,_utils_skills_js__WEBPACK_IMPORTED_MODULE_3__/* .isInstalled */ .j$)(s.name), status: "idle", message: "" })));
43551
+ function setRow(index, patch) {
43552
+ setRows((prev) => prev.map((r, i) => (i === index ? { ...r, ...patch } : r)));
43553
+ }
43554
+ (0,ink__WEBPACK_IMPORTED_MODULE_1__/* .useInput */ .Ge)(async (_input, key) => {
43555
+ if (key.upArrow) {
43556
+ setSelectedIndex((p) => (p > 0 ? p - 1 : _config_js__WEBPACK_IMPORTED_MODULE_2__/* .SKILLS_CATALOG */ .XI.length - 1));
43557
+ return;
43558
+ }
43559
+ if (key.downArrow) {
43560
+ setSelectedIndex((p) => (p < _config_js__WEBPACK_IMPORTED_MODULE_2__/* .SKILLS_CATALOG */ .XI.length - 1 ? p + 1 : 0));
43561
+ return;
43562
+ }
43563
+ if (key.return) {
43564
+ const skill = _config_js__WEBPACK_IMPORTED_MODULE_2__/* .SKILLS_CATALOG */ .XI[selectedIndex];
43565
+ const row = rows[selectedIndex];
43566
+ if (row.status === "working")
43567
+ return;
43568
+ if (row.installed) {
43569
+ setRow(selectedIndex, { status: "working", message: "Uninstalling..." });
43570
+ try {
43571
+ (0,_utils_skills_js__WEBPACK_IMPORTED_MODULE_3__/* .uninstallSkill */ .wW)(skill.name);
43572
+ setRow(selectedIndex, { installed: false, status: "done", message: "Uninstalled" });
43573
+ }
43574
+ catch (e) {
43575
+ setRow(selectedIndex, { status: "error", message: e instanceof Error ? e.message : "Failed" });
43576
+ }
43577
+ }
43578
+ else {
43579
+ setRow(selectedIndex, { status: "working", message: "Downloading..." });
43580
+ try {
43581
+ await (0,_utils_skills_js__WEBPACK_IMPORTED_MODULE_3__/* .installSkill */ .rP)(skill);
43582
+ setRow(selectedIndex, { installed: true, status: "done", message: "Installed" });
43583
+ }
43584
+ catch (e) {
43585
+ setRow(selectedIndex, { status: "error", message: e instanceof Error ? e.message : "Failed" });
43586
+ }
43587
+ }
43588
+ return;
43589
+ }
43590
+ if (_input === "q" || key.escape) {
43591
+ exit();
43592
+ }
43593
+ });
43594
+ return (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(ink__WEBPACK_IMPORTED_MODULE_1__/* .Box */ .az, { flexDirection: "column", paddingX: 1 },
43595
+ react__WEBPACK_IMPORTED_MODULE_0___default().createElement(ink__WEBPACK_IMPORTED_MODULE_1__/* .Box */ .az, { marginBottom: 1 },
43596
+ react__WEBPACK_IMPORTED_MODULE_0___default().createElement(ink__WEBPACK_IMPORTED_MODULE_1__/* .Text */ .EY, { bold: true, color: "red" }, "Skills Manager"),
43597
+ react__WEBPACK_IMPORTED_MODULE_0___default().createElement(ink__WEBPACK_IMPORTED_MODULE_1__/* .Text */ .EY, { dimColor: true }, " (~/.sith/skills/)")),
43598
+ _config_js__WEBPACK_IMPORTED_MODULE_2__/* .SKILLS_CATALOG */ .XI.map((skill, i) => {
43599
+ const row = rows[i];
43600
+ const isSelected = i === selectedIndex;
43601
+ const statusIcon = row.status === "working" ? "⏳"
43602
+ : row.status === "error" ? "❌"
43603
+ : row.installed ? "✅" : "☐";
43604
+ return (react__WEBPACK_IMPORTED_MODULE_0___default().createElement(ink__WEBPACK_IMPORTED_MODULE_1__/* .Box */ .az, { key: skill.name, marginY: 0 },
43605
+ react__WEBPACK_IMPORTED_MODULE_0___default().createElement(ink__WEBPACK_IMPORTED_MODULE_1__/* .Text */ .EY, { color: isSelected ? "cyan" : undefined },
43606
+ isSelected ? "❯ " : " ",
43607
+ statusIcon,
43608
+ " ",
43609
+ skill.name.padEnd(12)),
43610
+ react__WEBPACK_IMPORTED_MODULE_0___default().createElement(ink__WEBPACK_IMPORTED_MODULE_1__/* .Text */ .EY, { dimColor: !isSelected }, skill.description),
43611
+ row.message ? react__WEBPACK_IMPORTED_MODULE_0___default().createElement(ink__WEBPACK_IMPORTED_MODULE_1__/* .Text */ .EY, { color: row.status === "error" ? "red" : "green" },
43612
+ " ",
43613
+ row.message) : null));
43614
+ }),
43615
+ react__WEBPACK_IMPORTED_MODULE_0___default().createElement(ink__WEBPACK_IMPORTED_MODULE_1__/* .Box */ .az, { marginTop: 1 },
43616
+ react__WEBPACK_IMPORTED_MODULE_0___default().createElement(ink__WEBPACK_IMPORTED_MODULE_1__/* .Text */ .EY, { dimColor: true }, "\u2191\u2193 navigate Enter install/uninstall q quit"))));
43617
+ }
43618
+ function skillsCommand() {
43619
+ (0,ink__WEBPACK_IMPORTED_MODULE_1__/* .render */ .XX)(react__WEBPACK_IMPORTED_MODULE_0___default().createElement(SkillsMenu, null));
43620
+ }
43621
+
43622
+ __webpack_async_result__();
43623
+ } catch(e) { __webpack_async_result__(e); } });
43624
+
43625
+ /***/ }),
43626
+
43309
43627
  /***/ 3636:
43310
43628
  /***/ ((module, __webpack_exports__, __nccwpck_require__) => {
43311
43629
 
@@ -43461,12 +43779,16 @@ __nccwpck_require__.a(module, async (__webpack_handle_async_dependencies__, __we
43461
43779
  /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__nccwpck_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
43462
43780
  /* harmony import */ var ink__WEBPACK_IMPORTED_MODULE_1__ = __nccwpck_require__(3816);
43463
43781
  /* harmony import */ var ink_text_input__WEBPACK_IMPORTED_MODULE_2__ = __nccwpck_require__(9046);
43464
- /* harmony import */ var execa__WEBPACK_IMPORTED_MODULE_5__ = __nccwpck_require__(6181);
43782
+ /* harmony import */ var execa__WEBPACK_IMPORTED_MODULE_7__ = __nccwpck_require__(6181);
43465
43783
  /* harmony import */ var _ConfigModal_js__WEBPACK_IMPORTED_MODULE_3__ = __nccwpck_require__(3636);
43466
- /* harmony import */ var _utils_slashCommands_js__WEBPACK_IMPORTED_MODULE_6__ = __nccwpck_require__(9987);
43784
+ /* harmony import */ var _utils_slashCommands_js__WEBPACK_IMPORTED_MODULE_8__ = __nccwpck_require__(9987);
43467
43785
  /* harmony import */ var _config_js__WEBPACK_IMPORTED_MODULE_4__ = __nccwpck_require__(6878);
43468
- var __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([ink__WEBPACK_IMPORTED_MODULE_1__, ink_text_input__WEBPACK_IMPORTED_MODULE_2__, _ConfigModal_js__WEBPACK_IMPORTED_MODULE_3__]);
43469
- ([ink__WEBPACK_IMPORTED_MODULE_1__, ink_text_input__WEBPACK_IMPORTED_MODULE_2__, _ConfigModal_js__WEBPACK_IMPORTED_MODULE_3__] = __webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__);
43786
+ /* harmony import */ var _utils_skills_js__WEBPACK_IMPORTED_MODULE_5__ = __nccwpck_require__(6400);
43787
+ /* harmony import */ var _commands_skills_js__WEBPACK_IMPORTED_MODULE_6__ = __nccwpck_require__(9805);
43788
+ var __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([ink__WEBPACK_IMPORTED_MODULE_1__, ink_text_input__WEBPACK_IMPORTED_MODULE_2__, _ConfigModal_js__WEBPACK_IMPORTED_MODULE_3__, _commands_skills_js__WEBPACK_IMPORTED_MODULE_6__]);
43789
+ ([ink__WEBPACK_IMPORTED_MODULE_1__, ink_text_input__WEBPACK_IMPORTED_MODULE_2__, _ConfigModal_js__WEBPACK_IMPORTED_MODULE_3__, _commands_skills_js__WEBPACK_IMPORTED_MODULE_6__] = __webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__);
43790
+
43791
+
43470
43792
 
43471
43793
 
43472
43794
 
@@ -43485,6 +43807,7 @@ function WelcomeScreen() {
43485
43807
  react__WEBPACK_IMPORTED_MODULE_0___default().createElement(ink__WEBPACK_IMPORTED_MODULE_1__/* .Text */ .EY, { dimColor: true }, "or use slash commands:")),
43486
43808
  react__WEBPACK_IMPORTED_MODULE_0___default().createElement(ink__WEBPACK_IMPORTED_MODULE_1__/* .Box */ .az, { flexDirection: "column", marginTop: 1, marginLeft: 2 },
43487
43809
  react__WEBPACK_IMPORTED_MODULE_0___default().createElement(ink__WEBPACK_IMPORTED_MODULE_1__/* .Text */ .EY, { dimColor: true }, " /shell - Start Docker shell"),
43810
+ react__WEBPACK_IMPORTED_MODULE_0___default().createElement(ink__WEBPACK_IMPORTED_MODULE_1__/* .Text */ .EY, { dimColor: true }, " /skills - Install/uninstall skills"),
43488
43811
  react__WEBPACK_IMPORTED_MODULE_0___default().createElement(ink__WEBPACK_IMPORTED_MODULE_1__/* .Text */ .EY, { dimColor: true }, " /config - Configuration"),
43489
43812
  react__WEBPACK_IMPORTED_MODULE_0___default().createElement(ink__WEBPACK_IMPORTED_MODULE_1__/* .Text */ .EY, { dimColor: true }, " /help - Show help"))));
43490
43813
  }
@@ -43530,7 +43853,7 @@ async function getGitHubToken() {
43530
43853
  }
43531
43854
  // Try to get token from gh CLI
43532
43855
  try {
43533
- const { stdout } = await (0,execa__WEBPACK_IMPORTED_MODULE_5__/* .execa */ .Ho)("gh", ["auth", "token"]);
43856
+ const { stdout } = await (0,execa__WEBPACK_IMPORTED_MODULE_7__/* .execa */ .Ho)("gh", ["auth", "token"]);
43534
43857
  return stdout.trim();
43535
43858
  }
43536
43859
  catch {
@@ -43545,6 +43868,8 @@ function buildDockerShellCommand(githubToken) {
43545
43868
  "-it",
43546
43869
  "-v",
43547
43870
  `${process.cwd()}:${_config_js__WEBPACK_IMPORTED_MODULE_4__/* .DOCKER_CONFIG */ .e6.workspaceMount}`,
43871
+ "-v",
43872
+ `${(0,_utils_skills_js__WEBPACK_IMPORTED_MODULE_5__/* .getSkillsDir */ .YJ)()}:${_config_js__WEBPACK_IMPORTED_MODULE_4__/* .DOCKER_CONFIG */ .e6.skillsMount}`,
43548
43873
  "-e",
43549
43874
  `GITHUB_TOKEN=${githubToken}`,
43550
43875
  "--entrypoint",
@@ -43560,6 +43885,8 @@ function buildDockerOpencodeCommand(githubToken, prompt) {
43560
43885
  "-it",
43561
43886
  "-v",
43562
43887
  `${process.cwd()}:${_config_js__WEBPACK_IMPORTED_MODULE_4__/* .DOCKER_CONFIG */ .e6.workspaceMount}`,
43888
+ "-v",
43889
+ `${(0,_utils_skills_js__WEBPACK_IMPORTED_MODULE_5__/* .getSkillsDir */ .YJ)()}:${_config_js__WEBPACK_IMPORTED_MODULE_4__/* .DOCKER_CONFIG */ .e6.skillsMount}`,
43563
43890
  "-e",
43564
43891
  `GITHUB_TOKEN=${githubToken}`,
43565
43892
  "--entrypoint",
@@ -43602,7 +43929,7 @@ function TerminalUI() {
43602
43929
  const githubToken = await getGitHubToken();
43603
43930
  const dockerArgs = buildDockerShellCommand(githubToken);
43604
43931
  try {
43605
- await (0,execa__WEBPACK_IMPORTED_MODULE_5__/* .execa */ .Ho)("docker", dockerArgs, { stdio: "inherit" });
43932
+ await (0,execa__WEBPACK_IMPORTED_MODULE_7__/* .execa */ .Ho)("docker", dockerArgs, { stdio: "inherit" });
43606
43933
  console.log();
43607
43934
  console.log("✅ Exited shell");
43608
43935
  }
@@ -43623,7 +43950,7 @@ function TerminalUI() {
43623
43950
  const githubToken = await getGitHubToken();
43624
43951
  const dockerArgs = buildDockerOpencodeCommand(githubToken, prompt);
43625
43952
  try {
43626
- await (0,execa__WEBPACK_IMPORTED_MODULE_5__/* .execa */ .Ho)("docker", dockerArgs, { stdio: "inherit" });
43953
+ await (0,execa__WEBPACK_IMPORTED_MODULE_7__/* .execa */ .Ho)("docker", dockerArgs, { stdio: "inherit" });
43627
43954
  console.log();
43628
43955
  console.log("✅ Exited OpenCode");
43629
43956
  }
@@ -43642,12 +43969,16 @@ function TerminalUI() {
43642
43969
  case "shell":
43643
43970
  await handleDockerShell();
43644
43971
  break;
43972
+ case "skills":
43973
+ exit();
43974
+ (0,_commands_skills_js__WEBPACK_IMPORTED_MODULE_6__/* .skillsCommand */ .a)();
43975
+ break;
43645
43976
  case "config":
43646
43977
  setShowConfigModal(true);
43647
43978
  break;
43648
43979
  case "help":
43649
43980
  addMessage("Available commands:", "info");
43650
- const availableCommands = (0,_utils_slashCommands_js__WEBPACK_IMPORTED_MODULE_6__/* .getAvailableCommands */ .K)();
43981
+ const availableCommands = (0,_utils_slashCommands_js__WEBPACK_IMPORTED_MODULE_8__/* .getAvailableCommands */ .K)();
43651
43982
  for (const cmd of availableCommands) {
43652
43983
  addMessage(` ${cmd.command} - ${cmd.description}`, "info");
43653
43984
  }
@@ -43660,7 +43991,7 @@ function TerminalUI() {
43660
43991
  return;
43661
43992
  }
43662
43993
  setInput("");
43663
- const command = (0,_utils_slashCommands_js__WEBPACK_IMPORTED_MODULE_6__/* .parseSlashCommand */ .M)(trimmedValue);
43994
+ const command = (0,_utils_slashCommands_js__WEBPACK_IMPORTED_MODULE_8__/* .parseSlashCommand */ .M)(trimmedValue);
43664
43995
  if (command) {
43665
43996
  await handleSlashCommand(command, trimmedValue);
43666
43997
  }
@@ -43718,10 +44049,21 @@ __webpack_async_result__();
43718
44049
  /***/ ((__unused_webpack_module, __webpack_exports__, __nccwpck_require__) => {
43719
44050
 
43720
44051
  /* harmony export */ __nccwpck_require__.d(__webpack_exports__, {
44052
+ /* harmony export */ XI: () => (/* binding */ SKILLS_CATALOG),
44053
+ /* harmony export */ Z3: () => (/* binding */ NIX_CONFIG),
43721
44054
  /* harmony export */ ZC: () => (/* binding */ SPINNER_CONFIG),
43722
44055
  /* harmony export */ e6: () => (/* binding */ DOCKER_CONFIG),
43723
44056
  /* harmony export */ mF: () => (/* binding */ ASCII_LOGO)
43724
44057
  /* harmony export */ });
44058
+ // Predefined skill catalog — skills are installed to ~/.sith/skills/<name>/
44059
+ const SKILLS_CATALOG = [
44060
+ {
44061
+ name: "caveman",
44062
+ description: "Ultra-compressed communication (~75% token reduction)",
44063
+ source: "https://github.com/JuliusBrussee/caveman/archive/refs/heads/main.zip",
44064
+ homepage: "https://github.com/JuliusBrussee/caveman",
44065
+ },
44066
+ ];
43725
44067
  // Docker configuration
43726
44068
  const DOCKER_CONFIG = {
43727
44069
  imageName: "sith:latest",
@@ -43729,8 +44071,17 @@ const DOCKER_CONFIG = {
43729
44071
  folderName: "docker",
43730
44072
  dockerfileName: "Dockerfile",
43731
44073
  workspaceMount: "/workspace",
44074
+ skillsMount: "/opt/sith/external-skills",
43732
44075
  shellEntrypoint: "/opt/sith/nix/shell.nix",
43733
44076
  };
44077
+ // Nix configuration
44078
+ const NIX_CONFIG = {
44079
+ shellPath: "docker/nix/shell.nix",
44080
+ flakePath: "docker/nix/flake.nix",
44081
+ installerUrl: "https://nixos.org/nix/install",
44082
+ requiredVersion: "2.19",
44083
+ localConfigDir: ".sith/nix",
44084
+ };
43734
44085
  // Spinner animation configuration
43735
44086
  const SPINNER_CONFIG = {
43736
44087
  frames: ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"],
@@ -43760,12 +44111,16 @@ __nccwpck_require__.a(module, async (__webpack_handle_async_dependencies__, __we
43760
44111
  /* harmony import */ var url__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__nccwpck_require__.n(url__WEBPACK_IMPORTED_MODULE_2__);
43761
44112
  /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3__ = __nccwpck_require__(6928);
43762
44113
  /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__nccwpck_require__.n(path__WEBPACK_IMPORTED_MODULE_3__);
43763
- /* harmony import */ var update_notifier__WEBPACK_IMPORTED_MODULE_6__ = __nccwpck_require__(6213);
43764
- /* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_7__ = __nccwpck_require__(9611);
44114
+ /* harmony import */ var update_notifier__WEBPACK_IMPORTED_MODULE_8__ = __nccwpck_require__(6213);
44115
+ /* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_9__ = __nccwpck_require__(9611);
43765
44116
  /* harmony import */ var _commands_docker_js__WEBPACK_IMPORTED_MODULE_4__ = __nccwpck_require__(5515);
43766
- /* harmony import */ var _components_TerminalUI_js__WEBPACK_IMPORTED_MODULE_5__ = __nccwpck_require__(3535);
43767
- var __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([_commands_docker_js__WEBPACK_IMPORTED_MODULE_4__, _components_TerminalUI_js__WEBPACK_IMPORTED_MODULE_5__]);
43768
- ([_commands_docker_js__WEBPACK_IMPORTED_MODULE_4__, _components_TerminalUI_js__WEBPACK_IMPORTED_MODULE_5__] = __webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__);
44117
+ /* harmony import */ var _commands_nix_js__WEBPACK_IMPORTED_MODULE_5__ = __nccwpck_require__(9922);
44118
+ /* harmony import */ var _components_TerminalUI_js__WEBPACK_IMPORTED_MODULE_6__ = __nccwpck_require__(3535);
44119
+ /* harmony import */ var _commands_skills_js__WEBPACK_IMPORTED_MODULE_7__ = __nccwpck_require__(9805);
44120
+ var __webpack_async_dependencies__ = __webpack_handle_async_dependencies__([_commands_docker_js__WEBPACK_IMPORTED_MODULE_4__, _components_TerminalUI_js__WEBPACK_IMPORTED_MODULE_6__, _commands_skills_js__WEBPACK_IMPORTED_MODULE_7__]);
44121
+ ([_commands_docker_js__WEBPACK_IMPORTED_MODULE_4__, _components_TerminalUI_js__WEBPACK_IMPORTED_MODULE_6__, _commands_skills_js__WEBPACK_IMPORTED_MODULE_7__] = __webpack_async_dependencies__.then ? (await __webpack_async_dependencies__)() : __webpack_async_dependencies__);
44122
+
44123
+
43769
44124
 
43770
44125
 
43771
44126
 
@@ -43782,12 +44137,12 @@ const PROGRAM_NAME = 'sith';
43782
44137
  const PROGRAM_VERSION = pkg.version;
43783
44138
  const PROGRAM_DESCRIPTION = 'Turn your context to the dark side. Standardize and share your OpenCode setup with a fully dockerized environment, designed for seamless collaboration and CI integration.';
43784
44139
  // Check for updates (automatic background check)
43785
- const notifier = (0,update_notifier__WEBPACK_IMPORTED_MODULE_6__/* ["default"] */ .A)({ pkg });
44140
+ const notifier = (0,update_notifier__WEBPACK_IMPORTED_MODULE_8__/* ["default"] */ .A)({ pkg });
43786
44141
  notifier.notify();
43787
44142
  async function checkForUpdates() {
43788
- console.log(chalk__WEBPACK_IMPORTED_MODULE_7__/* ["default"] */ .Ay.cyan('Checking for updates...'));
44143
+ console.log(chalk__WEBPACK_IMPORTED_MODULE_9__/* ["default"] */ .Ay.cyan('Checking for updates...'));
43789
44144
  // Force update check by setting updateCheckInterval to 0
43790
- const notifier = (0,update_notifier__WEBPACK_IMPORTED_MODULE_6__/* ["default"] */ .A)({
44145
+ const notifier = (0,update_notifier__WEBPACK_IMPORTED_MODULE_8__/* ["default"] */ .A)({
43791
44146
  pkg,
43792
44147
  updateCheckInterval: 0
43793
44148
  });
@@ -43796,12 +44151,12 @@ async function checkForUpdates() {
43796
44151
  const update = notifier.update;
43797
44152
  if (update && update.latest !== pkg.version) {
43798
44153
  console.log();
43799
- console.log(chalk__WEBPACK_IMPORTED_MODULE_7__/* ["default"] */ .Ay.green(`Update available: ${chalk__WEBPACK_IMPORTED_MODULE_7__/* ["default"] */ .Ay.dim(pkg.version)} → ${chalk__WEBPACK_IMPORTED_MODULE_7__/* ["default"] */ .Ay.bold(update.latest)}`));
43800
- console.log(chalk__WEBPACK_IMPORTED_MODULE_7__/* ["default"] */ .Ay.cyan(`Run ${chalk__WEBPACK_IMPORTED_MODULE_7__/* ["default"] */ .Ay.bold(`npm install -g ${pkg.name}`)} to update`));
44154
+ console.log(chalk__WEBPACK_IMPORTED_MODULE_9__/* ["default"] */ .Ay.green(`Update available: ${chalk__WEBPACK_IMPORTED_MODULE_9__/* ["default"] */ .Ay.dim(pkg.version)} → ${chalk__WEBPACK_IMPORTED_MODULE_9__/* ["default"] */ .Ay.bold(update.latest)}`));
44155
+ console.log(chalk__WEBPACK_IMPORTED_MODULE_9__/* ["default"] */ .Ay.cyan(`Run ${chalk__WEBPACK_IMPORTED_MODULE_9__/* ["default"] */ .Ay.bold(`npm install -g ${pkg.name}`)} to update`));
43801
44156
  console.log();
43802
44157
  }
43803
44158
  else {
43804
- console.log(chalk__WEBPACK_IMPORTED_MODULE_7__/* ["default"] */ .Ay.green(`✓ You're on the latest version (${pkg.version})`));
44159
+ console.log(chalk__WEBPACK_IMPORTED_MODULE_9__/* ["default"] */ .Ay.green(`✓ You're on the latest version (${pkg.version})`));
43805
44160
  }
43806
44161
  }
43807
44162
  function createProgram() {
@@ -43813,6 +44168,8 @@ function createProgram() {
43813
44168
  .option('--pull', 'Pull prebuilt Docker image (recommended)')
43814
44169
  .option('--build', 'Build the Docker image from scratch')
43815
44170
  .option('--it', 'Launch interactive shell in Docker container')
44171
+ .option('--nix', 'Use native Nix shell (no Docker)')
44172
+ .option('--nix-install', 'Install Nix package manager locally')
43816
44173
  .option('--update', 'Check for updates')
43817
44174
  .option('--legacy', 'Use legacy menu interface');
43818
44175
  // Default action - show terminal UI or legacy menu
@@ -43821,6 +44178,12 @@ function createProgram() {
43821
44178
  if (options.update) {
43822
44179
  await checkForUpdates();
43823
44180
  }
44181
+ else if (options.nix) {
44182
+ await (0,_commands_nix_js__WEBPACK_IMPORTED_MODULE_5__/* .runNixShell */ .nb)();
44183
+ }
44184
+ else if (options.nixInstall) {
44185
+ await (0,_commands_nix_js__WEBPACK_IMPORTED_MODULE_5__/* .nixCommand */ .Dv)({ install: true });
44186
+ }
43824
44187
  else if (options.it) {
43825
44188
  await (0,_commands_docker_js__WEBPACK_IMPORTED_MODULE_4__/* .runShellDirect */ .l)();
43826
44189
  }
@@ -43830,7 +44193,7 @@ function createProgram() {
43830
44193
  }
43831
44194
  else {
43832
44195
  // Default: show new terminal UI
43833
- (0,_components_TerminalUI_js__WEBPACK_IMPORTED_MODULE_5__/* .renderTerminalUI */ .t)();
44196
+ (0,_components_TerminalUI_js__WEBPACK_IMPORTED_MODULE_6__/* .renderTerminalUI */ .t)();
43834
44197
  }
43835
44198
  });
43836
44199
  // Docker command - explicit Docker management
@@ -43849,6 +44212,22 @@ function createProgram() {
43849
44212
  .action(async () => {
43850
44213
  await (0,_commands_docker_js__WEBPACK_IMPORTED_MODULE_4__/* .runShellDirect */ .l)();
43851
44214
  });
44215
+ // Skills command - install/uninstall skills from catalog
44216
+ program
44217
+ .command('skills')
44218
+ .description('Manage skills (~/.sith/skills/)')
44219
+ .action(() => {
44220
+ (0,_commands_skills_js__WEBPACK_IMPORTED_MODULE_7__/* .skillsCommand */ .a)();
44221
+ });
44222
+ // Nix command - native Nix environment
44223
+ program
44224
+ .command('nix')
44225
+ .description('Manage native Nix environment')
44226
+ .option('--install', 'Install Nix package manager')
44227
+ .option('--shell', 'Run Nix shell')
44228
+ .action(async (options) => {
44229
+ await (0,_commands_nix_js__WEBPACK_IMPORTED_MODULE_5__/* .nixCommand */ .Dv)(options);
44230
+ });
43852
44231
  return program;
43853
44232
  }
43854
44233
  // Main execution
@@ -43858,6 +44237,71 @@ program.parse();
43858
44237
  __webpack_async_result__();
43859
44238
  } catch(e) { __webpack_async_result__(e); } });
43860
44239
 
44240
+ /***/ }),
44241
+
44242
+ /***/ 6400:
44243
+ /***/ ((__unused_webpack_module, __webpack_exports__, __nccwpck_require__) => {
44244
+
44245
+ /* harmony export */ __nccwpck_require__.d(__webpack_exports__, {
44246
+ /* harmony export */ YJ: () => (/* binding */ getSkillsDir),
44247
+ /* harmony export */ j$: () => (/* binding */ isInstalled),
44248
+ /* harmony export */ rP: () => (/* binding */ installSkill),
44249
+ /* harmony export */ wW: () => (/* binding */ uninstallSkill)
44250
+ /* harmony export */ });
44251
+ /* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_0__ = __nccwpck_require__(9896);
44252
+ /* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__nccwpck_require__.n(fs__WEBPACK_IMPORTED_MODULE_0__);
44253
+ /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1__ = __nccwpck_require__(6928);
44254
+ /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__nccwpck_require__.n(path__WEBPACK_IMPORTED_MODULE_1__);
44255
+ /* harmony import */ var os__WEBPACK_IMPORTED_MODULE_2__ = __nccwpck_require__(857);
44256
+ /* harmony import */ var os__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__nccwpck_require__.n(os__WEBPACK_IMPORTED_MODULE_2__);
44257
+ /* harmony import */ var execa__WEBPACK_IMPORTED_MODULE_3__ = __nccwpck_require__(6181);
44258
+
44259
+
44260
+
44261
+
44262
+ function getSkillsDir() {
44263
+ const dir = path__WEBPACK_IMPORTED_MODULE_1___default().join(os__WEBPACK_IMPORTED_MODULE_2___default().homedir(), ".sith", "skills");
44264
+ fs__WEBPACK_IMPORTED_MODULE_0___default().mkdirSync(dir, { recursive: true });
44265
+ return dir;
44266
+ }
44267
+ function isInstalled(name) {
44268
+ const skillJson = path__WEBPACK_IMPORTED_MODULE_1___default().join(getSkillsDir(), name, "skill.json");
44269
+ return fs__WEBPACK_IMPORTED_MODULE_0___default().existsSync(skillJson);
44270
+ }
44271
+ async function installSkill(skill) {
44272
+ const targetDir = path__WEBPACK_IMPORTED_MODULE_1___default().join(getSkillsDir(), skill.name);
44273
+ const tmpZip = path__WEBPACK_IMPORTED_MODULE_1___default().join(os__WEBPACK_IMPORTED_MODULE_2___default().tmpdir(), `sith-skill-${skill.name}.zip`);
44274
+ const tmpExtract = path__WEBPACK_IMPORTED_MODULE_1___default().join(os__WEBPACK_IMPORTED_MODULE_2___default().tmpdir(), `sith-skill-${skill.name}-extract`);
44275
+ try {
44276
+ await (0,execa__WEBPACK_IMPORTED_MODULE_3__/* .execa */ .Ho)("curl", ["-fsSL", skill.source, "-o", tmpZip]);
44277
+ fs__WEBPACK_IMPORTED_MODULE_0___default().mkdirSync(tmpExtract, { recursive: true });
44278
+ await (0,execa__WEBPACK_IMPORTED_MODULE_3__/* .execa */ .Ho)("unzip", ["-q", "-o", tmpZip, "-d", tmpExtract]);
44279
+ const entries = fs__WEBPACK_IMPORTED_MODULE_0___default().readdirSync(tmpExtract);
44280
+ if (entries.length === 0)
44281
+ throw new Error("Empty archive");
44282
+ const extracted = path__WEBPACK_IMPORTED_MODULE_1___default().join(tmpExtract, entries[0]);
44283
+ if (fs__WEBPACK_IMPORTED_MODULE_0___default().existsSync(targetDir))
44284
+ fs__WEBPACK_IMPORTED_MODULE_0___default().rmSync(targetDir, { recursive: true, force: true });
44285
+ fs__WEBPACK_IMPORTED_MODULE_0___default().cpSync(extracted, targetDir, { recursive: true });
44286
+ // Ensure skill.json exists with at minimum a name field
44287
+ const skillJson = path__WEBPACK_IMPORTED_MODULE_1___default().join(targetDir, "skill.json");
44288
+ if (!fs__WEBPACK_IMPORTED_MODULE_0___default().existsSync(skillJson)) {
44289
+ fs__WEBPACK_IMPORTED_MODULE_0___default().writeFileSync(skillJson, JSON.stringify({ name: skill.name, version: "local" }, null, 2));
44290
+ }
44291
+ }
44292
+ finally {
44293
+ fs__WEBPACK_IMPORTED_MODULE_0___default().rmSync(tmpZip, { force: true });
44294
+ fs__WEBPACK_IMPORTED_MODULE_0___default().rmSync(tmpExtract, { recursive: true, force: true });
44295
+ }
44296
+ }
44297
+ function uninstallSkill(name) {
44298
+ const targetDir = path__WEBPACK_IMPORTED_MODULE_1___default().join(getSkillsDir(), name);
44299
+ if (fs__WEBPACK_IMPORTED_MODULE_0___default().existsSync(targetDir)) {
44300
+ fs__WEBPACK_IMPORTED_MODULE_0___default().rmSync(targetDir, { recursive: true, force: true });
44301
+ }
44302
+ }
44303
+
44304
+
43861
44305
  /***/ }),
43862
44306
 
43863
44307
  /***/ 9987:
@@ -43880,6 +44324,8 @@ function parseSlashCommand(input) {
43880
44324
  return { type: "config", raw: trimmed };
43881
44325
  case "help":
43882
44326
  return { type: "help", raw: trimmed };
44327
+ case "skills":
44328
+ return { type: "skills", raw: trimmed };
43883
44329
  default:
43884
44330
  return null;
43885
44331
  }
@@ -43887,6 +44333,7 @@ function parseSlashCommand(input) {
43887
44333
  function getAvailableCommands() {
43888
44334
  return [
43889
44335
  { command: "/shell", description: "Start Docker shell (no OpenCode)" },
44336
+ { command: "/skills", description: "Install/uninstall skills" },
43890
44337
  { command: "/config", description: "Open configuration menu" },
43891
44338
  { command: "/help", description: "Show available commands" },
43892
44339
  ];
package/dist/package.json CHANGED
@@ -1 +1 @@
1
- {"name":"@m14i/sith","version":"1.14.1","description":"Turn your context to the dark side. Standardize and share your OpenCode setup with a fully dockerized environment, designed for seamless collaboration and CI integration.","type":"module","repository":{"type":"git","url":"https://github.com/MerzoukeMansouri/sith.git"},"bin":{"sith":"./dist/index.js"},"scripts":{"build":"ncc build src/index.ts -o dist && rm -rf dist/assets && cp -r assets dist/","dev":"tsx src/index.ts","dev:build":"pnpm build && node dist/index.js","dev:shell":"pnpm build && node dist/index.js shell","typecheck":"tsc --noEmit","clean":"rm -rf dist","prepublishOnly":"pnpm build"},"files":["dist","assets","docker"],"keywords":["opencode","docker","ci","automation","cli","nix"],"author":"","license":"MIT","dependencies":{"@inquirer/prompts":"^5.0.0","chalk":"^5.3.0","commander":"^12.1.0","execa":"^9.0.0","ink":"^7.0.3","ink-text-input":"^6.0.0","react":"^19.2.6","update-notifier":"^7.3.1"},"devDependencies":{"@semantic-release/changelog":"^6.0.3","@semantic-release/git":"^10.0.1","@semantic-release/github":"^11.0.1","@semantic-release/npm":"^12.0.1","@types/node":"^20.12.7","@types/react":"^19.2.14","@types/update-notifier":"^6.0.8","@vercel/ncc":"^0.38.1","semantic-release":"^24.2.0","tsx":"^4.7.2","typescript":"^5.4.5"},"engines":{"node":">=18"}}
1
+ {"name":"@m14i/sith","version":"1.15.0","description":"Turn your context to the dark side. Standardize and share your OpenCode setup with a fully dockerized environment, designed for seamless collaboration and CI integration.","type":"module","repository":{"type":"git","url":"https://github.com/MerzoukeMansouri/sith.git"},"bin":{"sith":"./dist/index.js"},"scripts":{"build":"ncc build src/index.ts -o dist && rm -rf dist/assets && cp -r assets dist/","dev":"tsx src/index.ts","dev:build":"pnpm build && node dist/index.js","dev:shell":"pnpm build && node dist/index.js shell","typecheck":"tsc --noEmit","clean":"rm -rf dist","prepublishOnly":"pnpm build"},"files":["dist","assets","docker"],"keywords":["opencode","docker","ci","automation","cli","nix"],"author":"","license":"MIT","dependencies":{"@inquirer/prompts":"^5.0.0","chalk":"^5.3.0","commander":"^12.1.0","execa":"^9.0.0","ink":"^7.0.3","ink-text-input":"^6.0.0","react":"^19.2.6","update-notifier":"^7.3.1"},"devDependencies":{"@semantic-release/changelog":"^6.0.3","@semantic-release/git":"^10.0.1","@semantic-release/github":"^11.0.1","@semantic-release/npm":"^12.0.1","@types/node":"^20.12.7","@types/react":"^19.2.14","@types/update-notifier":"^6.0.8","@vercel/ncc":"^0.38.1","semantic-release":"^24.2.0","tsx":"^4.7.2","typescript":"^5.4.5"},"engines":{"node":">=18"}}
package/dist/types.d.ts CHANGED
@@ -10,3 +10,13 @@ export interface DockerCommandOptions {
10
10
  build?: boolean;
11
11
  pull?: boolean;
12
12
  }
13
+ export interface NixCommandOptions {
14
+ install?: boolean;
15
+ shell?: boolean;
16
+ }
17
+ export interface SkillEntry {
18
+ name: string;
19
+ description: string;
20
+ source: string;
21
+ homepage: string;
22
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"","sourceRoot":"","sources":["file:///home/runner/work/sith/sith/src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB"}
1
+ {"version":3,"file":"","sourceRoot":"","sources":["file:///home/runner/work/sith/sith/src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB"}
@@ -0,0 +1,6 @@
1
+ import type { SkillEntry } from "../types.js";
2
+ export declare function getSkillsDir(): string;
3
+ export declare function isInstalled(name: string): boolean;
4
+ export declare function installSkill(skill: SkillEntry): Promise<void>;
5
+ export declare function uninstallSkill(name: string): void;
6
+ //# sourceMappingURL=skills.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["file:///home/runner/work/sith/sith/src/utils/skills.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,wBAAgB,YAAY,IAAI,MAAM,CAIrC;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAGjD;AAED,wBAAsB,YAAY,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CA2BnE;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAKjD"}
@@ -1,4 +1,4 @@
1
- export type SlashCommandType = "shell" | "config" | "help";
1
+ export type SlashCommandType = "shell" | "config" | "help" | "skills";
2
2
  export interface SlashCommand {
3
3
  type: SlashCommandType;
4
4
  raw: string;
@@ -1 +1 @@
1
- {"version":3,"file":"slashCommands.d.ts","sourceRoot":"","sources":["file:///home/runner/work/sith/sith/src/utils/slashCommands.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;AAE3D,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,gBAAgB,CAAC;IACvB,GAAG,EAAE,MAAM,CAAC;CACb;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAmBpE;AAED,wBAAgB,oBAAoB,IAAI,KAAK,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC,CAMtF"}
1
+ {"version":3,"file":"slashCommands.d.ts","sourceRoot":"","sources":["file:///home/runner/work/sith/sith/src/utils/slashCommands.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,GAAG,QAAQ,CAAC;AAEtE,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,gBAAgB,CAAC;IACvB,GAAG,EAAE,MAAM,CAAC;CACb;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAqBpE;AAED,wBAAgB,oBAAoB,IAAI,KAAK,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC,CAOtF"}
package/docker/Dockerfile CHANGED
@@ -15,10 +15,6 @@ RUN echo "sandbox = false" >> /etc/nix/nix.conf && \
15
15
  echo "filter-syscalls = false" >> /etc/nix/nix.conf && \
16
16
  echo "experimental-features = nix-command flakes" >> /etc/nix/nix.conf
17
17
 
18
- # Copier les fichiers de configuration des skills
19
- COPY docker/skills/rtk-config.toml /opt/sith/skills/rtk-config.toml
20
- COPY docker/skills/opencode-skills-config.json /opt/sith/skills/opencode-skills-config.json
21
-
22
18
  # Copier les assets (logo, etc.)
23
19
  COPY assets/ /opt/sith/assets/
24
20
 
@@ -87,16 +83,11 @@ ENV PATH="/root/.opencode/bin:/root/.local/bin:/root/.npm-global/bin:${PATH}"
87
83
  ENV NPM_CONFIG_PREFIX=/root/.npm-global
88
84
  ENV HOME=/root
89
85
 
90
- # === Token Optimization Skills Configuration ===
91
- # RTK (Rust Token Killer) - Désactivé par défaut (binaire non disponible publiquement)
92
- # Activez avec: docker run -e RTK_ENABLED=true ... si vous avez le binaire
93
- ENV RTK_ENABLED=false
94
-
95
- # Caveman - Compression de langage en mode ultra (75%+ de réduction)
96
- ENV CAVEMAN_MODE=ultra
97
- ENV CAVEMAN_AUTO=true
98
-
99
- # Réduction totale estimée: 85-95% de tokens par session CI/CD
86
+ # === Skills Configuration ===
87
+ # Skills are loaded at runtime from the host via volume mount:
88
+ # docker run -v ~/.sith/skills:/opt/sith/external-skills ...
89
+ # Each skill must have a skill.json in its directory.
90
+ ENV SITH_EXTERNAL_SKILLS=/opt/sith/external-skills
100
91
 
101
92
  # Note: Keep running as root due to Nix permission requirements
102
93
  # Nix-shell needs to modify /nix/var/nix/profiles/per-user at runtime
@@ -4,3 +4,4 @@
4
4
  mkdir -p /root/.local/bin
5
5
  mkdir -p /root/.local/share/opencode
6
6
  mkdir -p /workspace/opencode-output
7
+ mkdir -p /opt/sith/external-skills
@@ -1,77 +1,34 @@
1
1
  #!/bin/bash
2
- # Token optimization skills installation (RTK + Caveman)
2
+ # Skills installation from volume mount (~/.sith/skills /opt/sith/external-skills)
3
3
 
4
- mkdir -p /root/.agents/skills
5
-
6
- # Track installed skills
4
+ EXTERNAL_SKILLS_DIR="${SITH_EXTERNAL_SKILLS:-/opt/sith/external-skills}"
7
5
  declare -a INSTALLED_SKILLS=()
8
6
 
9
- # 1. RTK (Rust Token Killer)
10
- if [ "${RTK_ENABLED:-false}" = "true" ]; then
11
- mkdir -p /root/.agents/skills/rtk/bin
12
- mkdir -p /root/.agents/skills/rtk/config
13
-
14
- if [ -f /opt/sith/skills/rtk-config.toml ]; then
15
- cp /opt/sith/skills/rtk-config.toml /root/.agents/skills/rtk/config/config.toml
16
- mkdir -p /root/.config/rtk
17
- ln -sf /root/.agents/skills/rtk/config/config.toml /root/.config/rtk/config.toml
18
- fi
19
-
20
- if command -v rtk &> /dev/null; then
21
- RTK_VERSION=$(rtk --version 2>&1 | head -n1 | awk '{print $2}' || echo "unknown")
22
- INSTALLED_SKILLS+=("RTK|$RTK_VERSION|https://github.com/rust-token-killer/rtk")
7
+ mkdir -p /root/.agents/skills
23
8
 
24
- if [ -f /root/.bashrc ] && ! grep -q "rtk hook" /root/.bashrc; then
25
- echo 'eval "$(rtk hook bash)"' >> /root/.bashrc
9
+ if [ -d "$EXTERNAL_SKILLS_DIR" ]; then
10
+ for skill_dir in "$EXTERNAL_SKILLS_DIR"/*/; do
11
+ [ -d "$skill_dir" ] || continue
12
+ [ -f "$skill_dir/skill.json" ] || continue
13
+ skill_name=$(basename "$skill_dir")
14
+ cp -r "$skill_dir" "/root/.agents/skills/$skill_name"
15
+ if [ -f "/root/.agents/skills/$skill_name/skill.sh" ]; then
16
+ source "/root/.agents/skills/$skill_name/skill.sh" 2>/dev/null || true
26
17
  fi
27
- eval "$(rtk hook bash)" 2>/dev/null || true
28
- fi
29
- fi
30
-
31
- # 2. Caveman (mode ultra)
32
- if [ "${CAVEMAN_AUTO:-true}" = "true" ]; then
33
- mkdir -p /root/.agents/skills
34
-
35
- if [ ! -d /opt/sith/skills/caveman ]; then
36
- mkdir -p /opt/sith/skills
37
- cd /opt/sith/skills
38
- curl -fsSL https://github.com/JuliusBrussee/caveman/archive/refs/heads/main.zip -o caveman.zip 2>/dev/null
39
- unzip -q caveman.zip 2>/dev/null
40
- mv caveman-main caveman 2>/dev/null
41
- rm caveman.zip 2>/dev/null
42
- fi
43
-
44
- if [ -d /opt/sith/skills/caveman ]; then
45
- cp -r /opt/sith/skills/caveman /root/.agents/skills/caveman
46
-
47
- cat > /root/.agents/skills/caveman/.config << 'EOF'
48
- mode=ultra
49
- auto_activate=true
50
- EOF
51
-
52
- CAVEMAN_VERSION=$(grep -oP '(?<=version: ).*' /root/.agents/skills/caveman/skill.json 2>/dev/null || echo "main")
53
- INSTALLED_SKILLS+=("Caveman|$CAVEMAN_VERSION|https://github.com/JuliusBrussee/caveman")
54
- fi
55
- fi
56
-
57
- # 3. Configuration OpenCode skills
58
- if [ -f /opt/sith/skills/opencode-skills-config.json ]; then
59
- mkdir -p /root/.local/share/opencode/skills
60
- cp /opt/sith/skills/opencode-skills-config.json /root/.local/share/opencode/skills/config.json
18
+ version=$(grep -o '"version":"[^"]*"' "$skill_dir/skill.json" | cut -d'"' -f4 || echo "local")
19
+ INSTALLED_SKILLS+=("$skill_name|$version|~/.sith/skills")
20
+ done
61
21
  fi
62
22
 
63
- # Display table if any skills installed
64
23
  if [ ${#INSTALLED_SKILLS[@]} -gt 0 ]; then
65
24
  echo ""
66
25
  echo "┌─────────────────┬──────────┬─────────────────────────────────────────┐"
67
- echo "│ Skill │ Version │ GitHub │"
26
+ echo "│ Skill │ Version │ Source │"
68
27
  echo "├─────────────────┼──────────┼─────────────────────────────────────────┤"
69
-
70
28
  for skill_info in "${INSTALLED_SKILLS[@]}"; do
71
- IFS='|' read -r name version github <<< "$skill_info"
72
- printf "│ %-15s │ %-8s │ %-39s │\n" "$name" "$version" "$github"
29
+ IFS='|' read -r name version source <<< "$skill_info"
30
+ printf "│ %-15s │ %-8s │ %-39s │\n" "$name" "$version" "$source"
73
31
  done
74
-
75
32
  echo "└─────────────────┴──────────┴─────────────────────────────────────────┘"
76
33
  echo ""
77
34
  fi
@@ -22,7 +22,7 @@ source "${SCRIPT_DIR}/04-git-config.sh"
22
22
  # 5. OpenCode CLI installation
23
23
  source "${SCRIPT_DIR}/05-opencode-cli.sh"
24
24
 
25
- # 6. Skills installation (RTK + Caveman)
25
+ # 6. Skills installation (from volume mount)
26
26
  source "${SCRIPT_DIR}/06-skills-setup.sh"
27
27
 
28
28
  # 7. Ready message
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@m14i/sith",
3
- "version": "1.14.1",
3
+ "version": "1.15.0",
4
4
  "description": "Turn your context to the dark side. Standardize and share your OpenCode setup with a fully dockerized environment, designed for seamless collaboration and CI integration.",
5
5
  "type": "module",
6
6
  "repository": {
@@ -1,62 +0,0 @@
1
- {
2
- "version": "2.2.0",
3
- "description": "OpenCode Docker token optimization skills configuration",
4
- "skills": [
5
- {
6
- "name": "caveman",
7
- "enabled": true,
8
- "mode": "ultra",
9
- "auto_trigger": true,
10
- "source": "https://github.com/JuliusBrussee/caveman",
11
- "description": "Ultra-compressed communication mode - reduces response tokens by ~75%",
12
- "features": [
13
- "Caveman-style language compression",
14
- "Maintains technical accuracy",
15
- "Auto-activated for all responses",
16
- "Mode: ultra (maximum compression)"
17
- ],
18
- "estimated_reduction": "75%"
19
- },
20
- {
21
- "name": "rtk",
22
- "enabled": true,
23
- "auto_hook": true,
24
- "source": "https://github.com/rtk-ai/rtk",
25
- "description": "CLI proxy for command output optimization - reduces command output by 60-90%",
26
- "features": [
27
- "Automatic command interception via bash hook",
28
- "Filters: git, cargo, npm, docker, pytest, jest",
29
- "Saves full output on failures",
30
- "Configurable exclusions"
31
- ],
32
- "estimated_reduction": "60-90%",
33
- "supported_commands": [
34
- "git status",
35
- "git log",
36
- "git diff",
37
- "cargo build",
38
- "cargo test",
39
- "npm test",
40
- "npm run",
41
- "docker ps",
42
- "docker logs",
43
- "pytest",
44
- "jest"
45
- ]
46
- }
47
- ],
48
- "combined_effect": {
49
- "total_reduction": "85-95%",
50
- "estimated_savings_per_session": "$6-8 (GPT-4 pricing)",
51
- "best_for": "CI/CD environments with high command frequency"
52
- },
53
- "configuration": {
54
- "rtk_config_path": "/root/.config/rtk/config.toml",
55
- "caveman_path": "/root/.agents/skills/caveman",
56
- "environment_variables": {
57
- "CAVEMAN_MODE": "ultra",
58
- "CAVEMAN_AUTO": "true",
59
- "RTK_ENABLED": "true"
60
- }
61
- }
62
- }
@@ -1,48 +0,0 @@
1
- # RTK (Rust Token Killer) Configuration
2
- # Optimizes CLI output for LLM consumption - reduces tokens by 60-90%
3
- # Used in OpenCode Docker for CI/CD token optimization
4
-
5
- [hooks]
6
- # Commands to exclude from RTK interception
7
- # These commands shouldn't be filtered as they return critical raw data
8
- exclude_commands = ["curl", "wget", "docker logs", "cat"]
9
-
10
- [tee]
11
- # Save full command output to disk when commands fail
12
- # Useful for debugging while still getting compact output by default
13
- enabled = true
14
- mode = "failures" # Options: "failures", "always", "never"
15
-
16
- [filters]
17
- # Enable built-in filters for common dev tools
18
- # Each filter reduces verbose output to essential information only
19
-
20
- [filters.git]
21
- enabled = true
22
- level = "compact" # Options: "compact", "minimal", "full"
23
-
24
- [filters.cargo]
25
- enabled = true
26
- level = "compact"
27
-
28
- [filters.npm]
29
- enabled = true
30
- level = "compact"
31
-
32
- [filters.docker]
33
- enabled = true
34
- level = "compact"
35
-
36
- [filters.pytest]
37
- enabled = true
38
- level = "compact"
39
-
40
- [filters.jest]
41
- enabled = true
42
- level = "compact"
43
-
44
- # General output limits
45
- [output]
46
- max_lines = 500 # Maximum lines per command output
47
- truncate_long_lines = true
48
- max_line_length = 200 # Truncate lines longer than this