@opentabs-dev/cli 0.0.1

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 (57) hide show
  1. package/dist/cli.d.ts +3 -0
  2. package/dist/cli.d.ts.map +1 -0
  3. package/dist/cli.js +26 -0
  4. package/dist/cli.js.map +1 -0
  5. package/dist/commands/build.d.ts +10 -0
  6. package/dist/commands/build.d.ts.map +1 -0
  7. package/dist/commands/build.js +285 -0
  8. package/dist/commands/build.js.map +1 -0
  9. package/dist/commands/config.d.ts +7 -0
  10. package/dist/commands/config.d.ts.map +1 -0
  11. package/dist/commands/config.js +157 -0
  12. package/dist/commands/config.js.map +1 -0
  13. package/dist/commands/dev.d.ts +10 -0
  14. package/dist/commands/dev.d.ts.map +1 -0
  15. package/dist/commands/dev.js +128 -0
  16. package/dist/commands/dev.js.map +1 -0
  17. package/dist/commands/doctor.d.ts +7 -0
  18. package/dist/commands/doctor.d.ts.map +1 -0
  19. package/dist/commands/doctor.js +212 -0
  20. package/dist/commands/doctor.js.map +1 -0
  21. package/dist/commands/index.d.ts +10 -0
  22. package/dist/commands/index.d.ts.map +1 -0
  23. package/dist/commands/index.js +10 -0
  24. package/dist/commands/index.js.map +1 -0
  25. package/dist/commands/logs.d.ts +10 -0
  26. package/dist/commands/logs.d.ts.map +1 -0
  27. package/dist/commands/logs.js +103 -0
  28. package/dist/commands/logs.js.map +1 -0
  29. package/dist/commands/plugin.d.ts +6 -0
  30. package/dist/commands/plugin.d.ts.map +1 -0
  31. package/dist/commands/plugin.js +199 -0
  32. package/dist/commands/plugin.js.map +1 -0
  33. package/dist/commands/reload.d.ts +7 -0
  34. package/dist/commands/reload.d.ts.map +1 -0
  35. package/dist/commands/reload.js +88 -0
  36. package/dist/commands/reload.js.map +1 -0
  37. package/dist/commands/setup.d.ts +6 -0
  38. package/dist/commands/setup.d.ts.map +1 -0
  39. package/dist/commands/setup.js +70 -0
  40. package/dist/commands/setup.js.map +1 -0
  41. package/dist/commands/status.d.ts +7 -0
  42. package/dist/commands/status.d.ts.map +1 -0
  43. package/dist/commands/status.js +108 -0
  44. package/dist/commands/status.js.map +1 -0
  45. package/dist/config.d.ts +11 -0
  46. package/dist/config.d.ts.map +1 -0
  47. package/dist/config.js +37 -0
  48. package/dist/config.js.map +1 -0
  49. package/dist/parse-port.d.ts +15 -0
  50. package/dist/parse-port.d.ts.map +1 -0
  51. package/dist/parse-port.js +32 -0
  52. package/dist/parse-port.js.map +1 -0
  53. package/dist/scaffold.d.ts +21 -0
  54. package/dist/scaffold.d.ts.map +1 -0
  55. package/dist/scaffold.js +273 -0
  56. package/dist/scaffold.js.map +1 -0
  57. package/package.json +33 -0
@@ -0,0 +1,199 @@
1
+ /**
2
+ * `opentabs plugin` command — manage plugins (list, add, remove, create).
3
+ */
4
+ import { getConfigPath, getPluginsFromConfig, readConfig, resolvePluginPath } from '../config.js';
5
+ import { scaffoldPlugin, ScaffoldError } from '../scaffold.js';
6
+ import pc from 'picocolors';
7
+ import { existsSync, mkdirSync } from 'node:fs';
8
+ import { dirname, join, relative, resolve } from 'node:path';
9
+ const readManifest = async (resolvedPath) => {
10
+ const manifestPath = join(resolvedPath, 'opentabs-plugin.json');
11
+ if (!existsSync(manifestPath))
12
+ return null;
13
+ try {
14
+ const data = await Bun.file(manifestPath).json();
15
+ if (data !== null && typeof data === 'object' && 'name' in data && 'version' in data && 'tools' in data) {
16
+ const d = data;
17
+ return { name: d.name, version: d.version, toolCount: Array.isArray(d.tools) ? d.tools.length : 0 };
18
+ }
19
+ return null;
20
+ }
21
+ catch {
22
+ return null;
23
+ }
24
+ };
25
+ const handlePluginList = async (options) => {
26
+ const configPath = getConfigPath();
27
+ const config = await readConfig(configPath);
28
+ if (!config) {
29
+ console.error(pc.red(`No config found at ${configPath}`));
30
+ console.error('Run opentabs dev to create one automatically.');
31
+ process.exit(1);
32
+ }
33
+ const plugins = getPluginsFromConfig(config);
34
+ if (plugins.length === 0) {
35
+ console.log('No plugins configured.');
36
+ console.log('Add one with: opentabs plugin add <path>');
37
+ return;
38
+ }
39
+ if (options.json) {
40
+ const entries = await Promise.all(plugins.map(async (pluginPath) => {
41
+ const resolvedPath = resolvePluginPath(pluginPath, configPath);
42
+ const exists = existsSync(resolvedPath);
43
+ const manifest = exists ? await readManifest(resolvedPath) : null;
44
+ return {
45
+ path: pluginPath,
46
+ resolvedPath,
47
+ exists,
48
+ hasManifest: manifest !== null,
49
+ name: manifest?.name,
50
+ version: manifest?.version,
51
+ toolCount: manifest?.toolCount,
52
+ };
53
+ }));
54
+ console.log(JSON.stringify(entries, null, 2));
55
+ return;
56
+ }
57
+ console.log('Configured plugins:');
58
+ console.log('');
59
+ for (const pluginPath of plugins) {
60
+ const resolvedPath = resolvePluginPath(pluginPath, configPath);
61
+ const exists = existsSync(resolvedPath);
62
+ const manifest = exists ? await readManifest(resolvedPath) : null;
63
+ if (manifest) {
64
+ const indicator = pc.green('+');
65
+ const name = pc.bold(manifest.name);
66
+ const version = pc.dim(`v${manifest.version}`);
67
+ const tools = pc.dim(`${manifest.toolCount} tool${manifest.toolCount === 1 ? '' : 's'}`);
68
+ console.log(` ${indicator} ${name} ${version} ${tools} ${pc.dim(pluginPath)}`);
69
+ }
70
+ else if (exists) {
71
+ console.log(` ${pc.yellow('~')} ${pluginPath} ${pc.yellow('(not built)')}`);
72
+ }
73
+ else {
74
+ console.log(` ${pc.red('!')} ${pluginPath} ${pc.red('(not found)')}`);
75
+ }
76
+ }
77
+ console.log('');
78
+ console.log(` ${pc.green('+')} ready ${pc.yellow('~')} no manifest ${pc.red('!')} not found`);
79
+ };
80
+ const handlePluginAdd = async (pathArg) => {
81
+ const configPath = getConfigPath();
82
+ const configDir = dirname(configPath);
83
+ const existing = await readConfig(configPath);
84
+ let config;
85
+ if (existing) {
86
+ config = existing;
87
+ }
88
+ else {
89
+ mkdirSync(configDir, { recursive: true });
90
+ config = { plugins: [], tools: {}, secret: crypto.randomUUID() };
91
+ }
92
+ if (!Array.isArray(config.plugins))
93
+ config.plugins = [];
94
+ const plugins = config.plugins;
95
+ // Resolve the new path to an absolute path (relative paths resolve against CWD)
96
+ const resolvedNew = resolve(pathArg);
97
+ // Normalize to a relative-to-config-dir form for portable storage
98
+ const normalizedNew = relative(configDir, resolvedNew);
99
+ // Check for duplicates by comparing resolved absolute paths
100
+ const isDuplicate = plugins.some(existing => resolvePluginPath(existing, configPath) === resolvedNew);
101
+ if (isDuplicate) {
102
+ console.log('Plugin path already configured.');
103
+ return;
104
+ }
105
+ if (!existsSync(resolvedNew)) {
106
+ console.warn(pc.yellow(`Warning: Path does not exist: ${normalizedNew}`));
107
+ }
108
+ plugins.push(normalizedNew);
109
+ await Bun.write(configPath, JSON.stringify(config, null, 2) + '\n');
110
+ console.log(pc.green(`Added: ${normalizedNew}`));
111
+ console.log('Restart the MCP server to pick up the new plugin.');
112
+ };
113
+ const handlePluginRemove = async (nameOrPath) => {
114
+ const configPath = getConfigPath();
115
+ const config = await readConfig(configPath);
116
+ if (!config) {
117
+ console.error(pc.red(`No config found at ${configPath}`));
118
+ console.error('Run opentabs dev to create one automatically.');
119
+ process.exit(1);
120
+ }
121
+ if (!Array.isArray(config.plugins))
122
+ config.plugins = [];
123
+ const plugins = config.plugins;
124
+ const idx = plugins.findIndex(p => p === nameOrPath || p.endsWith('/' + nameOrPath) || p.endsWith('\\' + nameOrPath));
125
+ if (idx === -1) {
126
+ console.error(pc.red('Plugin not found in config.'));
127
+ console.error('Run opentabs plugin list to see configured plugins.');
128
+ process.exit(1);
129
+ }
130
+ const removed = plugins.splice(idx, 1)[0];
131
+ await Bun.write(configPath, JSON.stringify(config, null, 2) + '\n');
132
+ console.log(pc.green(`Removed: ${removed}`));
133
+ console.log('Restart the MCP server to pick up the change.');
134
+ };
135
+ // --- Command registration ---
136
+ export const registerPluginCommand = (program) => {
137
+ const pluginCmd = program
138
+ .command('plugin')
139
+ .description('Manage plugins (create, list, add, remove)')
140
+ .action(() => {
141
+ pluginCmd.help();
142
+ });
143
+ pluginCmd
144
+ .command('create')
145
+ .description('Scaffold a new plugin project')
146
+ .argument('<name>', 'Plugin name (lowercase alphanumeric + hyphens)')
147
+ .requiredOption('--domain <domain>', 'Target domain (e.g., .slack.com or github.com)')
148
+ .option('--display <name>', 'Display name (e.g., Slack)')
149
+ .option('--description <desc>', 'Plugin description')
150
+ .addHelpText('after', `
151
+ Examples:
152
+ $ opentabs plugin create my-plugin --domain .example.com
153
+ $ opentabs plugin create slack --domain .slack.com --display Slack`)
154
+ .action(async (name, options) => {
155
+ try {
156
+ await scaffoldPlugin({
157
+ name,
158
+ domain: options.domain,
159
+ display: options.display,
160
+ description: options.description,
161
+ });
162
+ }
163
+ catch (err) {
164
+ if (err instanceof ScaffoldError) {
165
+ console.error(pc.red(`Error: ${err.message}`));
166
+ process.exit(1);
167
+ }
168
+ throw err;
169
+ }
170
+ });
171
+ pluginCmd
172
+ .command('list')
173
+ .description('List configured plugins and their status')
174
+ .option('--json', 'Output plugin info as JSON')
175
+ .addHelpText('after', `
176
+ Examples:
177
+ $ opentabs plugin list
178
+ $ opentabs plugin list --json`)
179
+ .action((options) => handlePluginList(options));
180
+ pluginCmd
181
+ .command('add')
182
+ .description('Add a plugin path to the config')
183
+ .argument('<path>', 'Path to the plugin directory')
184
+ .addHelpText('after', `
185
+ Examples:
186
+ $ opentabs plugin add ./my-plugin
187
+ $ opentabs plugin add /absolute/path/to/plugin`)
188
+ .action((pathArg) => handlePluginAdd(pathArg));
189
+ pluginCmd
190
+ .command('remove')
191
+ .description('Remove a plugin path from the config')
192
+ .argument('<path-or-name>', 'Exact path or plugin directory name to match')
193
+ .addHelpText('after', `
194
+ Examples:
195
+ $ opentabs plugin remove ./my-plugin
196
+ $ opentabs plugin remove my-plugin`)
197
+ .action((nameOrPath) => handlePluginRemove(nameOrPath));
198
+ };
199
+ //# sourceMappingURL=plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.js","sourceRoot":"","sources":["../../src/commands/plugin.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * `opentabs reload` command — triggers server config/plugin rediscovery or extension reload.
3
+ */
4
+ import type { Command } from 'commander';
5
+ declare const registerReloadCommand: (program: Command) => void;
6
+ export { registerReloadCommand };
7
+ //# sourceMappingURL=reload.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reload.d.ts","sourceRoot":"","sources":["../../src/commands/reload.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA2EzC,QAAA,MAAM,qBAAqB,GAAI,SAAS,OAAO,KAAG,IAejD,CAAC;AAEF,OAAO,EAAE,qBAAqB,EAAE,CAAC"}
@@ -0,0 +1,88 @@
1
+ /**
2
+ * `opentabs reload` command — triggers server config/plugin rediscovery or extension reload.
3
+ */
4
+ import { isConnectionRefused } from '../config.js';
5
+ import { parsePort, resolvePort } from '../parse-port.js';
6
+ import pc from 'picocolors';
7
+ const handleReload = async (options) => {
8
+ const port = resolvePort(options);
9
+ if (options.extension) {
10
+ await reloadExtension(port);
11
+ }
12
+ else {
13
+ await reloadServer(port);
14
+ }
15
+ };
16
+ const reloadServer = async (port) => {
17
+ const url = `http://localhost:${port}/reload`;
18
+ try {
19
+ const res = await fetch(url, { method: 'POST', signal: AbortSignal.timeout(10_000) });
20
+ const data = (await res.json());
21
+ if (data.ok) {
22
+ console.log(pc.green('Server reloaded successfully'));
23
+ if (data.plugins !== undefined && data.durationMs !== undefined) {
24
+ console.log(pc.dim(` ${data.plugins} plugin(s) discovered in ${data.durationMs}ms`));
25
+ }
26
+ }
27
+ else {
28
+ console.error(pc.red(`Reload failed: ${data.error ?? 'unknown error'}`));
29
+ process.exit(1);
30
+ }
31
+ }
32
+ catch (err) {
33
+ if (isConnectionRefused(err)) {
34
+ console.error(pc.red('Server not running'));
35
+ const portSuffix = port !== 9515 ? ` --port ${port}` : '';
36
+ console.error(pc.dim(`Start it with: opentabs dev${portSuffix}`));
37
+ }
38
+ else {
39
+ const message = err instanceof Error ? err.message : String(err);
40
+ console.error(pc.red(`Error: ${message}`));
41
+ }
42
+ process.exit(1);
43
+ }
44
+ };
45
+ const reloadExtension = async (port) => {
46
+ const url = `http://localhost:${port}/extension/reload`;
47
+ try {
48
+ const res = await fetch(url, { method: 'POST', signal: AbortSignal.timeout(5_000) });
49
+ const data = (await res.json());
50
+ if (data.ok) {
51
+ console.log(pc.green('Extension reload signal sent'));
52
+ if (data.message) {
53
+ console.log(pc.dim(` ${data.message}`));
54
+ }
55
+ }
56
+ else {
57
+ console.error(pc.red(`Extension reload failed: ${data.error ?? 'unknown error'}`));
58
+ process.exit(1);
59
+ }
60
+ }
61
+ catch (err) {
62
+ if (isConnectionRefused(err)) {
63
+ console.error(pc.red('Server not running'));
64
+ const portSuffix = port !== 9515 ? ` --port ${port}` : '';
65
+ console.error(pc.dim(`Start it with: opentabs dev${portSuffix}`));
66
+ }
67
+ else {
68
+ const message = err instanceof Error ? err.message : String(err);
69
+ console.error(pc.red(`Error: ${message}`));
70
+ }
71
+ process.exit(1);
72
+ }
73
+ };
74
+ const registerReloadCommand = (program) => {
75
+ program
76
+ .command('reload')
77
+ .description('Reload server config/plugins or trigger extension reload')
78
+ .option('--port <number>', 'MCP server port (default: 9515)', parsePort)
79
+ .option('--extension', 'Reload the Chrome extension instead of server config')
80
+ .addHelpText('after', `
81
+ Examples:
82
+ $ opentabs reload # Reload server config and plugins
83
+ $ opentabs reload --extension # Reload the Chrome extension
84
+ $ opentabs reload --port 3000 # Reload server on custom port`)
85
+ .action((_options, command) => handleReload(command.optsWithGlobals()));
86
+ };
87
+ export { registerReloadCommand };
88
+ //# sourceMappingURL=reload.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reload.js","sourceRoot":"","sources":["../../src/commands/reload.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * `opentabs setup` command — copies the browser extension to ~/.opentabs/extension/.
3
+ */
4
+ import type { Command } from 'commander';
5
+ export declare const registerSetupCommand: (program: Command) => void;
6
+ //# sourceMappingURL=setup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/commands/setup.ts"],"names":[],"mappings":"AAAA;;GAEG;AAQH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA+DzC,eAAO,MAAM,oBAAoB,GAAI,SAAS,OAAO,KAAG,IAWvD,CAAC"}
@@ -0,0 +1,70 @@
1
+ /**
2
+ * `opentabs setup` command — copies the browser extension to ~/.opentabs/extension/.
3
+ */
4
+ import { EXTENSION_COPY_EXCLUDE_PATTERN } from '@opentabs-dev/shared';
5
+ import pc from 'picocolors';
6
+ import { cpSync, existsSync, mkdirSync } from 'node:fs';
7
+ import { homedir } from 'node:os';
8
+ import { resolve, join, dirname, relative } from 'node:path';
9
+ import { fileURLToPath } from 'node:url';
10
+ const resolveExtensionDir = () => {
11
+ try {
12
+ return dirname(fileURLToPath(import.meta.resolve('@opentabs-dev/browser-extension/package.json')));
13
+ }
14
+ catch {
15
+ const cliDir = dirname(fileURLToPath(import.meta.url));
16
+ return resolve(cliDir, '..', '..', '..', 'browser-extension');
17
+ }
18
+ };
19
+ const handleSetup = async () => {
20
+ const extensionSrc = resolveExtensionDir();
21
+ // Verify the extension source exists
22
+ if (!(await Bun.file(join(extensionSrc, 'manifest.json')).exists())) {
23
+ console.error(pc.red(`Error: Browser extension not found at ${extensionSrc}`));
24
+ console.error('Run bun run build from the project root to build the extension.');
25
+ process.exit(1);
26
+ }
27
+ // Read the CLI package version
28
+ const cliPkgPath = join(dirname(fileURLToPath(import.meta.url)), '..', '..', 'package.json');
29
+ const pkgJson = JSON.parse(await Bun.file(cliPkgPath).text());
30
+ const version = pkgJson.version;
31
+ const extensionDest = join(homedir(), '.opentabs', 'extension');
32
+ const isUpdate = existsSync(extensionDest);
33
+ if (isUpdate) {
34
+ console.log(pc.dim('Updating existing installation...'));
35
+ }
36
+ // Copy extension directory, skipping node_modules, src, .git, tsconfig*
37
+ cpSync(extensionSrc, extensionDest, {
38
+ recursive: true,
39
+ force: true,
40
+ filter: (source) => {
41
+ const rel = relative(extensionSrc, source);
42
+ return rel === '' || !EXTENSION_COPY_EXCLUDE_PATTERN.test(rel);
43
+ },
44
+ });
45
+ // Create adapters directory for plugins
46
+ mkdirSync(join(extensionDest, 'adapters'), { recursive: true });
47
+ // Write version marker
48
+ await Bun.write(join(extensionDest, '.opentabs-version'), version);
49
+ // Verify installation
50
+ if (!existsSync(join(extensionDest, 'manifest.json'))) {
51
+ console.error(pc.red('Error: Installation verification failed — manifest.json missing from destination.'));
52
+ process.exit(1);
53
+ }
54
+ console.log(pc.green(`Extension installed to ${extensionDest} (v${version})`));
55
+ console.log('');
56
+ console.log('To load the extension in Chrome:');
57
+ console.log(` 1. Open ${pc.cyan('chrome://extensions/')}`);
58
+ console.log(` 2. Enable "Developer mode" (top-right toggle)`);
59
+ console.log(` 3. Click "Load unpacked" and select: ${pc.cyan(extensionDest)}`);
60
+ };
61
+ export const registerSetupCommand = (program) => {
62
+ program
63
+ .command('setup')
64
+ .description('Install the browser extension to ~/.opentabs/')
65
+ .addHelpText('after', `
66
+ Examples:
67
+ $ opentabs setup`)
68
+ .action(() => handleSetup());
69
+ };
70
+ //# sourceMappingURL=setup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup.js","sourceRoot":"","sources":["../../src/commands/setup.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,8BAA8B,EAAE,MAAM,sBAAsB,CAAC;AACtE,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACxD,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAGzC,MAAM,mBAAmB,GAAG,GAAW,EAAE;IACvC,IAAI,CAAC;QACH,OAAO,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,8CAA8C,CAAC,CAAC,CAAC,CAAC;IACrG,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QACvD,OAAO,OAAO,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,mBAAmB,CAAC,CAAC;IAChE,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,WAAW,GAAG,KAAK,IAAmB,EAAE;IAC5C,MAAM,YAAY,GAAG,mBAAmB,EAAE,CAAC;IAE3C,qCAAqC;IACrC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,eAAe,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC;QACpE,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,yCAAyC,YAAY,EAAE,CAAC,CAAC,CAAC;QAC/E,OAAO,CAAC,KAAK,CAAC,iEAAiE,CAAC,CAAC;QACjF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,+BAA+B;IAC/B,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,cAAc,CAAC,CAAC;IAC7F,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,IAAI,EAAE,CAAwB,CAAC;IACrF,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAEhC,MAAM,aAAa,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,WAAW,EAAE,WAAW,CAAC,CAAC;IAChE,MAAM,QAAQ,GAAG,UAAU,CAAC,aAAa,CAAC,CAAC;IAE3C,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAC,CAAC;IAC3D,CAAC;IAED,wEAAwE;IACxE,MAAM,CAAC,YAAY,EAAE,aAAa,EAAE;QAClC,SAAS,EAAE,IAAI;QACf,KAAK,EAAE,IAAI;QACX,MAAM,EAAE,CAAC,MAAc,EAAE,EAAE;YACzB,MAAM,GAAG,GAAG,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;YAC3C,OAAO,GAAG,KAAK,EAAE,IAAI,CAAC,8BAA8B,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACjE,CAAC;KACF,CAAC,CAAC;IAEH,wCAAwC;IACxC,SAAS,CAAC,IAAI,CAAC,aAAa,EAAE,UAAU,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAEhE,uBAAuB;IACvB,MAAM,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,EAAE,mBAAmB,CAAC,EAAE,OAAO,CAAC,CAAC;IAEnE,sBAAsB;IACtB,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,aAAa,EAAE,eAAe,CAAC,CAAC,EAAE,CAAC;QACtD,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,mFAAmF,CAAC,CAAC,CAAC;QAC3G,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,0BAA0B,aAAa,MAAM,OAAO,GAAG,CAAC,CAAC,CAAC;IAC/E,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;IAChD,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC,IAAI,CAAC,sBAAsB,CAAC,EAAE,CAAC,CAAC;IAC5D,OAAO,CAAC,GAAG,CAAC,iDAAiD,CAAC,CAAC;IAC/D,OAAO,CAAC,GAAG,CAAC,0CAA0C,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC;AAClF,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,OAAgB,EAAQ,EAAE;IAC7D,OAAO;SACJ,OAAO,CAAC,OAAO,CAAC;SAChB,WAAW,CAAC,+CAA+C,CAAC;SAC5D,WAAW,CACV,OAAO,EACP;;mBAEa,CACd;SACA,MAAM,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC;AACjC,CAAC,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * `opentabs status` command — shows server status and connected plugins.
3
+ */
4
+ import type { Command } from 'commander';
5
+ declare const registerStatusCommand: (program: Command) => void;
6
+ export { registerStatusCommand };
7
+ //# sourceMappingURL=status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAqGzC,QAAA,MAAM,qBAAqB,GAAI,SAAS,OAAO,KAAG,IAejD,CAAC;AAEF,OAAO,EAAE,qBAAqB,EAAE,CAAC"}
@@ -0,0 +1,108 @@
1
+ /**
2
+ * `opentabs status` command — shows server status and connected plugins.
3
+ */
4
+ import { isConnectionRefused } from '../config.js';
5
+ import { parsePort, resolvePort } from '../parse-port.js';
6
+ import pc from 'picocolors';
7
+ const pad = (label) => ` ${pc.cyan(label.padEnd(14))}`;
8
+ const formatUptime = (seconds) => {
9
+ if (seconds < 60)
10
+ return `${seconds}s`;
11
+ const minutes = Math.floor(seconds / 60);
12
+ const secs = seconds % 60;
13
+ if (minutes < 60)
14
+ return `${minutes}m ${secs}s`;
15
+ const hours = Math.floor(minutes / 60);
16
+ const mins = minutes % 60;
17
+ if (hours < 24)
18
+ return `${hours}h ${mins}m`;
19
+ const days = Math.floor(hours / 24);
20
+ const hrs = hours % 24;
21
+ return `${days}d ${hrs}h`;
22
+ };
23
+ const colorTabState = (tabState) => {
24
+ if (tabState === 'ready')
25
+ return pc.green(tabState);
26
+ if (tabState === 'unavailable')
27
+ return pc.yellow(tabState);
28
+ return pc.dim(tabState);
29
+ };
30
+ const isTimeout = (err) => err instanceof DOMException && err.name === 'TimeoutError';
31
+ const handleStatus = async (options) => {
32
+ const port = resolvePort(options);
33
+ const url = `http://localhost:${port}/health`;
34
+ try {
35
+ const res = await fetch(url, { signal: AbortSignal.timeout(3_000) });
36
+ if (!res.ok) {
37
+ console.error(pc.red(`Error: MCP server returned HTTP ${res.status}.`));
38
+ console.error('The server may be misconfigured. Check the server logs for details.');
39
+ process.exit(1);
40
+ }
41
+ const data = (await res.json());
42
+ if (options.json) {
43
+ console.log(JSON.stringify(data, null, 2));
44
+ }
45
+ else {
46
+ const mcpClients = Number(data.mcpClients) || 0;
47
+ const plugins = Number(data.plugins) || 0;
48
+ const toolCount = Number(data.toolCount) || 0;
49
+ const uptime = Number(data.uptime) || 0;
50
+ const pluginDetails = Array.isArray(data.pluginDetails) ? data.pluginDetails : [];
51
+ console.log(pc.bold('OpenTabs MCP Server'));
52
+ console.log(`${pad('Status')}${pc.green('running')}`);
53
+ console.log(`${pad('Version')}${String(data.version)}`);
54
+ console.log(`${pad('Port')}${String(port)}`);
55
+ console.log(`${pad('Uptime')}${formatUptime(uptime)}`);
56
+ console.log(`${pad('Extension')}${data.extensionConnected ? pc.green('connected') : pc.yellow('not connected')}`);
57
+ console.log(`${pad('MCP clients')}${mcpClients > 0 ? pc.green(String(mcpClients)) : pc.dim('0')}`);
58
+ console.log(`${pad('Plugins')}${plugins > 0 ? pc.green(String(plugins)) : pc.yellow('0')}`);
59
+ console.log(`${pad('Tools')}${toolCount > 0 ? pc.green(String(toolCount)) : pc.dim('0')}`);
60
+ console.log(`${pad('Reloads')}${String(data.reloadCount)}`);
61
+ if (pluginDetails.length > 0) {
62
+ console.log('');
63
+ console.log(pc.bold(' Plugins'));
64
+ for (const p of pluginDetails) {
65
+ const state = colorTabState(p.tabState);
66
+ const tools = pc.dim(`${p.toolCount} tool${p.toolCount === 1 ? '' : 's'}`);
67
+ console.log(` ${p.displayName} ${pc.dim('—')} ${state} ${pc.dim('·')} ${tools}`);
68
+ }
69
+ }
70
+ }
71
+ }
72
+ catch (err) {
73
+ const startHint = `Start it with: opentabs dev${port !== 9515 ? ` --port ${port}` : ''}`;
74
+ if (isConnectionRefused(err)) {
75
+ console.error(pc.red('Server not running'));
76
+ console.error(pc.dim(startHint));
77
+ }
78
+ else if (isTimeout(err)) {
79
+ console.error(pc.red('Server not responding (timed out after 3s)'));
80
+ console.error(pc.dim(`The server at port ${port} did not respond in time.`));
81
+ }
82
+ else if (err instanceof SyntaxError) {
83
+ console.error(pc.red('Server returned invalid response'));
84
+ console.error(pc.dim('The health endpoint did not return valid JSON.'));
85
+ }
86
+ else {
87
+ const message = err instanceof Error ? err.message : String(err);
88
+ console.error(pc.red(`Error: ${message}`));
89
+ console.error(pc.dim(startHint));
90
+ }
91
+ process.exit(1);
92
+ }
93
+ };
94
+ const registerStatusCommand = (program) => {
95
+ program
96
+ .command('status')
97
+ .description('Show server status and connected plugins')
98
+ .option('--port <number>', 'Server port to check (default: 9515)', parsePort)
99
+ .option('--json', 'Output raw JSON from the health endpoint')
100
+ .addHelpText('after', `
101
+ Examples:
102
+ $ opentabs status
103
+ $ opentabs status --json
104
+ $ opentabs status --port 3000`)
105
+ .action((_options, command) => handleStatus(command.optsWithGlobals()));
106
+ };
107
+ export { registerStatusCommand };
108
+ //# 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,11 @@
1
+ /**
2
+ * Config file helpers shared across CLI commands.
3
+ */
4
+ export declare const getConfigDir: () => string;
5
+ export declare const getConfigPath: () => string;
6
+ export declare const getLogFilePath: () => string;
7
+ export declare const readConfig: (configPath: string) => Promise<Record<string, unknown> | null>;
8
+ export declare const getPluginsFromConfig: (config: Record<string, unknown>) => string[];
9
+ export declare const resolvePluginPath: (pluginPath: string, configPath: string) => string;
10
+ export declare const isConnectionRefused: (err: unknown) => boolean;
11
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,eAAO,MAAM,YAAY,QAAO,MAAqE,CAAC;AAEtG,eAAO,MAAM,aAAa,QAAO,MAA6C,CAAC;AAE/E,eAAO,MAAM,cAAc,QAAO,MAA4C,CAAC;AAE/E,eAAO,MAAM,UAAU,GAAU,YAAY,MAAM,KAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAoB3F,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAAI,QAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,MAAM,EACyC,CAAC;AAEvH,eAAO,MAAM,iBAAiB,GAAI,YAAY,MAAM,EAAE,YAAY,MAAM,KAAG,MACK,CAAC;AAEjF,eAAO,MAAM,mBAAmB,GAAI,KAAK,OAAO,KAAG,OAIlD,CAAC"}
package/dist/config.js ADDED
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Config file helpers shared across CLI commands.
3
+ */
4
+ import { homedir } from 'node:os';
5
+ import { join, dirname, resolve, isAbsolute } from 'node:path';
6
+ export const getConfigDir = () => Bun.env.OPENTABS_CONFIG_DIR || join(homedir(), '.opentabs');
7
+ export const getConfigPath = () => join(getConfigDir(), 'config.json');
8
+ export const getLogFilePath = () => join(getConfigDir(), 'server.log');
9
+ export const readConfig = async (configPath) => {
10
+ const configFile = Bun.file(configPath);
11
+ if (!(await configFile.exists())) {
12
+ return null;
13
+ }
14
+ let parsed;
15
+ try {
16
+ parsed = JSON.parse(await configFile.text());
17
+ }
18
+ catch (err) {
19
+ console.error(`Invalid JSON in config: ${err instanceof Error ? err.message : String(err)}`);
20
+ console.error(`File: ${configPath}`);
21
+ return null;
22
+ }
23
+ if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
24
+ console.error(`Invalid config at ${configPath}: expected a JSON object, got ${Array.isArray(parsed) ? 'array' : String(parsed)}`);
25
+ return null;
26
+ }
27
+ return parsed;
28
+ };
29
+ export const getPluginsFromConfig = (config) => Array.isArray(config.plugins) ? config.plugins.filter((p) => typeof p === 'string') : [];
30
+ export const resolvePluginPath = (pluginPath, configPath) => isAbsolute(pluginPath) ? pluginPath : resolve(dirname(configPath), pluginPath);
31
+ export const isConnectionRefused = (err) => {
32
+ if (!(err instanceof TypeError))
33
+ return false;
34
+ const cause = err.cause;
35
+ return cause?.code === 'ECONNREFUSED';
36
+ };
37
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAE/D,MAAM,CAAC,MAAM,YAAY,GAAG,GAAW,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,mBAAmB,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,WAAW,CAAC,CAAC;AAEtG,MAAM,CAAC,MAAM,aAAa,GAAG,GAAW,EAAE,CAAC,IAAI,CAAC,YAAY,EAAE,EAAE,aAAa,CAAC,CAAC;AAE/E,MAAM,CAAC,MAAM,cAAc,GAAG,GAAW,EAAE,CAAC,IAAI,CAAC,YAAY,EAAE,EAAE,YAAY,CAAC,CAAC;AAE/E,MAAM,CAAC,MAAM,UAAU,GAAG,KAAK,EAAE,UAAkB,EAA2C,EAAE;IAC9F,MAAM,UAAU,GAAG,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACxC,IAAI,CAAC,CAAC,MAAM,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC;QACjC,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC;IAC/C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,2BAA2B,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC7F,OAAO,CAAC,KAAK,CAAC,SAAS,UAAU,EAAE,CAAC,CAAC;QACrC,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3E,OAAO,CAAC,KAAK,CACX,qBAAqB,UAAU,iCAAiC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CACnH,CAAC;QACF,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,MAAiC,CAAC;AAC3C,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,MAA+B,EAAY,EAAE,CAChF,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAE,MAAM,CAAC,OAAqB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AAEvH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,UAAkB,EAAE,UAAkB,EAAU,EAAE,CAClF,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,UAAU,CAAC,CAAC;AAEjF,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,GAAY,EAAW,EAAE;IAC3D,IAAI,CAAC,CAAC,GAAG,YAAY,SAAS,CAAC;QAAE,OAAO,KAAK,CAAC;IAC9C,MAAM,KAAK,GAAI,GAAiD,CAAC,KAAK,CAAC;IACvE,OAAO,KAAK,EAAE,IAAI,KAAK,cAAc,CAAC;AACxC,CAAC,CAAC"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Shared port parser and resolver for Commander options.
3
+ */
4
+ declare const parsePort: (value: string) => number;
5
+ /**
6
+ * Resolves the MCP server port from (in priority order):
7
+ * 1. The --port flag (passed via Commander options)
8
+ * 2. The OPENTABS_PORT environment variable
9
+ * 3. The default port (9515)
10
+ */
11
+ declare const resolvePort: (options: {
12
+ port?: number;
13
+ }) => number;
14
+ export { parsePort, resolvePort };
15
+ //# sourceMappingURL=parse-port.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-port.d.ts","sourceRoot":"","sources":["../src/parse-port.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,QAAA,MAAM,SAAS,GAAI,OAAO,MAAM,KAAG,MAMlC,CAAC;AAEF;;;;;GAKG;AACH,QAAA,MAAM,WAAW,GAAI,SAAS;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,KAAG,MAYjD,CAAC;AAEF,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,CAAC"}