@learnrudi/cli 1.9.2 → 1.9.4

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.
Files changed (2) hide show
  1. package/dist/index.cjs +485 -2
  2. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -3834,6 +3834,485 @@ After configuring secrets, run: rudi index`);
3834
3834
  }
3835
3835
  }
3836
3836
 
3837
+ // src/commands/status.js
3838
+ var import_core12 = require("@learnrudi/core");
3839
+ var import_child_process7 = require("child_process");
3840
+ var import_fs10 = __toESM(require("fs"), 1);
3841
+ var import_path7 = __toESM(require("path"), 1);
3842
+ var import_os4 = __toESM(require("os"), 1);
3843
+ var AGENTS = [
3844
+ {
3845
+ id: "claude",
3846
+ name: "Claude Code",
3847
+ npmPackage: "@anthropic-ai/claude-code",
3848
+ credentialType: "keychain",
3849
+ keychainService: "Claude Code-credentials"
3850
+ },
3851
+ {
3852
+ id: "codex",
3853
+ name: "OpenAI Codex",
3854
+ npmPackage: "@openai/codex",
3855
+ credentialType: "file",
3856
+ credentialPath: "~/.codex/auth.json"
3857
+ },
3858
+ {
3859
+ id: "gemini",
3860
+ name: "Gemini CLI",
3861
+ npmPackage: "@google/gemini-cli",
3862
+ credentialType: "file",
3863
+ credentialPath: "~/.gemini/google_accounts.json"
3864
+ },
3865
+ {
3866
+ id: "copilot",
3867
+ name: "GitHub Copilot",
3868
+ npmPackage: "@githubnext/github-copilot-cli",
3869
+ credentialType: "file",
3870
+ credentialPath: "~/.config/github-copilot/hosts.json"
3871
+ }
3872
+ ];
3873
+ var RUNTIMES = [
3874
+ { id: "node", name: "Node.js", command: "node", versionFlag: "--version" },
3875
+ { id: "python", name: "Python", command: "python3", versionFlag: "--version" },
3876
+ { id: "deno", name: "Deno", command: "deno", versionFlag: "--version" },
3877
+ { id: "bun", name: "Bun", command: "bun", versionFlag: "--version" }
3878
+ ];
3879
+ var BINARIES = [
3880
+ { id: "ffmpeg", name: "FFmpeg", command: "ffmpeg", versionFlag: "-version" },
3881
+ { id: "ripgrep", name: "ripgrep", command: "rg", versionFlag: "--version" },
3882
+ { id: "git", name: "Git", command: "git", versionFlag: "--version" },
3883
+ { id: "pandoc", name: "Pandoc", command: "pandoc", versionFlag: "--version" },
3884
+ { id: "jq", name: "jq", command: "jq", versionFlag: "--version" }
3885
+ ];
3886
+ function fileExists(filePath) {
3887
+ const resolved = filePath.replace("~", import_os4.default.homedir());
3888
+ return import_fs10.default.existsSync(resolved);
3889
+ }
3890
+ function checkKeychain(service) {
3891
+ if (process.platform !== "darwin") return false;
3892
+ try {
3893
+ (0, import_child_process7.execSync)(`security find-generic-password -s "${service}"`, {
3894
+ stdio: ["pipe", "pipe", "pipe"]
3895
+ });
3896
+ return true;
3897
+ } catch {
3898
+ return false;
3899
+ }
3900
+ }
3901
+ function getVersion(command, versionFlag) {
3902
+ try {
3903
+ const output = (0, import_child_process7.execSync)(`${command} ${versionFlag} 2>&1`, {
3904
+ encoding: "utf-8",
3905
+ timeout: 5e3,
3906
+ stdio: ["pipe", "pipe", "pipe"]
3907
+ });
3908
+ const match = output.match(/(\d+\.\d+\.?\d*)/);
3909
+ return match ? match[1] : output.trim().split("\n")[0].slice(0, 50);
3910
+ } catch {
3911
+ return null;
3912
+ }
3913
+ }
3914
+ function findBinary(command, kind = "binary") {
3915
+ const rudiPaths = [
3916
+ import_path7.default.join(import_core12.PATHS.agents, command, "node_modules", ".bin", command),
3917
+ import_path7.default.join(import_core12.PATHS.runtimes, command, "bin", command),
3918
+ import_path7.default.join(import_core12.PATHS.binaries, command, command),
3919
+ import_path7.default.join(import_core12.PATHS.binaries, command)
3920
+ ];
3921
+ for (const p of rudiPaths) {
3922
+ if (import_fs10.default.existsSync(p)) {
3923
+ return { found: true, path: p, source: "rudi" };
3924
+ }
3925
+ }
3926
+ try {
3927
+ const output = (0, import_child_process7.execSync)(`which ${command} 2>/dev/null`, {
3928
+ encoding: "utf-8",
3929
+ timeout: 3e3
3930
+ });
3931
+ const globalPath = output.trim();
3932
+ if (globalPath) {
3933
+ return { found: true, path: globalPath, source: "global" };
3934
+ }
3935
+ } catch {
3936
+ }
3937
+ return { found: false, path: null, source: null };
3938
+ }
3939
+ function getAgentStatus(agent) {
3940
+ const rudiPath = import_path7.default.join(import_core12.PATHS.agents, agent.id, "node_modules", ".bin", agent.id);
3941
+ const rudiInstalled = import_fs10.default.existsSync(rudiPath);
3942
+ let globalPath = null;
3943
+ let globalInstalled = false;
3944
+ if (!rudiInstalled) {
3945
+ try {
3946
+ const which = (0, import_child_process7.execSync)(`which ${agent.id} 2>/dev/null`, { encoding: "utf-8" }).trim();
3947
+ if (which && !which.includes(".rudi/bins") && !which.includes(".rudi/shims")) {
3948
+ globalPath = which;
3949
+ globalInstalled = true;
3950
+ }
3951
+ } catch {
3952
+ }
3953
+ }
3954
+ const installed = rudiInstalled || globalInstalled;
3955
+ const activePath = rudiInstalled ? rudiPath : globalPath;
3956
+ const source = rudiInstalled ? "rudi" : globalInstalled ? "global" : null;
3957
+ let authenticated = false;
3958
+ if (agent.credentialType === "keychain") {
3959
+ authenticated = checkKeychain(agent.keychainService);
3960
+ } else if (agent.credentialType === "file") {
3961
+ authenticated = fileExists(agent.credentialPath);
3962
+ }
3963
+ let version = null;
3964
+ if (installed && activePath) {
3965
+ version = getVersion(activePath, "--version");
3966
+ }
3967
+ return {
3968
+ id: agent.id,
3969
+ name: agent.name,
3970
+ installed,
3971
+ source,
3972
+ // 'rudi' | 'global' | null
3973
+ authenticated,
3974
+ version,
3975
+ path: activePath,
3976
+ ready: installed && authenticated
3977
+ };
3978
+ }
3979
+ function getRuntimeStatus(runtime) {
3980
+ const location = findBinary(runtime.command, "runtime");
3981
+ const version = location.found ? getVersion(location.path, runtime.versionFlag) : null;
3982
+ return {
3983
+ id: runtime.id,
3984
+ name: runtime.name,
3985
+ installed: location.found,
3986
+ version,
3987
+ path: location.path,
3988
+ source: location.source
3989
+ };
3990
+ }
3991
+ function getBinaryStatus(binary) {
3992
+ const location = findBinary(binary.command, "binary");
3993
+ const version = location.found ? getVersion(location.path, binary.versionFlag) : null;
3994
+ return {
3995
+ id: binary.id,
3996
+ name: binary.name,
3997
+ installed: location.found,
3998
+ version,
3999
+ path: location.path,
4000
+ source: location.source
4001
+ };
4002
+ }
4003
+ async function getFullStatus() {
4004
+ const agents = AGENTS.map(getAgentStatus);
4005
+ const runtimes = RUNTIMES.map(getRuntimeStatus);
4006
+ const binaries = BINARIES.map(getBinaryStatus);
4007
+ let stacks = [];
4008
+ let prompts = [];
4009
+ try {
4010
+ stacks = (0, import_core12.getInstalledPackages)("stack").map((s) => ({
4011
+ id: s.id,
4012
+ name: s.name,
4013
+ version: s.version
4014
+ }));
4015
+ prompts = (0, import_core12.getInstalledPackages)("prompt").map((p) => ({
4016
+ id: p.id,
4017
+ name: p.name,
4018
+ category: p.category
4019
+ }));
4020
+ } catch {
4021
+ }
4022
+ const directories = {
4023
+ home: { path: import_core12.PATHS.home, exists: import_fs10.default.existsSync(import_core12.PATHS.home) },
4024
+ stacks: { path: import_core12.PATHS.stacks, exists: import_fs10.default.existsSync(import_core12.PATHS.stacks) },
4025
+ agents: { path: import_core12.PATHS.agents, exists: import_fs10.default.existsSync(import_core12.PATHS.agents) },
4026
+ runtimes: { path: import_core12.PATHS.runtimes, exists: import_fs10.default.existsSync(import_core12.PATHS.runtimes) },
4027
+ binaries: { path: import_core12.PATHS.binaries, exists: import_fs10.default.existsSync(import_core12.PATHS.binaries) },
4028
+ db: { path: import_core12.PATHS.db, exists: import_fs10.default.existsSync(import_core12.PATHS.db) }
4029
+ };
4030
+ const summary = {
4031
+ agentsInstalled: agents.filter((a) => a.installed).length,
4032
+ agentsReady: agents.filter((a) => a.ready).length,
4033
+ agentsTotal: agents.length,
4034
+ runtimesInstalled: runtimes.filter((r) => r.installed).length,
4035
+ runtimesTotal: runtimes.length,
4036
+ binariesInstalled: binaries.filter((b) => b.installed).length,
4037
+ binariesTotal: binaries.length,
4038
+ stacksInstalled: stacks.length,
4039
+ promptsInstalled: prompts.length
4040
+ };
4041
+ return {
4042
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
4043
+ platform: `${process.platform}-${process.arch}`,
4044
+ rudiHome: import_core12.PATHS.home,
4045
+ summary,
4046
+ agents,
4047
+ runtimes,
4048
+ binaries,
4049
+ stacks,
4050
+ prompts,
4051
+ directories
4052
+ };
4053
+ }
4054
+ function printStatus(status, filter) {
4055
+ console.log("RUDI Status");
4056
+ console.log("=".repeat(50));
4057
+ console.log(`Platform: ${status.platform}`);
4058
+ console.log(`RUDI Home: ${status.rudiHome}`);
4059
+ console.log("");
4060
+ if (!filter || filter === "agents") {
4061
+ console.log(`AGENTS (${status.summary.agentsReady}/${status.summary.agentsTotal} ready)`);
4062
+ console.log("-".repeat(50));
4063
+ for (const agent of status.agents) {
4064
+ const installIcon = agent.installed ? "\x1B[32m\u2713\x1B[0m" : "\x1B[31m\u2717\x1B[0m";
4065
+ const version = agent.version ? `v${agent.version}` : "";
4066
+ const source = agent.source ? `(${agent.source})` : "";
4067
+ console.log(` ${installIcon} ${agent.name} ${version} ${source}`);
4068
+ console.log(` Installed: ${agent.installed ? "yes" : "no"}, Auth: ${agent.authenticated ? "yes" : "no"}, Ready: ${agent.ready ? "yes" : "no"}`);
4069
+ }
4070
+ console.log("");
4071
+ }
4072
+ if (!filter || filter === "runtimes") {
4073
+ console.log(`RUNTIMES (${status.summary.runtimesInstalled}/${status.summary.runtimesTotal})`);
4074
+ console.log("-".repeat(50));
4075
+ for (const rt of status.runtimes) {
4076
+ const icon = rt.installed ? "\x1B[32m\u2713\x1B[0m" : "\x1B[90m\u25CB\x1B[0m";
4077
+ const version = rt.version ? `v${rt.version}` : "";
4078
+ const source = rt.source ? `(${rt.source})` : "";
4079
+ console.log(` ${icon} ${rt.name} ${version} ${source}`);
4080
+ }
4081
+ console.log("");
4082
+ }
4083
+ if (!filter || filter === "binaries") {
4084
+ console.log(`BINARIES (${status.summary.binariesInstalled}/${status.summary.binariesTotal})`);
4085
+ console.log("-".repeat(50));
4086
+ for (const bin of status.binaries) {
4087
+ const icon = bin.installed ? "\x1B[32m\u2713\x1B[0m" : "\x1B[90m\u25CB\x1B[0m";
4088
+ const version = bin.version ? `v${bin.version}` : "";
4089
+ const source = bin.source ? `(${bin.source})` : "";
4090
+ console.log(` ${icon} ${bin.name} ${version} ${source}`);
4091
+ }
4092
+ console.log("");
4093
+ }
4094
+ if (!filter || filter === "stacks") {
4095
+ console.log(`STACKS (${status.summary.stacksInstalled})`);
4096
+ console.log("-".repeat(50));
4097
+ if (status.stacks.length === 0) {
4098
+ console.log(" No stacks installed");
4099
+ } else {
4100
+ for (const stack of status.stacks) {
4101
+ console.log(` ${stack.id} v${stack.version || "?"}`);
4102
+ }
4103
+ }
4104
+ console.log("");
4105
+ }
4106
+ console.log("SUMMARY");
4107
+ console.log("-".repeat(50));
4108
+ console.log(` Agents ready: ${status.summary.agentsReady}/${status.summary.agentsTotal}`);
4109
+ console.log(` Runtimes: ${status.summary.runtimesInstalled}/${status.summary.runtimesTotal}`);
4110
+ console.log(` Binaries: ${status.summary.binariesInstalled}/${status.summary.binariesTotal}`);
4111
+ console.log(` Stacks: ${status.summary.stacksInstalled}`);
4112
+ console.log(` Prompts: ${status.summary.promptsInstalled}`);
4113
+ }
4114
+ async function cmdStatus(args, flags) {
4115
+ const filter = args[0];
4116
+ const status = await getFullStatus();
4117
+ if (flags.json) {
4118
+ if (filter) {
4119
+ const filtered = {
4120
+ timestamp: status.timestamp,
4121
+ platform: status.platform,
4122
+ [filter]: status[filter]
4123
+ };
4124
+ console.log(JSON.stringify(filtered, null, 2));
4125
+ } else {
4126
+ console.log(JSON.stringify(status, null, 2));
4127
+ }
4128
+ } else {
4129
+ printStatus(status, filter);
4130
+ }
4131
+ }
4132
+
4133
+ // src/commands/check.js
4134
+ var import_core13 = require("@learnrudi/core");
4135
+ var import_child_process8 = require("child_process");
4136
+ var import_fs11 = __toESM(require("fs"), 1);
4137
+ var import_path8 = __toESM(require("path"), 1);
4138
+ var import_os5 = __toESM(require("os"), 1);
4139
+ var AGENT_CREDENTIALS = {
4140
+ claude: { type: "keychain", service: "Claude Code-credentials" },
4141
+ codex: { type: "file", path: "~/.codex/auth.json" },
4142
+ gemini: { type: "file", path: "~/.gemini/google_accounts.json" },
4143
+ copilot: { type: "file", path: "~/.config/github-copilot/hosts.json" }
4144
+ };
4145
+ function fileExists2(filePath) {
4146
+ const resolved = filePath.replace("~", import_os5.default.homedir());
4147
+ return import_fs11.default.existsSync(resolved);
4148
+ }
4149
+ function checkKeychain2(service) {
4150
+ if (process.platform !== "darwin") return false;
4151
+ try {
4152
+ (0, import_child_process8.execSync)(`security find-generic-password -s "${service}"`, {
4153
+ stdio: ["pipe", "pipe", "pipe"]
4154
+ });
4155
+ return true;
4156
+ } catch {
4157
+ return false;
4158
+ }
4159
+ }
4160
+ function getVersion2(binaryPath, versionFlag = "--version") {
4161
+ try {
4162
+ const output = (0, import_child_process8.execSync)(`"${binaryPath}" ${versionFlag} 2>&1`, {
4163
+ encoding: "utf-8",
4164
+ timeout: 5e3
4165
+ });
4166
+ const match = output.match(/(\d+\.\d+\.?\d*)/);
4167
+ return match ? match[1] : null;
4168
+ } catch {
4169
+ return null;
4170
+ }
4171
+ }
4172
+ async function cmdCheck(args, flags) {
4173
+ const packageId = args[0];
4174
+ if (!packageId) {
4175
+ console.error("Usage: rudi check <package-id>");
4176
+ console.error("Examples:");
4177
+ console.error(" rudi check agent:claude");
4178
+ console.error(" rudi check runtime:python");
4179
+ console.error(" rudi check binary:ffmpeg");
4180
+ console.error(" rudi check stack:slack");
4181
+ process.exit(1);
4182
+ }
4183
+ let kind, name;
4184
+ if (packageId.includes(":")) {
4185
+ [kind, name] = packageId.split(":");
4186
+ } else {
4187
+ if (["claude", "codex", "gemini", "copilot"].includes(packageId)) {
4188
+ kind = "agent";
4189
+ name = packageId;
4190
+ } else if (["node", "python", "deno", "bun"].includes(packageId)) {
4191
+ kind = "runtime";
4192
+ name = packageId;
4193
+ } else {
4194
+ kind = "stack";
4195
+ name = packageId;
4196
+ }
4197
+ }
4198
+ const result = {
4199
+ id: `${kind}:${name}`,
4200
+ kind,
4201
+ name,
4202
+ installed: false,
4203
+ source: null,
4204
+ // 'rudi' | 'global' | null
4205
+ authenticated: null,
4206
+ // Only for agents
4207
+ ready: false,
4208
+ path: null,
4209
+ version: null
4210
+ };
4211
+ switch (kind) {
4212
+ case "agent": {
4213
+ const rudiPath = import_path8.default.join(import_core13.PATHS.agents, name, "node_modules", ".bin", name);
4214
+ const rudiInstalled = import_fs11.default.existsSync(rudiPath);
4215
+ let globalPath = null;
4216
+ let globalInstalled = false;
4217
+ if (!rudiInstalled) {
4218
+ try {
4219
+ const which = (0, import_child_process8.execSync)(`which ${name} 2>/dev/null`, { encoding: "utf-8" }).trim();
4220
+ if (which && !which.includes(".rudi/bins") && !which.includes(".rudi/shims")) {
4221
+ globalPath = which;
4222
+ globalInstalled = true;
4223
+ }
4224
+ } catch {
4225
+ }
4226
+ }
4227
+ result.installed = rudiInstalled || globalInstalled;
4228
+ result.path = rudiInstalled ? rudiPath : globalPath;
4229
+ result.source = rudiInstalled ? "rudi" : globalInstalled ? "global" : null;
4230
+ if (result.installed && result.path) {
4231
+ result.version = getVersion2(result.path);
4232
+ }
4233
+ const cred = AGENT_CREDENTIALS[name];
4234
+ if (cred) {
4235
+ if (cred.type === "keychain") {
4236
+ result.authenticated = checkKeychain2(cred.service);
4237
+ } else if (cred.type === "file") {
4238
+ result.authenticated = fileExists2(cred.path);
4239
+ }
4240
+ }
4241
+ result.ready = result.installed && result.authenticated;
4242
+ break;
4243
+ }
4244
+ case "runtime": {
4245
+ const rudiPath = import_path8.default.join(import_core13.PATHS.runtimes, name, "bin", name);
4246
+ if (import_fs11.default.existsSync(rudiPath)) {
4247
+ result.installed = true;
4248
+ result.path = rudiPath;
4249
+ result.version = getVersion2(rudiPath);
4250
+ } else {
4251
+ try {
4252
+ const globalPath = (0, import_child_process8.execSync)(`which ${name} 2>/dev/null`, { encoding: "utf-8" }).trim();
4253
+ if (globalPath) {
4254
+ result.installed = true;
4255
+ result.path = globalPath;
4256
+ result.version = getVersion2(globalPath);
4257
+ }
4258
+ } catch {
4259
+ }
4260
+ }
4261
+ result.ready = result.installed;
4262
+ break;
4263
+ }
4264
+ case "binary": {
4265
+ const rudiPath = import_path8.default.join(import_core13.PATHS.binaries, name, name);
4266
+ if (import_fs11.default.existsSync(rudiPath)) {
4267
+ result.installed = true;
4268
+ result.path = rudiPath;
4269
+ } else {
4270
+ try {
4271
+ const globalPath = (0, import_child_process8.execSync)(`which ${name} 2>/dev/null`, { encoding: "utf-8" }).trim();
4272
+ if (globalPath) {
4273
+ result.installed = true;
4274
+ result.path = globalPath;
4275
+ }
4276
+ } catch {
4277
+ }
4278
+ }
4279
+ result.ready = result.installed;
4280
+ break;
4281
+ }
4282
+ case "stack": {
4283
+ result.installed = (0, import_core13.isPackageInstalled)(`stack:${name}`);
4284
+ if (result.installed) {
4285
+ result.path = (0, import_core13.getPackagePath)(`stack:${name}`);
4286
+ }
4287
+ result.ready = result.installed;
4288
+ break;
4289
+ }
4290
+ default:
4291
+ console.error(`Unknown package kind: ${kind}`);
4292
+ process.exit(1);
4293
+ }
4294
+ if (flags.json) {
4295
+ console.log(JSON.stringify(result, null, 2));
4296
+ } else {
4297
+ const installIcon = result.installed ? "\x1B[32m\u2713\x1B[0m" : "\x1B[31m\u2717\x1B[0m";
4298
+ console.log(`${installIcon} ${result.id}`);
4299
+ console.log(` Installed: ${result.installed}`);
4300
+ if (result.path) console.log(` Path: ${result.path}`);
4301
+ if (result.version) console.log(` Version: ${result.version}`);
4302
+ if (result.authenticated !== null) {
4303
+ console.log(` Authenticated: ${result.authenticated}`);
4304
+ }
4305
+ console.log(` Ready: ${result.ready}`);
4306
+ }
4307
+ if (!result.installed) {
4308
+ process.exit(1);
4309
+ } else if (result.authenticated === false) {
4310
+ process.exit(2);
4311
+ } else {
4312
+ process.exit(0);
4313
+ }
4314
+ }
4315
+
3837
4316
  // src/index.js
3838
4317
  var VERSION = "2.0.0";
3839
4318
  async function main() {
@@ -3881,7 +4360,6 @@ async function main() {
3881
4360
  await cmdImport(args, flags);
3882
4361
  break;
3883
4362
  case "doctor":
3884
- case "check":
3885
4363
  await cmdDoctor(args, flags);
3886
4364
  break;
3887
4365
  case "init":
@@ -3919,9 +4397,14 @@ async function main() {
3919
4397
  await cmdIndex(args, flags);
3920
4398
  break;
3921
4399
  case "home":
3922
- case "status":
3923
4400
  await cmdHome(args, flags);
3924
4401
  break;
4402
+ case "status":
4403
+ await cmdStatus(args, flags);
4404
+ break;
4405
+ case "check":
4406
+ await cmdCheck(args, flags);
4407
+ break;
3925
4408
  // Shortcuts for listing specific package types
3926
4409
  case "stacks":
3927
4410
  await cmdList(["stacks"], flags);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@learnrudi/cli",
3
- "version": "1.9.2",
3
+ "version": "1.9.4",
4
4
  "description": "RUDI CLI - Install and manage MCP stacks, runtimes, and AI agents",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",