@learnrudi/cli 1.9.2 → 1.9.3

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 +452 -2
  2. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -3834,6 +3834,452 @@ 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 binaryPath = import_path7.default.join(import_core12.PATHS.agents, agent.id, "node_modules", ".bin", agent.id);
3941
+ const installed = import_fs10.default.existsSync(binaryPath);
3942
+ let authenticated = false;
3943
+ if (agent.credentialType === "keychain") {
3944
+ authenticated = checkKeychain(agent.keychainService);
3945
+ } else if (agent.credentialType === "file") {
3946
+ authenticated = fileExists(agent.credentialPath);
3947
+ }
3948
+ let version = null;
3949
+ if (installed) {
3950
+ version = getVersion(binaryPath, "--version");
3951
+ }
3952
+ return {
3953
+ id: agent.id,
3954
+ name: agent.name,
3955
+ installed,
3956
+ authenticated,
3957
+ version,
3958
+ path: installed ? binaryPath : null,
3959
+ ready: installed && authenticated
3960
+ };
3961
+ }
3962
+ function getRuntimeStatus(runtime) {
3963
+ const location = findBinary(runtime.command, "runtime");
3964
+ const version = location.found ? getVersion(location.path, runtime.versionFlag) : null;
3965
+ return {
3966
+ id: runtime.id,
3967
+ name: runtime.name,
3968
+ installed: location.found,
3969
+ version,
3970
+ path: location.path,
3971
+ source: location.source
3972
+ };
3973
+ }
3974
+ function getBinaryStatus(binary) {
3975
+ const location = findBinary(binary.command, "binary");
3976
+ const version = location.found ? getVersion(location.path, binary.versionFlag) : null;
3977
+ return {
3978
+ id: binary.id,
3979
+ name: binary.name,
3980
+ installed: location.found,
3981
+ version,
3982
+ path: location.path,
3983
+ source: location.source
3984
+ };
3985
+ }
3986
+ async function getFullStatus() {
3987
+ const agents = AGENTS.map(getAgentStatus);
3988
+ const runtimes = RUNTIMES.map(getRuntimeStatus);
3989
+ const binaries = BINARIES.map(getBinaryStatus);
3990
+ let stacks = [];
3991
+ let prompts = [];
3992
+ try {
3993
+ stacks = (0, import_core12.getInstalledPackages)("stack").map((s) => ({
3994
+ id: s.id,
3995
+ name: s.name,
3996
+ version: s.version
3997
+ }));
3998
+ prompts = (0, import_core12.getInstalledPackages)("prompt").map((p) => ({
3999
+ id: p.id,
4000
+ name: p.name,
4001
+ category: p.category
4002
+ }));
4003
+ } catch {
4004
+ }
4005
+ const directories = {
4006
+ home: { path: import_core12.PATHS.home, exists: import_fs10.default.existsSync(import_core12.PATHS.home) },
4007
+ stacks: { path: import_core12.PATHS.stacks, exists: import_fs10.default.existsSync(import_core12.PATHS.stacks) },
4008
+ agents: { path: import_core12.PATHS.agents, exists: import_fs10.default.existsSync(import_core12.PATHS.agents) },
4009
+ runtimes: { path: import_core12.PATHS.runtimes, exists: import_fs10.default.existsSync(import_core12.PATHS.runtimes) },
4010
+ binaries: { path: import_core12.PATHS.binaries, exists: import_fs10.default.existsSync(import_core12.PATHS.binaries) },
4011
+ db: { path: import_core12.PATHS.db, exists: import_fs10.default.existsSync(import_core12.PATHS.db) }
4012
+ };
4013
+ const summary = {
4014
+ agentsInstalled: agents.filter((a) => a.installed).length,
4015
+ agentsReady: agents.filter((a) => a.ready).length,
4016
+ agentsTotal: agents.length,
4017
+ runtimesInstalled: runtimes.filter((r) => r.installed).length,
4018
+ runtimesTotal: runtimes.length,
4019
+ binariesInstalled: binaries.filter((b) => b.installed).length,
4020
+ binariesTotal: binaries.length,
4021
+ stacksInstalled: stacks.length,
4022
+ promptsInstalled: prompts.length
4023
+ };
4024
+ return {
4025
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
4026
+ platform: `${process.platform}-${process.arch}`,
4027
+ rudiHome: import_core12.PATHS.home,
4028
+ summary,
4029
+ agents,
4030
+ runtimes,
4031
+ binaries,
4032
+ stacks,
4033
+ prompts,
4034
+ directories
4035
+ };
4036
+ }
4037
+ function printStatus(status, filter) {
4038
+ console.log("RUDI Status");
4039
+ console.log("=".repeat(50));
4040
+ console.log(`Platform: ${status.platform}`);
4041
+ console.log(`RUDI Home: ${status.rudiHome}`);
4042
+ console.log("");
4043
+ if (!filter || filter === "agents") {
4044
+ console.log(`AGENTS (${status.summary.agentsReady}/${status.summary.agentsTotal} ready)`);
4045
+ console.log("-".repeat(50));
4046
+ for (const agent of status.agents) {
4047
+ const installIcon = agent.installed ? "\x1B[32m\u2713\x1B[0m" : "\x1B[31m\u2717\x1B[0m";
4048
+ const authIcon = agent.authenticated ? "\x1B[32m\u2713\x1B[0m" : "\x1B[33m\u25CB\x1B[0m";
4049
+ const version = agent.version ? `v${agent.version}` : "";
4050
+ console.log(` ${installIcon} ${agent.name} ${version}`);
4051
+ console.log(` Installed: ${agent.installed ? "yes" : "no"}, Auth: ${agent.authenticated ? "yes" : "no"}`);
4052
+ }
4053
+ console.log("");
4054
+ }
4055
+ if (!filter || filter === "runtimes") {
4056
+ console.log(`RUNTIMES (${status.summary.runtimesInstalled}/${status.summary.runtimesTotal})`);
4057
+ console.log("-".repeat(50));
4058
+ for (const rt of status.runtimes) {
4059
+ const icon = rt.installed ? "\x1B[32m\u2713\x1B[0m" : "\x1B[90m\u25CB\x1B[0m";
4060
+ const version = rt.version ? `v${rt.version}` : "";
4061
+ const source = rt.source ? `(${rt.source})` : "";
4062
+ console.log(` ${icon} ${rt.name} ${version} ${source}`);
4063
+ }
4064
+ console.log("");
4065
+ }
4066
+ if (!filter || filter === "binaries") {
4067
+ console.log(`BINARIES (${status.summary.binariesInstalled}/${status.summary.binariesTotal})`);
4068
+ console.log("-".repeat(50));
4069
+ for (const bin of status.binaries) {
4070
+ const icon = bin.installed ? "\x1B[32m\u2713\x1B[0m" : "\x1B[90m\u25CB\x1B[0m";
4071
+ const version = bin.version ? `v${bin.version}` : "";
4072
+ const source = bin.source ? `(${bin.source})` : "";
4073
+ console.log(` ${icon} ${bin.name} ${version} ${source}`);
4074
+ }
4075
+ console.log("");
4076
+ }
4077
+ if (!filter || filter === "stacks") {
4078
+ console.log(`STACKS (${status.summary.stacksInstalled})`);
4079
+ console.log("-".repeat(50));
4080
+ if (status.stacks.length === 0) {
4081
+ console.log(" No stacks installed");
4082
+ } else {
4083
+ for (const stack of status.stacks) {
4084
+ console.log(` ${stack.id} v${stack.version || "?"}`);
4085
+ }
4086
+ }
4087
+ console.log("");
4088
+ }
4089
+ console.log("SUMMARY");
4090
+ console.log("-".repeat(50));
4091
+ console.log(` Agents ready: ${status.summary.agentsReady}/${status.summary.agentsTotal}`);
4092
+ console.log(` Runtimes: ${status.summary.runtimesInstalled}/${status.summary.runtimesTotal}`);
4093
+ console.log(` Binaries: ${status.summary.binariesInstalled}/${status.summary.binariesTotal}`);
4094
+ console.log(` Stacks: ${status.summary.stacksInstalled}`);
4095
+ console.log(` Prompts: ${status.summary.promptsInstalled}`);
4096
+ }
4097
+ async function cmdStatus(args, flags) {
4098
+ const filter = args[0];
4099
+ const status = await getFullStatus();
4100
+ if (flags.json) {
4101
+ if (filter) {
4102
+ const filtered = {
4103
+ timestamp: status.timestamp,
4104
+ platform: status.platform,
4105
+ [filter]: status[filter]
4106
+ };
4107
+ console.log(JSON.stringify(filtered, null, 2));
4108
+ } else {
4109
+ console.log(JSON.stringify(status, null, 2));
4110
+ }
4111
+ } else {
4112
+ printStatus(status, filter);
4113
+ }
4114
+ }
4115
+
4116
+ // src/commands/check.js
4117
+ var import_core13 = require("@learnrudi/core");
4118
+ var import_child_process8 = require("child_process");
4119
+ var import_fs11 = __toESM(require("fs"), 1);
4120
+ var import_path8 = __toESM(require("path"), 1);
4121
+ var import_os5 = __toESM(require("os"), 1);
4122
+ var AGENT_CREDENTIALS = {
4123
+ claude: { type: "keychain", service: "Claude Code-credentials" },
4124
+ codex: { type: "file", path: "~/.codex/auth.json" },
4125
+ gemini: { type: "file", path: "~/.gemini/google_accounts.json" },
4126
+ copilot: { type: "file", path: "~/.config/github-copilot/hosts.json" }
4127
+ };
4128
+ function fileExists2(filePath) {
4129
+ const resolved = filePath.replace("~", import_os5.default.homedir());
4130
+ return import_fs11.default.existsSync(resolved);
4131
+ }
4132
+ function checkKeychain2(service) {
4133
+ if (process.platform !== "darwin") return false;
4134
+ try {
4135
+ (0, import_child_process8.execSync)(`security find-generic-password -s "${service}"`, {
4136
+ stdio: ["pipe", "pipe", "pipe"]
4137
+ });
4138
+ return true;
4139
+ } catch {
4140
+ return false;
4141
+ }
4142
+ }
4143
+ function getVersion2(binaryPath, versionFlag = "--version") {
4144
+ try {
4145
+ const output = (0, import_child_process8.execSync)(`"${binaryPath}" ${versionFlag} 2>&1`, {
4146
+ encoding: "utf-8",
4147
+ timeout: 5e3
4148
+ });
4149
+ const match = output.match(/(\d+\.\d+\.?\d*)/);
4150
+ return match ? match[1] : null;
4151
+ } catch {
4152
+ return null;
4153
+ }
4154
+ }
4155
+ async function cmdCheck(args, flags) {
4156
+ const packageId = args[0];
4157
+ if (!packageId) {
4158
+ console.error("Usage: rudi check <package-id>");
4159
+ console.error("Examples:");
4160
+ console.error(" rudi check agent:claude");
4161
+ console.error(" rudi check runtime:python");
4162
+ console.error(" rudi check binary:ffmpeg");
4163
+ console.error(" rudi check stack:slack");
4164
+ process.exit(1);
4165
+ }
4166
+ let kind, name;
4167
+ if (packageId.includes(":")) {
4168
+ [kind, name] = packageId.split(":");
4169
+ } else {
4170
+ if (["claude", "codex", "gemini", "copilot"].includes(packageId)) {
4171
+ kind = "agent";
4172
+ name = packageId;
4173
+ } else if (["node", "python", "deno", "bun"].includes(packageId)) {
4174
+ kind = "runtime";
4175
+ name = packageId;
4176
+ } else {
4177
+ kind = "stack";
4178
+ name = packageId;
4179
+ }
4180
+ }
4181
+ const result = {
4182
+ id: `${kind}:${name}`,
4183
+ kind,
4184
+ name,
4185
+ installed: false,
4186
+ authenticated: null,
4187
+ // Only for agents
4188
+ ready: false,
4189
+ path: null,
4190
+ version: null
4191
+ };
4192
+ switch (kind) {
4193
+ case "agent": {
4194
+ const binaryPath = import_path8.default.join(import_core13.PATHS.agents, name, "node_modules", ".bin", name);
4195
+ result.installed = import_fs11.default.existsSync(binaryPath);
4196
+ result.path = result.installed ? binaryPath : null;
4197
+ if (result.installed) {
4198
+ result.version = getVersion2(binaryPath);
4199
+ }
4200
+ const cred = AGENT_CREDENTIALS[name];
4201
+ if (cred) {
4202
+ if (cred.type === "keychain") {
4203
+ result.authenticated = checkKeychain2(cred.service);
4204
+ } else if (cred.type === "file") {
4205
+ result.authenticated = fileExists2(cred.path);
4206
+ }
4207
+ }
4208
+ result.ready = result.installed && result.authenticated;
4209
+ break;
4210
+ }
4211
+ case "runtime": {
4212
+ const rudiPath = import_path8.default.join(import_core13.PATHS.runtimes, name, "bin", name);
4213
+ if (import_fs11.default.existsSync(rudiPath)) {
4214
+ result.installed = true;
4215
+ result.path = rudiPath;
4216
+ result.version = getVersion2(rudiPath);
4217
+ } else {
4218
+ try {
4219
+ const globalPath = (0, import_child_process8.execSync)(`which ${name} 2>/dev/null`, { encoding: "utf-8" }).trim();
4220
+ if (globalPath) {
4221
+ result.installed = true;
4222
+ result.path = globalPath;
4223
+ result.version = getVersion2(globalPath);
4224
+ }
4225
+ } catch {
4226
+ }
4227
+ }
4228
+ result.ready = result.installed;
4229
+ break;
4230
+ }
4231
+ case "binary": {
4232
+ const rudiPath = import_path8.default.join(import_core13.PATHS.binaries, name, name);
4233
+ if (import_fs11.default.existsSync(rudiPath)) {
4234
+ result.installed = true;
4235
+ result.path = rudiPath;
4236
+ } else {
4237
+ try {
4238
+ const globalPath = (0, import_child_process8.execSync)(`which ${name} 2>/dev/null`, { encoding: "utf-8" }).trim();
4239
+ if (globalPath) {
4240
+ result.installed = true;
4241
+ result.path = globalPath;
4242
+ }
4243
+ } catch {
4244
+ }
4245
+ }
4246
+ result.ready = result.installed;
4247
+ break;
4248
+ }
4249
+ case "stack": {
4250
+ result.installed = (0, import_core13.isPackageInstalled)(`stack:${name}`);
4251
+ if (result.installed) {
4252
+ result.path = (0, import_core13.getPackagePath)(`stack:${name}`);
4253
+ }
4254
+ result.ready = result.installed;
4255
+ break;
4256
+ }
4257
+ default:
4258
+ console.error(`Unknown package kind: ${kind}`);
4259
+ process.exit(1);
4260
+ }
4261
+ if (flags.json) {
4262
+ console.log(JSON.stringify(result, null, 2));
4263
+ } else {
4264
+ const installIcon = result.installed ? "\x1B[32m\u2713\x1B[0m" : "\x1B[31m\u2717\x1B[0m";
4265
+ console.log(`${installIcon} ${result.id}`);
4266
+ console.log(` Installed: ${result.installed}`);
4267
+ if (result.path) console.log(` Path: ${result.path}`);
4268
+ if (result.version) console.log(` Version: ${result.version}`);
4269
+ if (result.authenticated !== null) {
4270
+ console.log(` Authenticated: ${result.authenticated}`);
4271
+ }
4272
+ console.log(` Ready: ${result.ready}`);
4273
+ }
4274
+ if (!result.installed) {
4275
+ process.exit(1);
4276
+ } else if (result.authenticated === false) {
4277
+ process.exit(2);
4278
+ } else {
4279
+ process.exit(0);
4280
+ }
4281
+ }
4282
+
3837
4283
  // src/index.js
3838
4284
  var VERSION = "2.0.0";
3839
4285
  async function main() {
@@ -3881,7 +4327,6 @@ async function main() {
3881
4327
  await cmdImport(args, flags);
3882
4328
  break;
3883
4329
  case "doctor":
3884
- case "check":
3885
4330
  await cmdDoctor(args, flags);
3886
4331
  break;
3887
4332
  case "init":
@@ -3919,9 +4364,14 @@ async function main() {
3919
4364
  await cmdIndex(args, flags);
3920
4365
  break;
3921
4366
  case "home":
3922
- case "status":
3923
4367
  await cmdHome(args, flags);
3924
4368
  break;
4369
+ case "status":
4370
+ await cmdStatus(args, flags);
4371
+ break;
4372
+ case "check":
4373
+ await cmdCheck(args, flags);
4374
+ break;
3925
4375
  // Shortcuts for listing specific package types
3926
4376
  case "stacks":
3927
4377
  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.3",
4
4
  "description": "RUDI CLI - Install and manage MCP stacks, runtimes, and AI agents",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",