@instawp/cli 0.0.1-beta.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 (51) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +129 -0
  3. package/dist/commands/exec.d.ts +3 -0
  4. package/dist/commands/exec.js +126 -0
  5. package/dist/commands/exec.js.map +1 -0
  6. package/dist/commands/login.d.ts +2 -0
  7. package/dist/commands/login.js +63 -0
  8. package/dist/commands/login.js.map +1 -0
  9. package/dist/commands/sites.d.ts +3 -0
  10. package/dist/commands/sites.js +343 -0
  11. package/dist/commands/sites.js.map +1 -0
  12. package/dist/commands/ssh.d.ts +2 -0
  13. package/dist/commands/ssh.js +41 -0
  14. package/dist/commands/ssh.js.map +1 -0
  15. package/dist/commands/sync.d.ts +2 -0
  16. package/dist/commands/sync.js +131 -0
  17. package/dist/commands/sync.js.map +1 -0
  18. package/dist/commands/teams.d.ts +2 -0
  19. package/dist/commands/teams.js +122 -0
  20. package/dist/commands/teams.js.map +1 -0
  21. package/dist/commands/whoami.d.ts +2 -0
  22. package/dist/commands/whoami.js +60 -0
  23. package/dist/commands/whoami.js.map +1 -0
  24. package/dist/index.d.ts +2 -0
  25. package/dist/index.js +101 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/lib/api.d.ts +4 -0
  28. package/dist/lib/api.js +45 -0
  29. package/dist/lib/api.js.map +1 -0
  30. package/dist/lib/auth.d.ts +1 -0
  31. package/dist/lib/auth.js +75 -0
  32. package/dist/lib/auth.js.map +1 -0
  33. package/dist/lib/config.d.ts +11 -0
  34. package/dist/lib/config.js +66 -0
  35. package/dist/lib/config.js.map +1 -0
  36. package/dist/lib/output.d.ts +14 -0
  37. package/dist/lib/output.js +63 -0
  38. package/dist/lib/output.js.map +1 -0
  39. package/dist/lib/site-resolver.d.ts +2 -0
  40. package/dist/lib/site-resolver.js +78 -0
  41. package/dist/lib/site-resolver.js.map +1 -0
  42. package/dist/lib/ssh-connection.d.ts +8 -0
  43. package/dist/lib/ssh-connection.js +70 -0
  44. package/dist/lib/ssh-connection.js.map +1 -0
  45. package/dist/lib/ssh-keys.d.ts +2 -0
  46. package/dist/lib/ssh-keys.js +232 -0
  47. package/dist/lib/ssh-keys.js.map +1 -0
  48. package/dist/types.d.ts +76 -0
  49. package/dist/types.js +2 -0
  50. package/dist/types.js.map +1 -0
  51. package/package.json +55 -0
@@ -0,0 +1,78 @@
1
+ import { getClient } from './api.js';
2
+ import { error, info } from './output.js';
3
+ export async function resolveSite(identifier) {
4
+ const client = getClient();
5
+ // If purely numeric, fetch directly by ID
6
+ if (/^\d+$/.test(identifier)) {
7
+ try {
8
+ const res = await client.get(`/sites/${identifier}/details`);
9
+ const data = res.data?.data;
10
+ const site = data?.site || data;
11
+ return normalizeSite(site, data);
12
+ }
13
+ catch (err) {
14
+ if (err.response?.status === 404) {
15
+ error(`No site found with ID ${identifier}. Use \`instawp sites list\` to see your sites.`);
16
+ }
17
+ else {
18
+ error('Failed to fetch site details', err.response?.data?.message || err.message);
19
+ }
20
+ process.exit(1);
21
+ }
22
+ }
23
+ // Otherwise, search by name/domain
24
+ try {
25
+ const res = await client.get('/sites', { params: { per_page: 100 } });
26
+ const sites = res.data?.data || [];
27
+ const needle = identifier.toLowerCase();
28
+ const matches = sites.filter((s) => {
29
+ const name = (s.name || '').toLowerCase();
30
+ const subDomain = (s.sub_domain || '').toLowerCase();
31
+ const domainName = (s.domain?.name || '').toLowerCase();
32
+ return name === needle || subDomain === needle || domainName === needle;
33
+ });
34
+ if (matches.length === 0) {
35
+ error(`No site found matching '${identifier}'. Use \`instawp sites list\` to see your sites.`);
36
+ process.exit(1);
37
+ }
38
+ if (matches.length > 1) {
39
+ error(`Multiple sites match '${identifier}':`);
40
+ for (const s of matches) {
41
+ info(` ID ${s.id}: ${s.name || s.sub_domain} (${s.url || s.domain?.name || s.sub_domain})`);
42
+ }
43
+ info('Use the site ID to be specific.');
44
+ process.exit(1);
45
+ }
46
+ // Single match — fetch full details
47
+ const match = matches[0];
48
+ try {
49
+ const detailRes = await client.get(`/sites/${match.id}/details`);
50
+ const data = detailRes.data?.data;
51
+ const site = data?.site || data;
52
+ return normalizeSite(site, data);
53
+ }
54
+ catch {
55
+ // Fall back to list data if details endpoint fails
56
+ return normalizeSite(match, match);
57
+ }
58
+ }
59
+ catch (err) {
60
+ error('Failed to search sites', err.response?.data?.message || err.message);
61
+ process.exit(1);
62
+ }
63
+ }
64
+ function normalizeSite(site, raw) {
65
+ return {
66
+ id: site.id,
67
+ name: site.name || '',
68
+ sub_domain: site.sub_domain || site.main_domain || raw?.sub_domain || '',
69
+ url: site.url || '',
70
+ status: site.status ?? 0,
71
+ wp_version: site.wp_version || '',
72
+ php_version: site.php_version || '',
73
+ domain: site.domain || raw?.domain,
74
+ server_username: site.server_username || raw?.server_username || '',
75
+ main_domain: site.main_domain || raw?.main_domain || '',
76
+ };
77
+ }
78
+ //# sourceMappingURL=site-resolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"site-resolver.js","sourceRoot":"","sources":["../../src/lib/site-resolver.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { SshConnection } from '../types.js';
2
+ export declare function spawnInteractiveSsh(conn: SshConnection): number;
3
+ export declare function execViaSsh(conn: SshConnection, command: string): {
4
+ stdout: string;
5
+ stderr: string;
6
+ exitCode: number;
7
+ };
8
+ export declare function rsyncViaSsh(conn: SshConnection, source: string, dest: string, extraArgs: string[], dryRun: boolean, stream: boolean): number;
@@ -0,0 +1,70 @@
1
+ import { spawnSync } from 'node:child_process';
2
+ import { homedir } from 'node:os';
3
+ import path from 'node:path';
4
+ import { existsSync, mkdirSync } from 'node:fs';
5
+ const KNOWN_HOSTS = path.join(homedir(), '.instawp', 'known_hosts');
6
+ function ensureKnownHosts() {
7
+ const dir = path.dirname(KNOWN_HOSTS);
8
+ if (!existsSync(dir)) {
9
+ mkdirSync(dir, { recursive: true });
10
+ }
11
+ }
12
+ function sshArgs(conn) {
13
+ ensureKnownHosts();
14
+ return [
15
+ '-i', conn.privateKeyPath,
16
+ '-p', String(conn.port),
17
+ '-o', 'StrictHostKeyChecking=accept-new',
18
+ '-o', `UserKnownHostsFile=${KNOWN_HOSTS}`,
19
+ ];
20
+ }
21
+ function sshTarget(conn) {
22
+ return `${conn.username}@${conn.host}`;
23
+ }
24
+ export function spawnInteractiveSsh(conn) {
25
+ const result = spawnSync('ssh', [...sshArgs(conn), sshTarget(conn)], {
26
+ stdio: 'inherit',
27
+ });
28
+ return result.status ?? 1;
29
+ }
30
+ export function execViaSsh(conn, command) {
31
+ // Pipe command via stdin with -T (no PTY) — InstaWP servers require this
32
+ // instead of passing command as SSH args
33
+ const result = spawnSync('ssh', ['-T', ...sshArgs(conn), sshTarget(conn)], {
34
+ input: command + '\n',
35
+ encoding: 'utf-8',
36
+ stdio: ['pipe', 'pipe', 'pipe'],
37
+ });
38
+ return {
39
+ stdout: result.stdout || '',
40
+ stderr: result.stderr || '',
41
+ exitCode: result.status ?? 1,
42
+ };
43
+ }
44
+ export function rsyncViaSsh(conn, source, dest, extraArgs, dryRun, stream) {
45
+ ensureKnownHosts();
46
+ const sshCmd = `ssh -i ${conn.privateKeyPath} -p ${conn.port} -o StrictHostKeyChecking=accept-new -o UserKnownHostsFile=${KNOWN_HOSTS}`;
47
+ const args = [
48
+ '-avz',
49
+ '--exclude=.git',
50
+ '--exclude=node_modules',
51
+ '--exclude=.DS_Store',
52
+ ...(dryRun ? ['--dry-run'] : []),
53
+ ...extraArgs,
54
+ '-e', sshCmd,
55
+ source,
56
+ dest,
57
+ ];
58
+ const result = spawnSync('rsync', args, {
59
+ stdio: stream ? 'inherit' : ['pipe', 'pipe', 'pipe'],
60
+ encoding: stream ? undefined : 'utf-8',
61
+ });
62
+ if (!stream && result.stdout) {
63
+ console.log(result.stdout);
64
+ }
65
+ if (!stream && result.stderr && result.status !== 0) {
66
+ console.error(result.stderr);
67
+ }
68
+ return result.status ?? 1;
69
+ }
70
+ //# sourceMappingURL=ssh-connection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ssh-connection.js","sourceRoot":"","sources":["../../src/lib/ssh-connection.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { SshConnection } from '../types.js';
2
+ export declare function ensureSshAccess(siteId: number): Promise<SshConnection>;
@@ -0,0 +1,232 @@
1
+ import { existsSync, readFileSync, mkdirSync } from 'node:fs';
2
+ import { execSync } from 'node:child_process';
3
+ import { homedir } from 'node:os';
4
+ import path from 'node:path';
5
+ import { getClient } from './api.js';
6
+ import { getSshCache, setSshCache, clearSshCache } from './config.js';
7
+ import { error, spinner } from './output.js';
8
+ const INSTAWP_DIR = path.join(homedir(), '.instawp');
9
+ const CLI_KEY_PATH = path.join(INSTAWP_DIR, 'cli_key');
10
+ const CLI_KEY_PUB_PATH = CLI_KEY_PATH + '.pub';
11
+ function ensureInstawpDir() {
12
+ if (!existsSync(INSTAWP_DIR)) {
13
+ mkdirSync(INSTAWP_DIR, { recursive: true });
14
+ }
15
+ }
16
+ function findLocalPubKeys() {
17
+ const keys = [];
18
+ const sshDir = path.join(homedir(), '.ssh');
19
+ // Check CLI-managed key first
20
+ if (existsSync(CLI_KEY_PUB_PATH) && existsSync(CLI_KEY_PATH)) {
21
+ keys.push({ privatePath: CLI_KEY_PATH, pubContent: readFileSync(CLI_KEY_PUB_PATH, 'utf-8').trim() });
22
+ }
23
+ // Check common SSH key locations (RSA first — API only accepts ssh-rsa/ssh-dss)
24
+ for (const name of ['id_rsa', 'id_ed25519']) {
25
+ const privPath = path.join(sshDir, name);
26
+ const pubPath = privPath + '.pub';
27
+ if (existsSync(pubPath) && existsSync(privPath)) {
28
+ keys.push({ privatePath: privPath, pubContent: readFileSync(pubPath, 'utf-8').trim() });
29
+ }
30
+ }
31
+ return keys;
32
+ }
33
+ function parseKeyMaterial(pubContent) {
34
+ // Extract "type base64data" ignoring comment
35
+ const parts = pubContent.trim().split(/\s+/);
36
+ if (parts.length >= 2) {
37
+ return `${parts[0]} ${parts[1]}`;
38
+ }
39
+ return pubContent.trim();
40
+ }
41
+ function generateCliKey() {
42
+ ensureInstawpDir();
43
+ try {
44
+ // Use yes to auto-overwrite if an old key exists (e.g. wrong type)
45
+ execSync(`yes | ssh-keygen -t rsa -b 4096 -f "${CLI_KEY_PATH}" -N "" -C "instawp-cli"`, {
46
+ stdio: 'ignore',
47
+ shell: '/bin/sh',
48
+ });
49
+ }
50
+ catch {
51
+ error('Failed to generate SSH key. Ensure ssh-keygen (OpenSSH) is installed.');
52
+ process.exit(1);
53
+ }
54
+ return {
55
+ privatePath: CLI_KEY_PATH,
56
+ pubContent: readFileSync(CLI_KEY_PUB_PATH, 'utf-8').trim(),
57
+ };
58
+ }
59
+ export async function ensureSshAccess(siteId) {
60
+ // 1. Check cache
61
+ const cached = getSshCache(siteId);
62
+ if (cached) {
63
+ // Verify the private key still exists
64
+ if (existsSync(cached.connection.privateKeyPath)) {
65
+ return cached.connection;
66
+ }
67
+ clearSshCache(siteId);
68
+ }
69
+ const client = getClient();
70
+ const spin = spinner('Setting up SSH access...');
71
+ spin.start();
72
+ try {
73
+ // 2. Find local keys
74
+ let localKeys = findLocalPubKeys();
75
+ // 3. Fetch uploaded keys from API
76
+ let uploadedKeys = [];
77
+ try {
78
+ const res = await client.get('/ssh-keys');
79
+ uploadedKeys = (res.data?.data || []).map((k) => ({
80
+ id: k.id,
81
+ label: k.label || '',
82
+ ssh_key: k.ssh_key || '',
83
+ }));
84
+ }
85
+ catch {
86
+ // SSH keys endpoint might not exist; proceed to upload
87
+ }
88
+ // 4. Find a matching key (local key already uploaded)
89
+ let matchedKey = null;
90
+ for (const local of localKeys) {
91
+ const localMaterial = parseKeyMaterial(local.pubContent);
92
+ for (const uploaded of uploadedKeys) {
93
+ const uploadedMaterial = parseKeyMaterial(uploaded.ssh_key);
94
+ if (localMaterial === uploadedMaterial) {
95
+ matchedKey = { privatePath: local.privatePath, keyId: uploaded.id };
96
+ break;
97
+ }
98
+ }
99
+ if (matchedKey)
100
+ break;
101
+ }
102
+ // 5. If no match, generate CLI key if needed, then upload
103
+ if (!matchedKey) {
104
+ let keyToUpload;
105
+ const cliKeyExists = existsSync(CLI_KEY_PUB_PATH) && existsSync(CLI_KEY_PATH);
106
+ const cliKeyIsRsa = cliKeyExists && readFileSync(CLI_KEY_PUB_PATH, 'utf-8').trim().startsWith('ssh-rsa ');
107
+ if (cliKeyExists && cliKeyIsRsa) {
108
+ keyToUpload = {
109
+ privatePath: CLI_KEY_PATH,
110
+ pubContent: readFileSync(CLI_KEY_PUB_PATH, 'utf-8').trim(),
111
+ };
112
+ }
113
+ else {
114
+ spin.text = 'Generating SSH key...';
115
+ keyToUpload = generateCliKey();
116
+ }
117
+ spin.text = 'Uploading SSH key...';
118
+ try {
119
+ const uploadRes = await client.post('/ssh-keys', {
120
+ label: 'InstaWP CLI',
121
+ ssh_key: keyToUpload.pubContent,
122
+ });
123
+ const keyId = uploadRes.data?.data?.id;
124
+ if (!keyId) {
125
+ spin.fail('SSH key upload failed');
126
+ error('Unexpected response when uploading SSH key');
127
+ process.exit(1);
128
+ }
129
+ matchedKey = { privatePath: keyToUpload.privatePath, keyId };
130
+ }
131
+ catch (err) {
132
+ spin.fail('SSH key upload failed');
133
+ const msg = err.response?.data?.message || err.message;
134
+ if (err.response?.status === 403) {
135
+ error('Payment method required. Add one at app.instawp.io/billing');
136
+ }
137
+ else {
138
+ error('Failed to upload SSH key', msg);
139
+ }
140
+ process.exit(1);
141
+ }
142
+ }
143
+ // 6. Enable SSH + SFTP on site (must happen before attach — creates Server_ssh record)
144
+ // SFTP is required for rsync to work (enables the remote command subsystem)
145
+ spin.text = 'Enabling SSH...';
146
+ let sshDetails;
147
+ try {
148
+ const enableRes = await client.post(`/sites/${siteId}/update-ssh-status`, { status: 1 });
149
+ // API returns host/username at top level or inside data
150
+ const resp = enableRes.data || {};
151
+ const data = resp.data && typeof resp.data === 'object' && !Array.isArray(resp.data) ? resp.data : {};
152
+ sshDetails = {
153
+ host: resp.host || data.host || data.ip || '',
154
+ username: resp.username || data.username || '',
155
+ port: resp.port || data.port || 22,
156
+ };
157
+ }
158
+ catch (err) {
159
+ spin.fail('Failed to enable SSH');
160
+ const msg = err.response?.data?.message || err.message;
161
+ if (err.response?.status === 403) {
162
+ error('SSH requires a paid plan. Upgrade at app.instawp.io/billing');
163
+ }
164
+ else {
165
+ error('Could not enable SSH on site', msg);
166
+ }
167
+ process.exit(1);
168
+ }
169
+ // Also enable SFTP (needed for rsync remote command execution)
170
+ try {
171
+ await client.post(`/sites/${siteId}/update-sftp-status`, { status: 1 });
172
+ }
173
+ catch {
174
+ // Non-fatal — SFTP may already be enabled or not available
175
+ }
176
+ // 7. Attach key to site (after SSH enabled so Server_ssh record exists)
177
+ spin.text = 'Attaching SSH key to site...';
178
+ try {
179
+ await client.post(`/sites/${siteId}/ssh-keys/${matchedKey.keyId}`);
180
+ }
181
+ catch (err) {
182
+ // 409/duplicate is fine — key already attached
183
+ if (err.response?.status !== 409 && err.response?.status !== 422) {
184
+ spin.fail('Failed to attach SSH key');
185
+ const msg = err.response?.data?.message || err.message;
186
+ if (err.response?.status === 403) {
187
+ error('Payment method required. Add one at app.instawp.io/billing');
188
+ }
189
+ else {
190
+ error('Could not attach SSH key to site', msg);
191
+ }
192
+ process.exit(1);
193
+ }
194
+ }
195
+ if (!sshDetails.host || !sshDetails.username) {
196
+ spin.fail('SSH details incomplete');
197
+ error('Could not get SSH connection details from API');
198
+ process.exit(1);
199
+ }
200
+ // 8. Build and cache connection
201
+ const connection = {
202
+ host: sshDetails.host,
203
+ username: sshDetails.username,
204
+ port: sshDetails.port,
205
+ privateKeyPath: matchedKey.privatePath,
206
+ siteId,
207
+ domain: '',
208
+ };
209
+ // Fetch domain for remote path construction
210
+ try {
211
+ const siteRes = await client.get(`/sites/${siteId}/details`);
212
+ const siteData = siteRes.data?.data;
213
+ const site = siteData?.site || siteData;
214
+ connection.domain = site?.main_domain || site?.sub_domain || site?.domain?.name || '';
215
+ }
216
+ catch {
217
+ // Non-fatal; domain used only for rsync path
218
+ }
219
+ setSshCache(siteId, { connection, cachedAt: Date.now() });
220
+ spin.succeed('SSH access ready');
221
+ return connection;
222
+ }
223
+ catch (err) {
224
+ // Re-throw if already handled (process.exit above)
225
+ if (err.code === 'ERR_PROCESS_EXIT')
226
+ throw err;
227
+ spin.fail('SSH setup failed');
228
+ error('Unexpected error during SSH setup', err.message);
229
+ process.exit(1);
230
+ }
231
+ }
232
+ //# sourceMappingURL=ssh-keys.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ssh-keys.js","sourceRoot":"","sources":["../../src/lib/ssh-keys.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,76 @@
1
+ export interface CliConfig {
2
+ api_url: string;
3
+ token: string | null;
4
+ user: UserInfo | null;
5
+ }
6
+ export interface UserInfo {
7
+ id: number;
8
+ name: string;
9
+ email: string;
10
+ }
11
+ export interface Site {
12
+ id: number;
13
+ domain: string;
14
+ url: string;
15
+ status: string;
16
+ wp_version: string;
17
+ php_version: string;
18
+ created_at: string;
19
+ }
20
+ export interface SiteCreateParams {
21
+ site_name: string;
22
+ php_version?: string;
23
+ plan_id?: number;
24
+ configuration_id?: number;
25
+ }
26
+ export interface SftpCredentials {
27
+ host: string;
28
+ username: string;
29
+ password: string;
30
+ port: number;
31
+ }
32
+ export interface RunCmdResult {
33
+ output: string;
34
+ exit_code: number;
35
+ }
36
+ export interface ApiResponse<T = any> {
37
+ status: boolean;
38
+ data: T;
39
+ message?: string;
40
+ }
41
+ export interface SiteDetails {
42
+ id: number;
43
+ name: string;
44
+ sub_domain: string;
45
+ url: string;
46
+ status: number;
47
+ wp_version: string;
48
+ php_version: string;
49
+ domain?: {
50
+ name: string;
51
+ };
52
+ server_username?: string;
53
+ main_domain?: string;
54
+ }
55
+ export interface SshKeyInfo {
56
+ id: number;
57
+ label: string;
58
+ ssh_key: string;
59
+ }
60
+ export interface SshConnection {
61
+ host: string;
62
+ username: string;
63
+ port: number;
64
+ privateKeyPath: string;
65
+ siteId: number;
66
+ domain: string;
67
+ }
68
+ export interface SshConnectionCache {
69
+ connection: SshConnection;
70
+ cachedAt: number;
71
+ }
72
+ export interface TeamInfo {
73
+ id: number;
74
+ name: string;
75
+ created_at: string;
76
+ }
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "@instawp/cli",
3
+ "version": "0.0.1-beta.1",
4
+ "description": "InstaWP CLI - Create and manage WordPress sites from the terminal",
5
+ "type": "module",
6
+ "bin": {
7
+ "instawp": "./dist/index.js"
8
+ },
9
+ "files": [
10
+ "dist",
11
+ "!dist/__tests__"
12
+ ],
13
+ "scripts": {
14
+ "build": "tsc",
15
+ "dev": "tsc --watch",
16
+ "prepublishOnly": "npm run build",
17
+ "test": "vitest run",
18
+ "test:watch": "vitest"
19
+ },
20
+ "engines": {
21
+ "node": ">=18"
22
+ },
23
+ "keywords": [
24
+ "instawp",
25
+ "wordpress",
26
+ "wp-cli",
27
+ "cli",
28
+ "hosting",
29
+ "devtools"
30
+ ],
31
+ "homepage": "https://github.com/InstaWP/cli#readme",
32
+ "repository": {
33
+ "type": "git",
34
+ "url": "git+https://github.com/InstaWP/cli.git"
35
+ },
36
+ "bugs": {
37
+ "url": "https://github.com/InstaWP/cli/issues"
38
+ },
39
+ "author": "InstaWP <vikas@instawp.com>",
40
+ "license": "MIT",
41
+ "dependencies": {
42
+ "axios": "^1.7.0",
43
+ "chalk": "^5.3.0",
44
+ "cli-table3": "^0.6.5",
45
+ "commander": "^12.1.0",
46
+ "conf": "^13.0.0",
47
+ "open": "^10.1.0",
48
+ "ora": "^8.1.0"
49
+ },
50
+ "devDependencies": {
51
+ "@types/node": "^20.0.0",
52
+ "typescript": "^5.5.0",
53
+ "vitest": "^4.0.18"
54
+ }
55
+ }