@reumbra/forge 0.1.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.
Files changed (63) hide show
  1. package/README.md +165 -0
  2. package/bin/forge.js +2 -0
  3. package/dist/cli.d.ts +2 -0
  4. package/dist/cli.js +225 -0
  5. package/dist/cli.js.map +1 -0
  6. package/dist/commands/activate.d.ts +1 -0
  7. package/dist/commands/activate.js +55 -0
  8. package/dist/commands/activate.js.map +1 -0
  9. package/dist/commands/config.d.ts +1 -0
  10. package/dist/commands/config.js +35 -0
  11. package/dist/commands/config.js.map +1 -0
  12. package/dist/commands/dashboard.d.ts +1 -0
  13. package/dist/commands/dashboard.js +171 -0
  14. package/dist/commands/dashboard.js.map +1 -0
  15. package/dist/commands/deactivate.d.ts +1 -0
  16. package/dist/commands/deactivate.js +33 -0
  17. package/dist/commands/deactivate.js.map +1 -0
  18. package/dist/commands/doctor.d.ts +5 -0
  19. package/dist/commands/doctor.js +156 -0
  20. package/dist/commands/doctor.js.map +1 -0
  21. package/dist/commands/install.d.ts +1 -0
  22. package/dist/commands/install.js +94 -0
  23. package/dist/commands/install.js.map +1 -0
  24. package/dist/commands/list.d.ts +1 -0
  25. package/dist/commands/list.js +46 -0
  26. package/dist/commands/list.js.map +1 -0
  27. package/dist/commands/status.d.ts +1 -0
  28. package/dist/commands/status.js +75 -0
  29. package/dist/commands/status.js.map +1 -0
  30. package/dist/commands/uninstall.d.ts +1 -0
  31. package/dist/commands/uninstall.js +31 -0
  32. package/dist/commands/uninstall.js.map +1 -0
  33. package/dist/commands/update.d.ts +1 -0
  34. package/dist/commands/update.js +30 -0
  35. package/dist/commands/update.js.map +1 -0
  36. package/dist/lib/api.d.ts +17 -0
  37. package/dist/lib/api.js +53 -0
  38. package/dist/lib/api.js.map +1 -0
  39. package/dist/lib/config.d.ts +4 -0
  40. package/dist/lib/config.js +40 -0
  41. package/dist/lib/config.js.map +1 -0
  42. package/dist/lib/logger.d.ts +11 -0
  43. package/dist/lib/logger.js +40 -0
  44. package/dist/lib/logger.js.map +1 -0
  45. package/dist/lib/machine-id.d.ts +5 -0
  46. package/dist/lib/machine-id.js +11 -0
  47. package/dist/lib/machine-id.js.map +1 -0
  48. package/dist/lib/paths.d.ts +8 -0
  49. package/dist/lib/paths.js +13 -0
  50. package/dist/lib/paths.js.map +1 -0
  51. package/dist/lib/styles.d.ts +32 -0
  52. package/dist/lib/styles.js +50 -0
  53. package/dist/lib/styles.js.map +1 -0
  54. package/dist/lib/ui.d.ts +22 -0
  55. package/dist/lib/ui.js +131 -0
  56. package/dist/lib/ui.js.map +1 -0
  57. package/dist/lib/zip.d.ts +6 -0
  58. package/dist/lib/zip.js +56 -0
  59. package/dist/lib/zip.js.map +1 -0
  60. package/dist/types.d.ts +61 -0
  61. package/dist/types.js +2 -0
  62. package/dist/types.js.map +1 -0
  63. package/package.json +51 -0
@@ -0,0 +1,171 @@
1
+ import { existsSync } from "node:fs";
2
+ import * as p from "@clack/prompts";
3
+ import { loadConfig } from "../lib/config.js";
4
+ import { CONFIG_PATH } from "../lib/paths.js";
5
+ import { bold, cyan, dim, green, reset, yellow } from "../lib/styles.js";
6
+ import { banner } from "../lib/ui.js";
7
+ import { activate } from "./activate.js";
8
+ import { showConfig } from "./config.js";
9
+ import { deactivate } from "./deactivate.js";
10
+ import { doctor } from "./doctor.js";
11
+ import { install } from "./install.js";
12
+ import { list } from "./list.js";
13
+ import { status } from "./status.js";
14
+ import { uninstall } from "./uninstall.js";
15
+ import { update } from "./update.js";
16
+ function buildStatusLine() {
17
+ if (!existsSync(CONFIG_PATH)) {
18
+ return `${yellow}No config found${reset} ${dim}— run activate to get started${reset}`;
19
+ }
20
+ const config = loadConfig();
21
+ if (!config.license_key) {
22
+ return `${yellow}No license key${reset} ${dim}— run activate to bind a license${reset}`;
23
+ }
24
+ const maskedKey = `${config.license_key.slice(0, 8)}..${config.license_key.slice(-4)}`;
25
+ const pluginCount = Object.keys(config.installed_plugins).length;
26
+ const pluginLabel = pluginCount === 0 ? "no plugins" : `${pluginCount} plugin${pluginCount > 1 ? "s" : ""}`;
27
+ return `${green}Licensed${reset} ${dim}${maskedKey}${reset} ${cyan}${pluginLabel} installed${reset}`;
28
+ }
29
+ function getMenuOptions(hasLicense) {
30
+ if (!hasLicense) {
31
+ return [
32
+ { value: "activate", label: "Activate license", hint: "bind a license key to this machine" },
33
+ { value: "doctor", label: "Run diagnostics", hint: "check environment health" },
34
+ { value: "config", label: "Show config", hint: "view current configuration" },
35
+ { value: "exit", label: "Exit" },
36
+ ];
37
+ }
38
+ return [
39
+ { value: "status", label: "License status", hint: "plan, expiry, devices, plugins" },
40
+ { value: "list", label: "Browse plugins", hint: "see available plugins for your plan" },
41
+ { value: "install", label: "Install plugin", hint: "download and install a plugin" },
42
+ { value: "update", label: "Update plugins", hint: "check for and apply updates" },
43
+ { value: "uninstall", label: "Uninstall plugin", hint: "remove an installed plugin" },
44
+ { value: "doctor", label: "Run diagnostics", hint: "check environment health" },
45
+ { value: "config", label: "Show config", hint: "view current configuration" },
46
+ { value: "deactivate", label: "Deactivate", hint: "unbind this machine" },
47
+ { value: "exit", label: "Exit" },
48
+ ];
49
+ }
50
+ async function executeAction(action) {
51
+ console.log();
52
+ switch (action) {
53
+ case "activate": {
54
+ const key = await p.text({
55
+ message: "Enter your license key:",
56
+ placeholder: "FRG-XXXX-XXXX-XXXX",
57
+ validate: (v) => {
58
+ if (!v || !/^FRG-[A-Z2-9]{4}-[A-Z2-9]{4}-[A-Z2-9]{4}$/.test(v)) {
59
+ return "Invalid format. Expected: FRG-XXXX-XXXX-XXXX";
60
+ }
61
+ },
62
+ });
63
+ if (p.isCancel(key))
64
+ return;
65
+ await activate(key);
66
+ break;
67
+ }
68
+ case "install": {
69
+ const plugin = await p.text({
70
+ message: "Plugin name to install:",
71
+ placeholder: "e.g. core, forge-product@1.2.0",
72
+ validate: (v) => {
73
+ if (!v?.trim())
74
+ return "Plugin name is required";
75
+ },
76
+ });
77
+ if (p.isCancel(plugin))
78
+ return;
79
+ let name = plugin.trim();
80
+ let version;
81
+ if (name.includes("@")) {
82
+ const parts = name.split("@");
83
+ name = parts[0];
84
+ version = parts[1];
85
+ }
86
+ await install(name, version);
87
+ break;
88
+ }
89
+ case "uninstall": {
90
+ const config = loadConfig();
91
+ const installed = Object.keys(config.installed_plugins);
92
+ if (installed.length === 0) {
93
+ p.log.warn("No plugins installed.");
94
+ return;
95
+ }
96
+ const plugin = await p.select({
97
+ message: "Select plugin to uninstall:",
98
+ options: installed.map((name) => ({
99
+ value: name,
100
+ label: name,
101
+ hint: `v${config.installed_plugins[name].version}`,
102
+ })),
103
+ });
104
+ if (p.isCancel(plugin))
105
+ return;
106
+ const confirmed = await p.confirm({
107
+ message: `Uninstall ${bold}${plugin}${reset}?`,
108
+ });
109
+ if (p.isCancel(confirmed) || !confirmed)
110
+ return;
111
+ uninstall(plugin);
112
+ break;
113
+ }
114
+ case "update":
115
+ await update();
116
+ break;
117
+ case "status":
118
+ await status();
119
+ break;
120
+ case "list":
121
+ await list();
122
+ break;
123
+ case "doctor": {
124
+ await doctor();
125
+ break;
126
+ }
127
+ case "config":
128
+ showConfig();
129
+ break;
130
+ case "deactivate": {
131
+ const confirmed = await p.confirm({
132
+ message: "Deactivate this machine? This will free up a machine slot.",
133
+ });
134
+ if (p.isCancel(confirmed) || !confirmed)
135
+ return;
136
+ await deactivate();
137
+ break;
138
+ }
139
+ case "exit":
140
+ break;
141
+ }
142
+ }
143
+ export async function dashboard() {
144
+ console.log(`\n${banner()}\n`);
145
+ // Dashboard loop
146
+ while (true) {
147
+ const statusLine = buildStatusLine();
148
+ p.log.info(statusLine);
149
+ const config = loadConfig();
150
+ const hasLicense = config.license_key != null;
151
+ const action = await p.select({
152
+ message: "What would you like to do?",
153
+ options: getMenuOptions(hasLicense),
154
+ });
155
+ if (p.isCancel(action) || action === "exit") {
156
+ p.outro(`${dim}Goodbye!${reset}`);
157
+ return;
158
+ }
159
+ try {
160
+ await executeAction(action);
161
+ }
162
+ catch (err) {
163
+ if (err instanceof Error) {
164
+ p.log.error(err.message);
165
+ }
166
+ }
167
+ // Spacer before next loop iteration
168
+ console.log();
169
+ }
170
+ }
171
+ //# sourceMappingURL=dashboard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashboard.js","sourceRoot":"","sources":["../../src/commands/dashboard.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function deactivate(): Promise<void>;
@@ -0,0 +1,33 @@
1
+ import { ApiError, apiRequest } from "../lib/api.js";
2
+ import { loadConfig, saveConfig } from "../lib/config.js";
3
+ import { log } from "../lib/logger.js";
4
+ export async function deactivate() {
5
+ const config = loadConfig();
6
+ if (!config.license_key) {
7
+ log.error("No license key configured. Run `forge activate <key>` first.");
8
+ process.exit(1);
9
+ }
10
+ log.step("Deactivating this machine...");
11
+ try {
12
+ await apiRequest(config, {
13
+ method: "POST",
14
+ path: "/auth/deactivate",
15
+ body: {
16
+ license_key: config.license_key,
17
+ machine_id: config.machine_id,
18
+ },
19
+ });
20
+ config.license_key = null;
21
+ saveConfig(config);
22
+ log.success("Machine deactivated. License slot freed.");
23
+ log.info("You can now activate on another machine.");
24
+ }
25
+ catch (err) {
26
+ if (err instanceof ApiError) {
27
+ log.error(err.message);
28
+ process.exit(1);
29
+ }
30
+ throw err;
31
+ }
32
+ }
33
+ //# sourceMappingURL=deactivate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deactivate.js","sourceRoot":"","sources":["../../src/commands/deactivate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AAEvC,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAE5B,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;QACxB,GAAG,CAAC,KAAK,CAAC,8DAA8D,CAAC,CAAC;QAC1E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,GAAG,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;IAEzC,IAAI,CAAC;QACH,MAAM,UAAU,CAAC,MAAM,EAAE;YACvB,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,kBAAkB;YACxB,IAAI,EAAE;gBACJ,WAAW,EAAE,MAAM,CAAC,WAAW;gBAC/B,UAAU,EAAE,MAAM,CAAC,UAAU;aAC9B;SACF,CAAC,CAAC;QAEH,MAAM,CAAC,WAAW,GAAG,IAAI,CAAC;QAC1B,UAAU,CAAC,MAAM,CAAC,CAAC;QAEnB,GAAG,CAAC,OAAO,CAAC,0CAA0C,CAAC,CAAC;QACxD,GAAG,CAAC,IAAI,CAAC,0CAA0C,CAAC,CAAC;IACvD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,QAAQ,EAAE,CAAC;YAC5B,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACvB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC"}
@@ -0,0 +1,5 @@
1
+ export interface DoctorResult {
2
+ checks: number;
3
+ issues: number;
4
+ }
5
+ export declare function doctor(): Promise<DoctorResult>;
@@ -0,0 +1,156 @@
1
+ import { existsSync, readdirSync, statSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { loadConfig } from "../lib/config.js";
4
+ import { log } from "../lib/logger.js";
5
+ import { CACHE_DIR, CONFIG_PATH, claudePluginDir, FORGE_DIR } from "../lib/paths.js";
6
+ import { bold, dim, green, reset, yellow } from "../lib/styles.js";
7
+ import { banner, box } from "../lib/ui.js";
8
+ export async function doctor() {
9
+ console.log(`\n${banner()}\n`);
10
+ const results = [];
11
+ // 1. Node.js version
12
+ const nodeVersion = process.versions.node;
13
+ const major = Number.parseInt(nodeVersion.split(".")[0], 10);
14
+ results.push({
15
+ label: "Node.js",
16
+ ok: major >= 20,
17
+ detail: `v${nodeVersion}`,
18
+ hint: major < 20 ? "Requires Node.js >=20" : undefined,
19
+ });
20
+ // 2. Forge directory
21
+ results.push({
22
+ label: "Forge directory",
23
+ ok: existsSync(FORGE_DIR),
24
+ detail: FORGE_DIR,
25
+ hint: !existsSync(FORGE_DIR) ? "Run `forge activate <key>` to set up" : undefined,
26
+ });
27
+ // 3. Config file
28
+ const hasConfig = existsSync(CONFIG_PATH);
29
+ let configChecks = [];
30
+ if (hasConfig) {
31
+ const config = loadConfig();
32
+ configChecks = [
33
+ {
34
+ label: "License key",
35
+ ok: config.license_key != null,
36
+ detail: config.license_key ? `${config.license_key.slice(0, 8)}...` : "(not set)",
37
+ },
38
+ { label: "Machine ID", ok: true, detail: `${config.machine_id.slice(0, 12)}...` },
39
+ { label: "API URL", ok: true, detail: config.api_url },
40
+ ];
41
+ }
42
+ else {
43
+ configChecks = [
44
+ {
45
+ label: "Config file",
46
+ ok: false,
47
+ detail: CONFIG_PATH,
48
+ hint: "Run `forge activate <key>` to create",
49
+ },
50
+ ];
51
+ }
52
+ results.push(...configChecks);
53
+ // 4. Cache directory
54
+ if (existsSync(CACHE_DIR)) {
55
+ const cached = readdirSync(CACHE_DIR);
56
+ const totalSize = dirSize(CACHE_DIR);
57
+ results.push({
58
+ label: "Cache",
59
+ ok: true,
60
+ detail: `${cached.length} item(s), ${formatBytes(totalSize)}`,
61
+ });
62
+ }
63
+ else {
64
+ results.push({ label: "Cache", ok: true, detail: "empty (normal for fresh installs)" });
65
+ }
66
+ // 5. Claude Code plugin directory
67
+ const pluginDir = claudePluginDir();
68
+ results.push({
69
+ label: "Claude Code plugins",
70
+ ok: existsSync(pluginDir),
71
+ detail: pluginDir,
72
+ hint: !existsSync(pluginDir) ? "Make sure Claude Code is installed" : undefined,
73
+ });
74
+ // 6. Installed plugins integrity
75
+ const config = loadConfig();
76
+ for (const [name, info] of Object.entries(config.installed_plugins)) {
77
+ const pluginPath = join(pluginDir, name);
78
+ if (existsSync(pluginPath)) {
79
+ const hasManifest = existsSync(join(pluginPath, ".claude-plugin", "plugin.json"));
80
+ results.push({
81
+ label: `${name}@${info.version}`,
82
+ ok: hasManifest,
83
+ detail: hasManifest ? "intact" : "missing plugin.json",
84
+ hint: !hasManifest ? "Plugin may be corrupted, try reinstalling" : undefined,
85
+ });
86
+ }
87
+ else {
88
+ results.push({
89
+ label: `${name}@${info.version}`,
90
+ ok: false,
91
+ detail: "not found on disk",
92
+ hint: `Run \`forge install ${name}\` to reinstall`,
93
+ });
94
+ }
95
+ }
96
+ // 7. API connectivity
97
+ const apiUrl = hasConfig
98
+ ? config.api_url
99
+ : (process.env.FORGE_API_URL ?? "https://api.reumbra.com/velvet");
100
+ let apiOk = false;
101
+ try {
102
+ const res = await fetch(`${apiUrl}/health`, { signal: AbortSignal.timeout(25000) });
103
+ apiOk = res.ok;
104
+ }
105
+ catch {
106
+ // unreachable or timeout (Lambda cold starts can take ~20s)
107
+ }
108
+ results.push({
109
+ label: "API connectivity",
110
+ ok: apiOk,
111
+ detail: apiOk ? `${apiUrl} reachable` : `${apiUrl} unreachable`,
112
+ hint: !apiOk ? "Installed plugins work offline. API needed for install/update." : undefined,
113
+ });
114
+ // Render
115
+ const lines = [];
116
+ for (const r of results) {
117
+ const icon = r.ok ? `${green}✓${reset}` : `${yellow}!${reset}`;
118
+ lines.push(`${icon} ${bold}${r.label}${reset} ${dim}${r.detail}${reset}`);
119
+ if (r.hint) {
120
+ lines.push(` ${dim}${r.hint}${reset}`);
121
+ }
122
+ }
123
+ console.log(box(lines, { title: "Diagnostics" }));
124
+ const issues = results.filter((r) => !r.ok).length;
125
+ const checks = results.length;
126
+ log.plain("");
127
+ if (issues === 0) {
128
+ log.success(`All ${checks} checks passed!`);
129
+ }
130
+ else {
131
+ log.warn(`${issues} issue(s) found out of ${checks} checks.`);
132
+ }
133
+ return { checks, issues };
134
+ }
135
+ function dirSize(dir) {
136
+ let total = 0;
137
+ try {
138
+ for (const entry of readdirSync(dir)) {
139
+ const fullPath = join(dir, entry);
140
+ const stat = statSync(fullPath);
141
+ total += stat.isDirectory() ? dirSize(fullPath) : stat.size;
142
+ }
143
+ }
144
+ catch {
145
+ // Permission or read errors — skip
146
+ }
147
+ return total;
148
+ }
149
+ function formatBytes(bytes) {
150
+ if (bytes < 1024)
151
+ return `${bytes} B`;
152
+ if (bytes < 1024 * 1024)
153
+ return `${(bytes / 1024).toFixed(1)} KB`;
154
+ return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
155
+ }
156
+ //# sourceMappingURL=doctor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function install(pluginName: string, version?: string): Promise<void>;
@@ -0,0 +1,94 @@
1
+ import { cpSync, existsSync, mkdirSync, readdirSync, rmSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { ApiError, apiRequest, downloadFile } from "../lib/api.js";
4
+ import { loadConfig, saveConfig } from "../lib/config.js";
5
+ import { log } from "../lib/logger.js";
6
+ import { CACHE_DIR, claudePluginDir } from "../lib/paths.js";
7
+ import { bold, dim, green, reset } from "../lib/styles.js";
8
+ import { createSpinner } from "../lib/ui.js";
9
+ import { extractZip } from "../lib/zip.js";
10
+ export async function install(pluginName, version) {
11
+ const config = loadConfig();
12
+ if (!config.license_key) {
13
+ log.error("No license key configured. Run `forge activate <key>` first.");
14
+ process.exit(1);
15
+ }
16
+ // Normalize plugin name (allow shorthand: "core" → "forge-core")
17
+ const fullName = pluginName.startsWith("forge-") ? pluginName : `forge-${pluginName}`;
18
+ const versionLabel = version ? `@${version}` : "";
19
+ const spinner = createSpinner(`Requesting ${bold}${fullName}${reset}${versionLabel}...`);
20
+ try {
21
+ const result = await apiRequest(config, {
22
+ method: "POST",
23
+ path: "/plugins/download",
24
+ body: {
25
+ plugin_name: fullName,
26
+ ...(version ? { version } : {}),
27
+ },
28
+ });
29
+ // Download the zip
30
+ spinner.update(`Downloading ${bold}${fullName}@${result.version}${reset}...`);
31
+ const zipBuffer = await downloadFile(result.url);
32
+ // Extract to cache
33
+ spinner.update("Extracting...");
34
+ const cacheDir = join(CACHE_DIR, `${fullName}@${result.version}`);
35
+ if (existsSync(cacheDir)) {
36
+ rmSync(cacheDir, { recursive: true });
37
+ }
38
+ mkdirSync(cacheDir, { recursive: true });
39
+ await extractZip(zipBuffer, cacheDir);
40
+ // Link into Claude Code plugin directory
41
+ spinner.update("Installing into Claude Code...");
42
+ linkPlugin(fullName, cacheDir);
43
+ // Update config
44
+ config.installed_plugins[fullName] = {
45
+ version: result.version,
46
+ installed_at: new Date().toISOString(),
47
+ };
48
+ saveConfig(config);
49
+ spinner.stop(`${green}✓${reset} ${bold}${fullName}@${result.version}${reset} installed!`);
50
+ log.info(`${dim}Run the plugin setup command in your project to get started.${reset}`);
51
+ }
52
+ catch (err) {
53
+ spinner.stop();
54
+ if (err instanceof ApiError) {
55
+ if (err.code === "PLUGIN_NOT_IN_PLAN") {
56
+ log.error(`${fullName} is not available on your plan.`);
57
+ log.info("Upgrade at https://reumbra.dev/forge/pricing");
58
+ }
59
+ else if (err.code === "VERSION_NOT_FOUND") {
60
+ log.error(`Version ${version} not found for ${fullName}.`);
61
+ }
62
+ else if (err.code === "LICENSE_INACTIVE") {
63
+ log.error("Your license is inactive. Contact support.");
64
+ }
65
+ else {
66
+ log.error(err.message);
67
+ }
68
+ process.exit(1);
69
+ }
70
+ throw err;
71
+ }
72
+ }
73
+ function linkPlugin(pluginName, cacheDir) {
74
+ const destDir = join(claudePluginDir(), pluginName);
75
+ // Remove existing install
76
+ if (existsSync(destDir)) {
77
+ rmSync(destDir, { recursive: true });
78
+ }
79
+ // Find the plugin root inside the extracted zip
80
+ // Could be at root or nested one level (e.g., forge-core-1.0.0/)
81
+ const entries = readdirSync(cacheDir);
82
+ let sourceDir = cacheDir;
83
+ // If there's a single directory and it contains .claude-plugin/, use it
84
+ if (entries.length === 1) {
85
+ const nested = join(cacheDir, entries[0]);
86
+ if (existsSync(join(nested, ".claude-plugin"))) {
87
+ sourceDir = nested;
88
+ }
89
+ }
90
+ // Copy to Claude Code plugins directory
91
+ mkdirSync(destDir, { recursive: true });
92
+ cpSync(sourceDir, destDir, { recursive: true });
93
+ }
94
+ //# sourceMappingURL=install.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install.js","sourceRoot":"","sources":["../../src/commands/install.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function list(): Promise<void>;
@@ -0,0 +1,46 @@
1
+ import { ApiError, apiRequest } from "../lib/api.js";
2
+ import { loadConfig } from "../lib/config.js";
3
+ import { log } from "../lib/logger.js";
4
+ import { badge, banner, table } from "../lib/ui.js";
5
+ export async function list() {
6
+ const config = loadConfig();
7
+ if (!config.license_key) {
8
+ log.error("No license key configured. Run `forge activate <key>` first.");
9
+ process.exit(1);
10
+ }
11
+ try {
12
+ const result = await apiRequest(config, {
13
+ method: "GET",
14
+ path: "/plugins/list",
15
+ });
16
+ console.log(`\n${banner()}\n`);
17
+ if (result.plugins.length === 0) {
18
+ log.info("No plugins available for your plan.");
19
+ return;
20
+ }
21
+ const rows = result.plugins.map((plugin) => {
22
+ const installed = config.installed_plugins[plugin.name];
23
+ let status;
24
+ if (installed) {
25
+ status =
26
+ installed.version === plugin.current_version
27
+ ? badge("✓ up to date", "success")
28
+ : badge(`↑ ${installed.version} → ${plugin.current_version}`, "warning");
29
+ }
30
+ else {
31
+ status = badge("not installed", "neutral");
32
+ }
33
+ const version = plugin.current_version ? `v${plugin.current_version}` : "—";
34
+ return [plugin.name, version, status, plugin.description];
35
+ });
36
+ console.log(table(rows, { header: ["Plugin", "Version", "Status", "Description"] }));
37
+ }
38
+ catch (err) {
39
+ if (err instanceof ApiError) {
40
+ log.error(err.message);
41
+ process.exit(1);
42
+ }
43
+ throw err;
44
+ }
45
+ }
46
+ //# sourceMappingURL=list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.js","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAGpD,MAAM,CAAC,KAAK,UAAU,IAAI;IACxB,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAE5B,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;QACxB,GAAG,CAAC,KAAK,CAAC,8DAA8D,CAAC,CAAC;QAC1E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,UAAU,CAAe,MAAM,EAAE;YACpD,MAAM,EAAE,KAAK;YACb,IAAI,EAAE,eAAe;SACtB,CAAC,CAAC;QAEH,OAAO,CAAC,GAAG,CAAC,KAAK,MAAM,EAAE,IAAI,CAAC,CAAC;QAE/B,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAChC,GAAG,CAAC,IAAI,CAAC,qCAAqC,CAAC,CAAC;YAChD,OAAO;QACT,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE;YACzC,MAAM,SAAS,GAAG,MAAM,CAAC,iBAAiB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YACxD,IAAI,MAAc,CAAC;YACnB,IAAI,SAAS,EAAE,CAAC;gBACd,MAAM;oBACJ,SAAS,CAAC,OAAO,KAAK,MAAM,CAAC,eAAe;wBAC1C,CAAC,CAAC,KAAK,CAAC,cAAc,EAAE,SAAS,CAAC;wBAClC,CAAC,CAAC,KAAK,CAAC,KAAK,SAAS,CAAC,OAAO,MAAM,MAAM,CAAC,eAAe,EAAE,EAAE,SAAS,CAAC,CAAC;YAC/E,CAAC;iBAAM,CAAC;gBACN,MAAM,GAAG,KAAK,CAAC,eAAe,EAAE,SAAS,CAAC,CAAC;YAC7C,CAAC;YACD,MAAM,OAAO,GAAG,MAAM,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;YAC5E,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC;QAC5D,CAAC,CAAC,CAAC;QAEH,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,CAAC,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,aAAa,CAAC,EAAE,CAAC,CAAC,CAAC;IACvF,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,QAAQ,EAAE,CAAC;YAC5B,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACvB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function status(): Promise<void>;
@@ -0,0 +1,75 @@
1
+ import { ApiError, apiRequest } from "../lib/api.js";
2
+ import { loadConfig } from "../lib/config.js";
3
+ import { log } from "../lib/logger.js";
4
+ import { bold, dim, green, red, reset, yellow } from "../lib/styles.js";
5
+ import { badge, box, statusBadge, table } from "../lib/ui.js";
6
+ export async function status() {
7
+ const config = loadConfig();
8
+ if (!config.license_key) {
9
+ log.error("No license key configured. Run `forge activate <key>` first.");
10
+ process.exit(1);
11
+ }
12
+ try {
13
+ const result = await apiRequest(config, {
14
+ method: "GET",
15
+ path: "/auth/status",
16
+ query: {
17
+ license_key: config.license_key,
18
+ machine_id: config.machine_id,
19
+ },
20
+ });
21
+ const lic = result.license;
22
+ const expires = new Date(lic.expires_at);
23
+ const daysLeft = Math.ceil((expires.getTime() - Date.now()) / (1000 * 60 * 60 * 24));
24
+ // Determine status
25
+ let licStatus;
26
+ if (!lic.is_active)
27
+ licStatus = "inactive";
28
+ else if (daysLeft <= 0)
29
+ licStatus = "expired";
30
+ else if (daysLeft <= 14)
31
+ licStatus = "expiring";
32
+ else
33
+ licStatus = "active";
34
+ const expiryColor = daysLeft <= 0 ? red : daysLeft <= 14 ? yellow : green;
35
+ // License box
36
+ console.log(box([
37
+ `${bold}Plan:${reset} ${lic.plan}`,
38
+ `${bold}Email:${reset} ${lic.email}`,
39
+ `${bold}Status:${reset} ${statusBadge(licStatus)}`,
40
+ `${bold}Expires:${reset} ${expiryColor}${expires.toLocaleDateString()}${reset} ${dim}(${daysLeft}d left)${reset}`,
41
+ `${bold}Machines:${reset} ${lic.machines.length} registered`,
42
+ ], { title: "License", borderColor: dim }));
43
+ // Machines
44
+ if (lic.machines.length > 0) {
45
+ const machineRows = lic.machines.map((m) => {
46
+ const current = m.machine_id === config.machine_id;
47
+ return [
48
+ `${m.machine_id.slice(0, 16)}...`,
49
+ current ? badge("this machine", "info") : dim + (m.label ?? "—") + reset,
50
+ dim + new Date(m.activated_at).toLocaleDateString() + reset,
51
+ ];
52
+ });
53
+ console.log(table(machineRows, { header: ["Machine", "Label", "Activated"] }));
54
+ }
55
+ // Plugins
56
+ if (lic.allowed_plugins.length > 0) {
57
+ const pluginRows = lic.allowed_plugins.map((name) => {
58
+ const installed = config.installed_plugins[name];
59
+ const stat = installed
60
+ ? badge(`v${installed.version}`, "success")
61
+ : badge("not installed", "neutral");
62
+ return [name, stat];
63
+ });
64
+ console.log(table(pluginRows, { header: ["Plugin", "Status"] }));
65
+ }
66
+ }
67
+ catch (err) {
68
+ if (err instanceof ApiError) {
69
+ log.error(err.message);
70
+ process.exit(1);
71
+ }
72
+ throw err;
73
+ }
74
+ }
75
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function uninstall(pluginName: string): void;