@telelabsai/ship 1.1.6 → 1.1.8

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.
@@ -64,7 +64,9 @@ function login() {
64
64
 
65
65
  server.listen(0, () => {
66
66
  const port = server.address().port;
67
- const authUrl = `${DASHBOARD_URL}/authorize-cli?port=${port}`;
67
+ const hostname = os.hostname();
68
+ const platform = process.platform === 'darwin' ? 'macOS' : process.platform === 'win32' ? 'Windows' : 'Linux';
69
+ const authUrl = `${DASHBOARD_URL}/authorize-cli?port=${port}&device=${encodeURIComponent(hostname)}&platform=${encodeURIComponent(platform)}`;
68
70
 
69
71
  console.log(` Auth URL: ${authUrl}\n`);
70
72
  console.log(' Waiting for authorization...\n');
@@ -2,13 +2,13 @@ const https = require('https');
2
2
  const http = require('http');
3
3
  const fs = require('fs');
4
4
  const path = require('path');
5
- const readline = require('readline');
5
+ const prompts = require('prompts');
6
6
  const { loadCredentials, DASHBOARD_URL } = require('./auth.js');
7
7
 
8
8
  /**
9
9
  * ship sync [--workspace <slug>] [--org <slug>] [--key <key>] [--dir <path>]
10
10
  *
11
- * Interactive mode (no flags): picks org + workspace from list
11
+ * Interactive mode (no flags): picks workspace with arrow keys
12
12
  * CI mode (with flags): uses provided org + workspace directly
13
13
  */
14
14
  function sync(args) {
@@ -36,7 +36,7 @@ function sync(args) {
36
36
  return;
37
37
  }
38
38
 
39
- // Interactive mode — fetch orgs + workspaces, let user pick
39
+ // Interactive mode
40
40
  if (!process.stdin.isTTY) {
41
41
  console.error(' Error: --org and --workspace required in non-interactive mode.');
42
42
  console.error(' Usage: ship sync --org <slug> --workspace <slug>\n');
@@ -45,7 +45,7 @@ function sync(args) {
45
45
 
46
46
  console.log(' Fetching your workspaces...\n');
47
47
 
48
- fetchJson(`${DASHBOARD_URL}/api/cli/workspaces`, token, (err, data) => {
48
+ fetchJson(`${DASHBOARD_URL}/api/cli/workspaces`, token, async (err, data) => {
49
49
  if (err) {
50
50
  console.error(` Error: ${err.message}\n`);
51
51
  process.exit(1);
@@ -61,7 +61,7 @@ function sync(args) {
61
61
  process.exit(0);
62
62
  }
63
63
 
64
- // Flatten all workspaces with org info
64
+ // Flatten all workspaces
65
65
  const allWorkspaces = [];
66
66
  for (const o of orgs) {
67
67
  for (const w of o.workspaces) {
@@ -80,42 +80,43 @@ function sync(args) {
80
80
  process.exit(0);
81
81
  }
82
82
 
83
- // Show picker
84
- console.log(' Available workspaces:\n');
85
- allWorkspaces.forEach((w, i) => {
86
- console.log(` ${i + 1}. ${w.wsName} (${w.orgName}) — ${w.files} files`);
83
+ // Arrow-key workspace picker
84
+ const { selected } = await prompts({
85
+ type: 'select',
86
+ name: 'selected',
87
+ message: 'Select workspace',
88
+ choices: allWorkspaces.map((w) => ({
89
+ title: `${w.wsName} (${w.orgName})`,
90
+ description: `${w.files} files`,
91
+ value: w,
92
+ })),
87
93
  });
88
- console.log('');
89
-
90
- const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
91
94
 
92
- rl.question(' Select workspace [1]: ', (answer) => {
93
- const idx = parseInt(answer || '1', 10) - 1;
94
- if (idx < 0 || idx >= allWorkspaces.length) {
95
- console.error(' Invalid selection.\n');
96
- rl.close();
97
- process.exit(1);
98
- }
95
+ if (!selected) {
96
+ console.log(' Cancelled.\n');
97
+ process.exit(0);
98
+ }
99
99
 
100
- const selected = allWorkspaces[idx];
101
- console.log(`\n Will sync "${selected.wsName}" (${selected.files} files) to ${path.join(dir, '.claude')}`);
102
-
103
- rl.question(' Proceed? [Y/n]: ', (confirm) => {
104
- rl.close();
105
- const c = (confirm || 'y').toLowerCase().trim();
106
- if (c !== 'y' && c !== 'yes' && c !== '') {
107
- console.log(' Cancelled.\n');
108
- process.exit(0);
109
- }
110
- console.log('');
111
- doSync(selected.orgSlug, selected.wsSlug, token, dir);
112
- });
100
+ // Confirmation
101
+ const { confirmed } = await prompts({
102
+ type: 'confirm',
103
+ name: 'confirmed',
104
+ message: `Sync "${selected.wsName}" (${selected.files} files) to ${path.join(dir, '.claude')}?`,
105
+ initial: true,
113
106
  });
107
+
108
+ if (!confirmed) {
109
+ console.log(' Cancelled.\n');
110
+ process.exit(0);
111
+ }
112
+
113
+ console.log('');
114
+ doSync(selected.orgSlug, selected.wsSlug, token, dir);
114
115
  });
115
116
  }
116
117
 
117
118
  function doSync(orgSlug, workspaceSlug, token, dir) {
118
- console.log(` Syncing workspace "${workspaceSlug}" from org "${orgSlug}"...\n`);
119
+ console.log(` Syncing workspace "${workspaceSlug}"...\n`);
119
120
 
120
121
  const url = `${DASHBOARD_URL}/api/sync/${orgSlug}?workspace=${workspaceSlug}`;
121
122
 
@@ -147,9 +148,8 @@ function doSync(orgSlug, workspaceSlug, token, dir) {
147
148
  console.log(` + .claude/${file.path}`);
148
149
  }
149
150
 
150
- console.log(`\n Synced ${written} files to ${claudeDir}\n`);
151
+ console.log(`\n Synced ${written} files to ${claudeDir}\n`);
151
152
 
152
- // Save config for future syncs
153
153
  saveSyncConfig(dir, orgSlug, workspaceSlug);
154
154
  });
155
155
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@telelabsai/ship",
3
- "version": "1.1.6",
3
+ "version": "1.1.8",
4
4
  "description": "Ship code faster with pre-configured agents, skills, rules, and hooks for Claude Code.",
5
5
  "bin": {
6
6
  "ship": "cli/bin.js"
@@ -37,5 +37,8 @@
37
37
  },
38
38
  "engines": {
39
39
  "node": ">=18.0.0"
40
+ },
41
+ "dependencies": {
42
+ "prompts": "^2.4.2"
40
43
  }
41
44
  }