pro-app 0.1.0 → 0.1.2

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 (3) hide show
  1. package/README.md +3 -2
  2. package/bin/proapp.js +54 -37
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -3,10 +3,11 @@
3
3
  Connect Claude Code or Codex to your PROApp workspace.
4
4
 
5
5
  ```
6
- npx pro-app
6
+ npx pro-app claude
7
+ npx pro-app codex
7
8
  ```
8
9
 
9
- Adds PROApp to whichever assistant you have and opens PROApp sign-in in your browser. Sign in, click **Allow access**, done.
10
+ Adds PROApp to that assistant and opens PROApp sign-in in your browser. Sign in, click **Allow access**, done. `npx pro-app` alone connects whichever one is installed (and asks if both are).
10
11
 
11
12
  - `npx pro-app login` — sign in again
12
13
  - `npx pro-app logout` — sign out
package/bin/proapp.js CHANGED
@@ -2,63 +2,80 @@
2
2
  'use strict';
3
3
  // PROApp connector for local AI coding assistants. No credentials live here:
4
4
  // sign-in happens in your browser on PROApp's own page, and each assistant
5
- // stores its own token. Usage: npx pro-app [connect|login|logout|status|help]
5
+ // stores its own token. Usage: npx pro-app [claude|codex] | login|logout|status [claude|codex]
6
6
  const { spawnSync } = require('node:child_process');
7
+ const readline = require('node:readline');
7
8
 
8
- const URL = 'https://www.pro-app.com/api/mcp';
9
+ const SERVER = 'https://www.proapphub.com/api/mcp';
9
10
  const NAME = 'proapp';
10
11
  const APPS = [
11
- { label: 'Claude Code', bin: 'claude',
12
- add: ['mcp', 'add', '--transport', 'http', '--scope', 'user', '--client-id', 'proapp-claude-code', '--callback-port', '8766', NAME, URL],
12
+ { key: 'claude', label: 'Claude Code', bin: 'claude',
13
+ add: ['mcp', 'add', '--transport', 'http', '--scope', 'user', '--client-id', 'proapp-claude-code', '--callback-port', '8766', NAME, SERVER],
13
14
  remove: ['mcp', 'remove', NAME, '--scope', 'user'] },
14
- { label: 'Codex', bin: 'codex',
15
- add: ['mcp', 'add', NAME, '--url', URL, '--oauth-client-id', 'proapp-codex'],
15
+ { key: 'codex', label: 'Codex', bin: 'codex',
16
+ add: ['mcp', 'add', NAME, '--url', SERVER, '--oauth-client-id', 'proapp-codex'],
16
17
  remove: ['mcp', 'remove', NAME] },
17
18
  ];
18
19
 
19
- const run = (bin, args, quiet = false) => spawnSync(bin, args, { stdio: quiet ? 'ignore' : 'inherit', shell: false });
20
+ // On Windows, npm installs CLIs as .cmd/.ps1 shims that can only be started through a
21
+ // shell. Every argument here is a fixed string (no user input), so this is safe.
22
+ const SHELL = process.platform === 'win32';
23
+ const run = (bin, args, quiet = false) => spawnSync(bin, args, { stdio: quiet ? 'ignore' : 'inherit', shell: SHELL });
20
24
  const installed = (bin) => {
21
- const probe = spawnSync(bin, ['--version'], { stdio: 'ignore', shell: false });
25
+ const probe = spawnSync(bin, ['--version'], { stdio: 'ignore', shell: SHELL });
22
26
  return !probe.error && probe.status === 0;
23
27
  };
28
+ const fail = (message) => { console.error(message); process.exit(1); };
24
29
 
25
- function pick(which) {
30
+ function ask(question) {
31
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
32
+ return new Promise(resolve => rl.question(question, answer => { rl.close(); resolve(answer.trim().toLowerCase()); }));
33
+ }
34
+
35
+ /** One assistant: the one named, the only one installed, or the one the user picks. */
36
+ async function choose(which) {
26
37
  const apps = APPS.filter(app => installed(app.bin));
27
- const chosen = which ? apps.filter(app => app.bin === which || app.label.toLowerCase().startsWith(which)) : apps;
28
- if (!apps.length) {
29
- console.error('Neither Claude Code nor Codex was found. Install one, then run: npx pro-app');
30
- process.exit(1);
31
- }
32
- if (!chosen.length) {
33
- console.error(`"${which}" is not installed. Found: ${apps.map(a => a.bin).join(', ')}`);
34
- process.exit(1);
38
+ if (!apps.length) fail('Neither Claude Code nor Codex was found. Install one, then run: npx pro-app');
39
+ if (which) {
40
+ const app = APPS.find(a => a.key === which);
41
+ if (!app) fail(`Unknown assistant "${which}". Use: npx pro-app claude or npx pro-app codex`);
42
+ if (!apps.includes(app)) fail(`${app.label} is not installed on this computer.`);
43
+ return app;
35
44
  }
36
- return chosen;
45
+ if (apps.length === 1) return apps[0];
46
+ if (!process.stdin.isTTY) fail('Both Claude Code and Codex are installed. Run: npx pro-app claude or npx pro-app codex');
47
+ const answer = await ask('Connect PROApp to which assistant? [1] Claude Code [2] Codex: ');
48
+ const app = answer === '1' || answer.startsWith('cl') ? apps.find(a => a.key === 'claude')
49
+ : answer === '2' || answer.startsWith('co') ? apps.find(a => a.key === 'codex') : undefined;
50
+ if (!app) fail('No assistant chosen. Run: npx pro-app claude or npx pro-app codex');
51
+ return app;
37
52
  }
38
53
 
39
- function connect(which) {
40
- for (const app of pick(which)) {
41
- run(app.bin, app.remove, true);
42
- if (run(app.bin, app.add, true).status !== 0) { console.error(`Could not add PROApp to ${app.label}.`); continue; }
43
- console.log(`\nPROApp added to ${app.label}. Opening sign-in in your browser...`);
44
- if (run(app.bin, ['mcp', 'login', NAME]).status !== 0) console.log(`Finish later with: npx pro-app login ${app.bin}`);
45
- else console.log(`${app.label} is connected to PROApp.`);
46
- }
54
+ function connect(app) {
55
+ run(app.bin, app.remove, true);
56
+ if (run(app.bin, app.add, true).status !== 0) fail(`Could not add PROApp to ${app.label}.`);
57
+ console.log(`\nPROApp added to ${app.label}. Opening sign-in in your browser...`);
58
+ if (run(app.bin, ['mcp', 'login', NAME]).status !== 0) console.log(`Finish later with: npx pro-app login ${app.key}`);
59
+ else console.log(`${app.label} is connected to PROApp.`);
47
60
  }
48
61
 
49
- const [command = 'connect', which] = process.argv.slice(2);
50
- switch (command) {
51
- case 'connect': connect(which); break;
52
- case 'login': for (const app of pick(which)) run(app.bin, ['mcp', 'login', NAME]); break;
53
- case 'logout': for (const app of pick(which)) run(app.bin, ['mcp', 'logout', NAME]); break;
54
- case 'status': for (const app of pick(which)) { console.log(`\n${app.label}:`); run(app.bin, ['mcp', 'get', NAME]); } break;
55
- default:
56
- console.log(`PROApp for Claude Code and Codex
62
+ async function main() {
63
+ const [command, which] = process.argv.slice(2);
64
+ const assistants = APPS.map(a => a.key);
65
+ if (!command || assistants.includes(command)) return connect(await choose(command));
66
+ if (command === 'login') { const app = await choose(which); return void run(app.bin, ['mcp', 'login', NAME]); }
67
+ if (command === 'logout') { const app = await choose(which); return void run(app.bin, ['mcp', 'logout', NAME]); }
68
+ if (command === 'status') { const app = await choose(which); console.log(`\n${app.label}:`); return void run(app.bin, ['mcp', 'get', NAME]); }
69
+ console.log(`PROApp for Claude Code and Codex
57
70
 
58
- npx pro-app connect (adds PROApp and opens sign-in)
59
- npx pro-app login sign in again
71
+ npx pro-app claude connect Claude Code (adds PROApp and opens sign-in)
72
+ npx pro-app codex connect Codex
73
+ npx pro-app connect whichever is installed (asks if both are)
74
+ npx pro-app login sign in again (add claude/codex if both installed)
60
75
  npx pro-app logout sign out
61
76
  npx pro-app status show the connection
62
77
 
63
- Add "claude" or "codex" to act on just one. Your company needs the PROApp AI Assistant add-on.`);
78
+ Your company needs the PROApp AI Assistant add-on.`);
64
79
  }
80
+
81
+ main();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pro-app",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Connect Claude Code or Codex to your PROApp workspace.",
5
5
  "bin": {
6
6
  "pro-app": "bin/proapp.js"