@myapihq/cli 1.0.40 → 1.0.46

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.
@@ -1,3 +1,3 @@
1
- export declare function signup(): Promise<void>;
2
- export declare function whoami(): Promise<void>;
3
- export declare function switchCmd(): Promise<void>;
1
+ export declare function signup(flags?: Record<string, string | boolean>): Promise<void>;
2
+ export declare function whoami(flags?: Record<string, string | boolean>): Promise<void>;
3
+ export declare function switchCmd(flags?: Record<string, string | boolean>, indexArg?: string): Promise<void>;
@@ -39,7 +39,11 @@ async function patch(path, body, apiKey) {
39
39
  return json.data ?? json;
40
40
  }
41
41
  // myapi auth signup — upgrade anonymous session to registered account.
42
- export async function signup() {
42
+ export async function signup(flags = {}) {
43
+ if (flags.help) {
44
+ info('Usage: myapi auth signup\n\nUpgrades an anonymous account to a registered account by linking an email.\nA verification code will be sent — you must enter it interactively.\nIf the email is already in use, adds it as a second account instead.');
45
+ return;
46
+ }
43
47
  const config = loadConfig();
44
48
  if (!config?.api_key)
45
49
  error('Not configured. Run: myapi auth setup');
@@ -66,10 +70,9 @@ export async function signup() {
66
70
  info(`› Sent a code to ${email} · paste it below`);
67
71
  const code = (await ask(rl, '› Code? ')).trim();
68
72
  const data = await post('/hq/account/verify-code', { email, code });
69
- const skillsAns = (await ask(rl, ' Install the MyAPI skills pack? (Y/n) ')).trim();
70
- const wantsSkills = yn(skillsAns);
73
+ const skillsFromFlag = flags['install-skills'] ? true : flags['no-skills'] ? false : null;
74
+ const wantsSkills = skillsFromFlag !== null ? skillsFromFlag : yn((await ask(rl, '› Install the MyAPI skills pack? (Y/n) ')).trim());
71
75
  if (upgradeOk) {
72
- // Upgrade: update current account in place.
73
76
  saveConfig({
74
77
  ...config,
75
78
  api_key: data.api_key,
@@ -83,12 +86,10 @@ export async function signup() {
83
86
  success(`› Welcome! Account upgraded · ${email}`);
84
87
  }
85
88
  else {
86
- // Add as new account and switch to it.
87
89
  const idx = addAccount({
88
90
  api_key: data.api_key,
89
91
  account_id: data.account_id,
90
92
  email,
91
- pin: '',
92
93
  default_org: data.default_org,
93
94
  default_funnel: data.default_funnel,
94
95
  is_anonymous: false,
@@ -105,7 +106,11 @@ export async function signup() {
105
106
  }
106
107
  }
107
108
  // myapi auth whoami — show current session info.
108
- export async function whoami() {
109
+ export async function whoami(flags = {}) {
110
+ if (flags.help) {
111
+ info('Usage: myapi auth whoami\n\nDisplays the active account details: email, account ID, default org, default funnel, account type, and current balance.');
112
+ return;
113
+ }
109
114
  const config = loadConfig();
110
115
  if (!config?.api_key)
111
116
  error('Not configured. Run: myapi auth setup');
@@ -120,11 +125,15 @@ export async function whoami() {
120
125
  info(`Balance: ${bal.balance_display} | Credits: ${bal.credits_display}`);
121
126
  }
122
127
  catch {
123
- // Balance fetch is best-effort; don't fail whoami if it errors.
128
+ info(`Balance: (unavailable)`);
124
129
  }
125
130
  }
126
- // myapi auth switch — switch between saved accounts.
127
- export async function switchCmd() {
131
+ // myapi auth switch [index] — switch between saved accounts.
132
+ export async function switchCmd(flags = {}, indexArg) {
133
+ if (flags.help) {
134
+ info('Usage: myapi auth switch [index]\n\nSwitches the active account. Pass an account index to skip the prompt.\n\nExample:\n myapi auth switch 2');
135
+ return;
136
+ }
128
137
  const accounts = listAccounts();
129
138
  if (accounts.length === 0)
130
139
  error('No accounts configured. Run: myapi auth setup');
@@ -138,19 +147,22 @@ export async function switchCmd() {
138
147
  const marker = a.active ? ' ◀ active' : '';
139
148
  info(` ${a.index + 1}. ${label}${marker}`);
140
149
  }
141
- const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
142
- try {
143
- const ans = (await ask(rl, `› Switch to account (1-${accounts.length})? `)).trim();
144
- const idx = parseInt(ans, 10) - 1;
145
- if (isNaN(idx) || idx < 0 || idx >= accounts.length) {
146
- error('Invalid selection.');
150
+ let idxStr = indexArg ?? '';
151
+ if (!idxStr) {
152
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
153
+ try {
154
+ idxStr = (await ask(rl, `› Switch to account (1-${accounts.length})? `)).trim();
147
155
  }
148
- if (switchAccount(idx)) {
149
- const a = accounts[idx];
150
- success(`› Switched to ${a.email ?? a.account_id}`);
156
+ finally {
157
+ rl.close();
151
158
  }
152
159
  }
153
- finally {
154
- rl.close();
160
+ const idx = parseInt(idxStr, 10) - 1;
161
+ if (isNaN(idx) || idx < 0 || idx >= accounts.length) {
162
+ error('Invalid selection.');
163
+ }
164
+ if (switchAccount(idx)) {
165
+ const a = accounts[idx];
166
+ success(`› Switched to ${a.email ?? a.account_id}`);
155
167
  }
156
168
  }
@@ -17,7 +17,7 @@ export async function balance(flags) {
17
17
  }
18
18
  export async function history(flags) {
19
19
  if (flags.help) {
20
- info('Usage: myapi billing history [--json]\n\nShows your recent billing transactions and top-ups.');
20
+ info('Usage: myapi billing history [--json]\n\nShows your recent billing transactions and top-ups.\n\nFlags:\n --json Output raw JSON');
21
21
  return;
22
22
  }
23
23
  const config = requireConfig();
@@ -40,7 +40,7 @@ export async function history(flags) {
40
40
  }
41
41
  export async function topup(amountStr, flags) {
42
42
  if (flags.help) {
43
- info('Usage: myapi billing topup <amount>\n\nAmount is in whole dollars (e.g. "10" charges $10).\nUse --yes to skip confirmation.\nExample: myapi billing topup 10');
43
+ info('Usage: myapi billing topup <amount>\n\nAmount is in whole dollars (e.g. "10" charges $10).\nUse --yes to skip confirmation.\nExample: myapi billing topup 10\n\nFlags:\n --yes Skip confirmation prompt');
44
44
  return;
45
45
  }
46
46
  const amount = Math.round(parseFloat(amountStr));
@@ -6,7 +6,7 @@ export async function check(domainArg, flags) {
6
6
  const orgId = flags.org || config.default_org;
7
7
  const domain = domainArg || config.default_domain;
8
8
  if (!orgId || !domain)
9
- error("Missing required arguments.\nUsage: myapi domain check <domain> --org <id>\n(Or set defaults via: myapi auth config set-org <id> / set-domain <domain>)");
9
+ error("Missing required arguments.\nUsage: myapi domain check <domain> --org <id>\n(Set defaults: myapi auth config set-org <id> / myapi auth config set-domain <domain>)");
10
10
  const res = await sdkDomain.checkDomain(config.api_key, orgId, domain);
11
11
  if (res.available) {
12
12
  const price = res.price_display || `$${(res.price_cents / 100).toFixed(2)}`;
@@ -21,7 +21,7 @@ export async function register(domainArg, flags) {
21
21
  const orgId = flags.org || config.default_org;
22
22
  const domain = domainArg || config.default_domain;
23
23
  if (!orgId || !domain)
24
- error("Missing required arguments.\nUsage: myapi domain register <domain> --org <id> [--years <num>]\n(Or set defaults via: myapi auth config set-org <id> / set-domain <domain>)");
24
+ error("Missing required arguments.\nUsage: myapi domain register <domain> --org <id> [--years <num>]\n(Set defaults: myapi auth config set-org <id> / myapi auth config set-domain <domain>)");
25
25
  const years = parseInt(flags.years) || 1;
26
26
  const res = await sdkDomain.registerDomain(config.api_key, orgId, domain, years);
27
27
  success(`Registered ${domain}!\n${JSON.stringify(res, null, 2)}`);
@@ -31,7 +31,7 @@ export async function importDomain(domainArg, flags) {
31
31
  const orgId = flags.org || config.default_org;
32
32
  const domain = domainArg || config.default_domain;
33
33
  if (!orgId || !domain)
34
- error("Missing required arguments.\nUsage: myapi domain import <domain> --org <id> [--namecheap-user <user> --namecheap-key <key>]\n(Or set defaults via: myapi auth config set-org <id> / set-domain <domain>)");
34
+ error("Missing required arguments.\nUsage: myapi domain import <domain> --org <id> [--namecheap-user <user> --namecheap-key <key>]\n(Set defaults: myapi auth config set-org <id> / myapi auth config set-domain <domain>)");
35
35
  const payload = { domain };
36
36
  if (flags['namecheap-user'])
37
37
  payload.namecheap_api_user = flags['namecheap-user'];
@@ -44,7 +44,7 @@ export async function list(flags) {
44
44
  const config = requireConfig();
45
45
  const orgId = flags.org || config.default_org;
46
46
  if (!orgId)
47
- error("Missing required arguments.\nUsage: myapi domain list --org <id> [--filter=all|unassigned|org]\n(Or set a default org via: myapi auth config set-org <id>)");
47
+ error("Missing required arguments.\nUsage: myapi domain list --org <id> [--filter=all|unassigned|org]\n(Set default: myapi auth config set-org <id>)");
48
48
  const filter = flags.filter;
49
49
  const domains = await sdkDomain.listDomains(config.api_key, orgId, filter);
50
50
  printTable(domains);
@@ -55,7 +55,7 @@ export async function assign(domainArg, flags) {
55
55
  const domain = domainArg || config.default_domain;
56
56
  const targetOrgId = flags.target;
57
57
  if (!orgId || !domain || !targetOrgId)
58
- error("Missing required arguments.\nUsage: myapi domain assign <domain> --org <id> --target <target_org_id>\n(Or set defaults via: myapi auth config set-org <id> / set-domain <domain>)");
58
+ error("Missing required arguments.\nUsage: myapi domain assign <domain> --org <id> --target <target_org_id>\n(Set defaults: myapi auth config set-org <id> / myapi auth config set-domain <domain>)");
59
59
  await sdkDomain.assignDomain(config.api_key, orgId, domain, targetOrgId);
60
60
  success(`Assigned ${domain} to org ${targetOrgId}`);
61
61
  }
@@ -64,7 +64,7 @@ export async function unassign(domainArg, flags) {
64
64
  const orgId = flags.org || config.default_org;
65
65
  const domain = domainArg || config.default_domain;
66
66
  if (!orgId || !domain)
67
- error("Missing required arguments.\nUsage: myapi domain unassign <domain> --org <id>\n(Or set defaults via: myapi auth config set-org <id> / set-domain <domain>)");
67
+ error("Missing required arguments.\nUsage: myapi domain unassign <domain> --org <id>\n(Set defaults: myapi auth config set-org <id> / myapi auth config set-domain <domain>)");
68
68
  await sdkDomain.unassignDomain(config.api_key, orgId, domain);
69
69
  success(`Unassigned ${domain} from org ${orgId}`);
70
70
  }
@@ -73,7 +73,7 @@ export async function status(domainArg, flags) {
73
73
  const orgId = flags.org || config.default_org;
74
74
  const domain = domainArg || config.default_domain;
75
75
  if (!orgId || !domain)
76
- error("Missing required arguments.\nUsage: myapi domain status <domain> --org <id>\n(Or set defaults via: myapi auth config set-org <id> / set-domain <domain>)");
76
+ error("Missing required arguments.\nUsage: myapi domain status <domain> --org <id>\n(Set defaults: myapi auth config set-org <id> / myapi auth config set-domain <domain>)");
77
77
  const res = await sdkDomain.getDomainStatus(config.api_key, orgId, domain);
78
78
  const display = {
79
79
  domain: res.domain,
@@ -88,7 +88,7 @@ export async function settings(domainArg, flags) {
88
88
  const orgId = flags.org || config.default_org;
89
89
  const domain = domainArg || config.default_domain;
90
90
  if (!orgId || !domain)
91
- error("Missing required arguments.\nUsage: myapi domain settings <domain> --org <id>\n(Or set defaults via: myapi auth config set-org <id> / set-domain <domain>)");
91
+ error("Missing required arguments.\nUsage: myapi domain settings <domain> --org <id>\n(Set defaults: myapi auth config set-org <id> / myapi auth config set-domain <domain>)");
92
92
  const res = await sdkDomain.getDomainSettings(config.api_key, orgId, domain);
93
93
  printJson(res);
94
94
  }
@@ -97,7 +97,7 @@ export async function updateSettings(domainArg, flags) {
97
97
  const orgId = flags.org || config.default_org;
98
98
  const domain = domainArg || config.default_domain;
99
99
  if (!orgId || !domain)
100
- error("Missing required arguments.\nUsage: myapi domain update-settings <domain> --org <id> [--security=...] [--browser-check=...] [--purge-cache]\n(Or set defaults via: myapi auth config set-org <id> / set-domain <domain>)");
100
+ error("Missing required arguments.\nUsage: myapi domain update-settings <domain> --org <id> [--security=...] [--browser-check=...] [--purge-cache]\n(Set defaults: myapi auth config set-org <id> / myapi auth config set-domain <domain>)");
101
101
  const payload = {};
102
102
  if (flags.security)
103
103
  payload.security_level = flags.security;
@@ -110,7 +110,7 @@ export async function updateSettings(domainArg, flags) {
110
110
  }
111
111
  export async function run(subcommand, args, flags) {
112
112
  if (!subcommand || (flags.help && !subcommand)) {
113
- info('Usage: myapi domain <subcommand>\n\nSubcommands:\n list List domains\n check Check domain availability\n register Register a domain\n import Import an existing domain\n assign Assign domain to org\n unassign Unassign domain from its current org\n status Get domain status\n settings Get domain settings\n update-settings Update domain settings\n\nNote: All domain commands require the --org <id> flag.');
113
+ info('Usage: myapi domain <subcommand>\n\nSubcommands:\n list List domains\n check Check domain availability\n register Register a domain\n import Import an existing domain\n assign Assign domain to org\n unassign Unassign domain from its current org\n status Get domain status\n settings Get domain settings\n update-settings Update domain settings\n\nTip: Set defaults with "myapi auth config set-org <id>" to skip --org on every command.');
114
114
  return;
115
115
  }
116
116
  if (flags.help) {
@@ -80,22 +80,22 @@ export async function verify(id, flags) {
80
80
  }
81
81
  export async function run(subcommand, args, flags) {
82
82
  if (!subcommand || (flags.help && !subcommand)) {
83
- info('Usage: myapi funnel <subcommand>\n\nSubcommands:\n list List funnels\n create Create a funnel\n get Get funnel details\n delete Delete a funnel\n push Push a raw HTML page to a slug\n verify Verify links and webhooks\n\nNote: All funnel commands require the --org <id> flag.');
83
+ info('Usage: myapi funnel <subcommand>\n\nSubcommands:\n list List funnels\n create Create a funnel\n get Get funnel details\n delete Delete a funnel\n push Push a raw HTML page to a slug\n\nNote: Most funnel commands require the --org <id> flag (or set a default via myapi auth config set-org <id>).');
84
84
  return;
85
85
  }
86
86
  if (flags.help) {
87
87
  if (subcommand === 'list')
88
- info('Usage: myapi funnel list --org <id>');
88
+ info('Usage: myapi funnel list --org <id>\n\nLists all funnels in the organization.\n\nFlags:\n --org <id> Organization ID (or set default via myapi auth config set-org)');
89
89
  else if (subcommand === 'create')
90
- info('Usage: myapi funnel create --org <id>');
90
+ info('Usage: myapi funnel create --org <id>\n\nCreates a new funnel in the organization.\n\nFlags:\n --org <id> Organization ID (or set default via myapi auth config set-org)');
91
91
  else if (subcommand === 'get')
92
- info('Usage: myapi funnel get <id> --org <id>');
92
+ info('Usage: myapi funnel get <id> --org <id>\n\nFetches details of a specific funnel.\n\nFlags:\n --org <id> Organization ID (or set default via myapi auth config set-org)');
93
93
  else if (subcommand === 'delete')
94
- info('Usage: myapi funnel delete <id> --org <id>');
94
+ info('Usage: myapi funnel delete <id> --org <id>\n\nDeletes a funnel permanently.\n\nFlags:\n --org <id> Organization ID (or set default via myapi auth config set-org)');
95
95
  else if (subcommand === 'push')
96
- info('Usage: myapi funnel push [funnel_id] [slug] < index.html\n\nPushes HTML from stdin. Uses your default funnel and slug "/" when omitted.');
97
- else if (subcommand === 'verify')
98
- info('Usage: myapi funnel verify <id> --org <id> [--slug <slug>]\n\nVerifies syntax and structure before pushing.');
96
+ info('Usage: myapi funnel push [funnel_id] [slug] < index.html\n\nPushes an HTML page from stdin to a slug path within a funnel.\nUses your configured default funnel and slug "/" when arguments are omitted.\n\nFlags:\n --org <id> Organization ID\n --slug <path> Target slug path (default: /)');
97
+ else if (subcommand === 'pull')
98
+ info('Usage: myapi funnel pull [funnel_id] [slug]\n\nFetches the HTML content of a funnel page.');
99
99
  return;
100
100
  }
101
101
  if (subcommand === 'list')
@@ -4,15 +4,18 @@ import { success, error, printTable, info, printJson } from '../output.js';
4
4
  import * as readline from 'readline';
5
5
  export async function createNew(flags) {
6
6
  if (flags.help) {
7
- info('Usage: myapi keys create\n\nCreates a new API key. You will be prompted to enter a name for the key.');
7
+ info('Usage: myapi auth api-keys create [--name <name>]\n\nCreates a new API key.\n\nFlags:\n --name <name> Key name (skips prompt)');
8
8
  return;
9
9
  }
10
10
  const config = requireConfig();
11
- const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
12
- const name = await new Promise(resolve => rl.question('Enter a name for the new key: ', resolve));
13
- rl.close();
11
+ let name = flags.name || '';
12
+ if (!name) {
13
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
14
+ name = await new Promise(resolve => rl.question('Enter a name for the new key: ', resolve));
15
+ rl.close();
16
+ }
14
17
  if (!name.trim()) {
15
- error('Key name cannot be empty.');
18
+ error('Key name cannot be empty. Use --name <name>');
16
19
  return;
17
20
  }
18
21
  const keyInfo = await hq.createApiKey(config.api_key, name.trim());
@@ -137,14 +137,14 @@ export async function importKey(apiKey, flags) {
137
137
  }
138
138
  catch { /* non-fatal */ }
139
139
  const wantsSkills = flags['install-skills'] ? true : flags['no-skills'] ? false : true;
140
- addAccount({ api_key: apiKey, account_id: accountId, pin: '', email, default_org: defaultOrg, default_funnel: defaultFunnel, skills_installed: wantsSkills });
140
+ addAccount({ api_key: apiKey, account_id: accountId, email, default_org: defaultOrg, default_funnel: defaultFunnel, skills_installed: wantsSkills });
141
141
  success(`› ✓ Key imported${email ? ` · ${email}` : ''}`);
142
142
  if (wantsSkills)
143
143
  await installSkills();
144
144
  }
145
145
  export async function setup(flags = {}) {
146
146
  if (flags.help) {
147
- info('Usage: myapi auth setup [--anonymous] [--yes] [--install-skills|--no-skills]\n\nFlags:\n --anonymous Skip registration, create anonymous account\n --yes Skip confirmation prompts\n --install-skills Auto-install skills pack\n --no-skills Skip skills installation');
147
+ info('Usage: myapi auth setup [--anonymous] [--yes] [--install-skills|--no-skills]\n\nConfigures your account and stores your default org and funnel so you don\'t need to pass --org or --funnel on every command.\n\nFlags:\n --anonymous Skip registration, create anonymous account\n --yes Skip confirmation prompts\n --install-skills Auto-install skills pack\n --no-skills Skip skills installation');
148
148
  return;
149
149
  }
150
150
  info('› Configuring MyAPI…');
@@ -189,7 +189,7 @@ export async function setup(flags = {}) {
189
189
  const skillsFromFlag = flags['install-skills'] ? true : flags['no-skills'] ? false : null;
190
190
  try {
191
191
  const useAnon = flags.anonymous || flags.anon;
192
- const createAns = useAnon ? 'n' : await ask(rl, '› Create an account? (Y/n) ');
192
+ const createAns = useAnon ? 'n' : await ask(rl, '› Register with email? (Y/n, or N to continue anonymously) ');
193
193
  if (yn(createAns)) {
194
194
  const data = await registeredFlow(rl);
195
195
  apiKey = data.api_key;
@@ -213,7 +213,6 @@ export async function setup(flags = {}) {
213
213
  addAccount({
214
214
  api_key: apiKey,
215
215
  account_id: accountId,
216
- pin: '',
217
216
  email: email || undefined,
218
217
  default_org: defaultOrg,
219
218
  default_funnel: defaultFunnel,
@@ -1,4 +1,4 @@
1
1
  export declare function checkForUpdate(currentVersion: string): Promise<void>;
2
- export declare function update(): Promise<void>;
2
+ export declare function update(flags?: Record<string, string | boolean>): Promise<void>;
3
3
  export declare function latestVersion(): Promise<string | null>;
4
4
  export declare function isNewer(latest: string, current: string): boolean;
@@ -28,7 +28,11 @@ export async function checkForUpdate(currentVersion) {
28
28
  }
29
29
  }
30
30
  // myapi update — explicit update, same logic as auto-update.
31
- export async function update() {
31
+ export async function update(flags = {}) {
32
+ if (flags.help) {
33
+ info('Usage: myapi update\n\nUpdates the MyAPI CLI and skills pack to the latest published version.\nEquivalent to: npm install -g @myapihq/cli');
34
+ return;
35
+ }
32
36
  info('› Checking for updates…');
33
37
  try {
34
38
  const res = await fetch(REGISTRY_URL, { signal: AbortSignal.timeout(5000) });
package/dist/config.d.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  export interface AccountEntry {
2
2
  api_key: string;
3
3
  account_id: string;
4
- pin: string;
5
4
  email?: string;
6
5
  default_org?: string;
7
6
  default_funnel?: string;
package/dist/config.js CHANGED
@@ -34,7 +34,7 @@ export function loadConfig() {
34
34
  const envKey = process.env.MYAPI_API_KEY || process.env.MYAPI_KEY;
35
35
  const full = loadFullConfig();
36
36
  if (!full && envKey)
37
- return { api_key: envKey, account_id: '', pin: '' };
37
+ return { api_key: envKey, account_id: '' };
38
38
  if (!full)
39
39
  return null;
40
40
  const active = full.accounts[full.active] ?? full.accounts[0];
package/dist/index.js CHANGED
@@ -41,25 +41,35 @@ async function main() {
41
41
  try {
42
42
  switch (command) {
43
43
  case 'auth':
44
- if (!subcommand || flags.help) {
45
- info('Usage: myapi auth <subcommand>\n\nSubcommands:\n setup Configure your account\n whoami Show current account\n signup Upgrade anonymous account to registered\n switch Switch between accounts\n config Manage CLI defaults (org_id, domain…)\n install-skills Install the MyAPI skills pack\n api-keys Manage API keys');
44
+ if (!subcommand || (flags.help && !subcommand)) {
45
+ info('Usage: myapi auth <subcommand>\n\nSubcommands:\n setup Configure your account\n import-key Import an existing API key non-interactively\n whoami Show current account\n signup Upgrade anonymous account to registered\n switch [index] Switch between accounts\n config Manage CLI defaults (org_id, domain…)\n install-skills Install the MyAPI skills pack\n api-keys Manage API keys');
46
46
  break;
47
47
  }
48
48
  if (subcommand === 'setup')
49
- await setupCmd.setup();
49
+ await setupCmd.setup(flags);
50
+ else if (subcommand === 'import-key')
51
+ await setupCmd.importKey(restArgs[0], flags);
50
52
  else if (subcommand === 'whoami')
51
- await authCmd.whoami();
53
+ await authCmd.whoami(flags);
52
54
  else if (subcommand === 'signup')
53
- await authCmd.signup();
55
+ await authCmd.signup(flags);
54
56
  else if (subcommand === 'switch')
55
- await authCmd.switchCmd();
57
+ await authCmd.switchCmd(flags, restArgs[0]);
56
58
  else if (subcommand === 'install-skills') {
59
+ if (flags.help) {
60
+ info('Usage: myapi auth install-skills\n\nInstalls the MyAPI skills pack for Claude, Gemini, and Cursor agents.');
61
+ break;
62
+ }
57
63
  await setupCmd.installSkills();
58
64
  success('› Skills installed.');
59
65
  }
60
66
  else if (subcommand === 'config')
61
67
  await configCmd.run(restArgs[0], restArgs.slice(1), flags);
62
68
  else if (subcommand === 'api-keys') {
69
+ if (flags.help && !restArgs[0]) {
70
+ info('Usage: myapi auth api-keys <subcommand>\n\nSubcommands:\n list List all API keys\n create Create a new API key\n revoke <id> Revoke an API key by ID');
71
+ break;
72
+ }
63
73
  if (!restArgs[0]) {
64
74
  info('Usage: myapi auth api-keys <list|create|revoke>');
65
75
  break;
@@ -75,7 +85,7 @@ async function main() {
75
85
  info('Unknown subcommand. Run: myapi auth --help');
76
86
  break;
77
87
  case 'update':
78
- await updateCmd.update();
88
+ await updateCmd.update(flags);
79
89
  break;
80
90
  case 'org':
81
91
  if (!subcommand || (flags.help && !subcommand)) {
@@ -117,6 +127,13 @@ async function main() {
117
127
  case 'funnel':
118
128
  await funnelCmd.run(subcommand, restArgs, flags);
119
129
  break;
130
+ // Convenience aliases
131
+ case 'setup':
132
+ await setupCmd.setup(flags);
133
+ break;
134
+ case 'config':
135
+ await configCmd.run(subcommand, restArgs, flags);
136
+ break;
120
137
  default:
121
138
  error(`Unknown command: ${command}. Run "myapi" for available commands.`);
122
139
  }
@@ -138,7 +155,7 @@ function printHelp() {
138
155
  myapi funnel create
139
156
  echo '<h1>Hello!</h1>' | myapi funnel push <funnel_id> /`
140
157
  : `Quick start:
141
- myapi auth setup`;
158
+ myapi auth setup --help`;
142
159
  info(`myapi - MyAPI command-line interface
143
160
 
144
161
  Usage: myapi <command> [subcommand] [args]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@myapihq/cli",
3
- "version": "1.0.40",
3
+ "version": "1.0.46",
4
4
  "description": "MyAPI command-line interface",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -42,7 +42,11 @@ async function patch(path: string, body: unknown, apiKey: string): Promise<unkno
42
42
  }
43
43
 
44
44
  // myapi auth signup — upgrade anonymous session to registered account.
45
- export async function signup() {
45
+ export async function signup(flags: Record<string, string | boolean> = {}) {
46
+ if (flags.help) {
47
+ info('Usage: myapi auth signup\n\nUpgrades an anonymous account to a registered account by linking an email.\nA verification code will be sent — you must enter it interactively.\nIf the email is already in use, adds it as a second account instead.');
48
+ return;
49
+ }
46
50
  const config = loadConfig();
47
51
  if (!config?.api_key) error('Not configured. Run: myapi auth setup');
48
52
  if (!config!.is_anonymous) error('Already registered. Use your existing account.');
@@ -74,11 +78,10 @@ export async function signup() {
74
78
  default_funnel: string;
75
79
  };
76
80
 
77
- const skillsAns = (await ask(rl, ' Install the MyAPI skills pack? (Y/n) ')).trim();
78
- const wantsSkills = yn(skillsAns);
81
+ const skillsFromFlag = flags['install-skills'] ? true : flags['no-skills'] ? false : null;
82
+ const wantsSkills = skillsFromFlag !== null ? skillsFromFlag : yn((await ask(rl, '› Install the MyAPI skills pack? (Y/n) ')).trim());
79
83
 
80
84
  if (upgradeOk) {
81
- // Upgrade: update current account in place.
82
85
  saveConfig({
83
86
  ...config!,
84
87
  api_key: data.api_key,
@@ -91,12 +94,10 @@ export async function signup() {
91
94
  });
92
95
  success(`› Welcome! Account upgraded · ${email}`);
93
96
  } else {
94
- // Add as new account and switch to it.
95
97
  const idx = addAccount({
96
98
  api_key: data.api_key,
97
99
  account_id: data.account_id,
98
100
  email,
99
- pin: '',
100
101
  default_org: data.default_org,
101
102
  default_funnel: data.default_funnel,
102
103
  is_anonymous: false,
@@ -113,7 +114,11 @@ export async function signup() {
113
114
  }
114
115
 
115
116
  // myapi auth whoami — show current session info.
116
- export async function whoami() {
117
+ export async function whoami(flags: Record<string, string | boolean> = {}) {
118
+ if (flags.help) {
119
+ info('Usage: myapi auth whoami\n\nDisplays the active account details: email, account ID, default org, default funnel, account type, and current balance.');
120
+ return;
121
+ }
117
122
  const config = loadConfig();
118
123
  if (!config?.api_key) error('Not configured. Run: myapi auth setup');
119
124
 
@@ -127,12 +132,16 @@ export async function whoami() {
127
132
  const bal = await hq.getBalance(config!.api_key);
128
133
  info(`Balance: ${bal.balance_display} | Credits: ${bal.credits_display}`);
129
134
  } catch {
130
- // Balance fetch is best-effort; don't fail whoami if it errors.
135
+ info(`Balance: (unavailable)`);
131
136
  }
132
137
  }
133
138
 
134
- // myapi auth switch — switch between saved accounts.
135
- export async function switchCmd() {
139
+ // myapi auth switch [index] — switch between saved accounts.
140
+ export async function switchCmd(flags: Record<string, string | boolean> = {}, indexArg?: string) {
141
+ if (flags.help) {
142
+ info('Usage: myapi auth switch [index]\n\nSwitches the active account. Pass an account index to skip the prompt.\n\nExample:\n myapi auth switch 2');
143
+ return;
144
+ }
136
145
  const accounts = listAccounts();
137
146
  if (accounts.length === 0) error('No accounts configured. Run: myapi auth setup');
138
147
  if (accounts.length === 1) {
@@ -147,18 +156,21 @@ export async function switchCmd() {
147
156
  info(` ${a.index + 1}. ${label}${marker}`);
148
157
  }
149
158
 
150
- const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
151
- try {
152
- const ans = (await ask(rl, `› Switch to account (1-${accounts.length})? `)).trim();
153
- const idx = parseInt(ans, 10) - 1;
154
- if (isNaN(idx) || idx < 0 || idx >= accounts.length) {
155
- error('Invalid selection.');
156
- }
157
- if (switchAccount(idx)) {
158
- const a = accounts[idx];
159
- success(`› Switched to ${a.email ?? a.account_id}`);
159
+ let idxStr = indexArg ?? '';
160
+ if (!idxStr) {
161
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
162
+ try {
163
+ idxStr = (await ask(rl, `› Switch to account (1-${accounts.length})? `)).trim();
164
+ } finally {
165
+ rl.close();
160
166
  }
161
- } finally {
162
- rl.close();
167
+ }
168
+ const idx = parseInt(idxStr, 10) - 1;
169
+ if (isNaN(idx) || idx < 0 || idx >= accounts.length) {
170
+ error('Invalid selection.');
171
+ }
172
+ if (switchAccount(idx)) {
173
+ const a = accounts[idx];
174
+ success(`› Switched to ${a.email ?? a.account_id}`);
163
175
  }
164
176
  }
@@ -20,7 +20,7 @@ export async function balance(flags: Record<string, string | boolean>) {
20
20
 
21
21
  export async function history(flags: Record<string, string | boolean>) {
22
22
  if (flags.help) {
23
- info('Usage: myapi billing history [--json]\n\nShows your recent billing transactions and top-ups.');
23
+ info('Usage: myapi billing history [--json]\n\nShows your recent billing transactions and top-ups.\n\nFlags:\n --json Output raw JSON');
24
24
  return;
25
25
  }
26
26
  const config = requireConfig();
@@ -48,7 +48,7 @@ export async function history(flags: Record<string, string | boolean>) {
48
48
 
49
49
  export async function topup(amountStr: string, flags: Record<string, string | boolean>) {
50
50
  if (flags.help) {
51
- info('Usage: myapi billing topup <amount>\n\nAmount is in whole dollars (e.g. "10" charges $10).\nUse --yes to skip confirmation.\nExample: myapi billing topup 10');
51
+ info('Usage: myapi billing topup <amount>\n\nAmount is in whole dollars (e.g. "10" charges $10).\nUse --yes to skip confirmation.\nExample: myapi billing topup 10\n\nFlags:\n --yes Skip confirmation prompt');
52
52
  return;
53
53
  }
54
54
  const amount = Math.round(parseFloat(amountStr));
@@ -6,7 +6,7 @@ export async function check(domainArg: string, flags: Record<string, string | bo
6
6
  const config = requireConfig();
7
7
  const orgId = (flags.org as string) || config.default_org;
8
8
  const domain = domainArg || (config.default_domain as string);
9
- if (!orgId || !domain) error("Missing required arguments.\nUsage: myapi domain check <domain> --org <id>\n(Or set defaults via: myapi auth config set-org <id> / set-domain <domain>)");
9
+ if (!orgId || !domain) error("Missing required arguments.\nUsage: myapi domain check <domain> --org <id>\n(Set defaults: myapi auth config set-org <id> / myapi auth config set-domain <domain>)");
10
10
  const res = await sdkDomain.checkDomain(config.api_key, orgId, domain) as { available: boolean; price_cents: number; price_display?: string; message?: string };
11
11
  if (res.available) {
12
12
  const price = res.price_display || `$${(res.price_cents / 100).toFixed(2)}`;
@@ -20,7 +20,7 @@ export async function register(domainArg: string, flags: Record<string, string |
20
20
  const config = requireConfig();
21
21
  const orgId = (flags.org as string) || config.default_org;
22
22
  const domain = domainArg || (config.default_domain as string);
23
- if (!orgId || !domain) error("Missing required arguments.\nUsage: myapi domain register <domain> --org <id> [--years <num>]\n(Or set defaults via: myapi auth config set-org <id> / set-domain <domain>)");
23
+ if (!orgId || !domain) error("Missing required arguments.\nUsage: myapi domain register <domain> --org <id> [--years <num>]\n(Set defaults: myapi auth config set-org <id> / myapi auth config set-domain <domain>)");
24
24
  const years = parseInt(flags.years as string) || 1;
25
25
  const res = await sdkDomain.registerDomain(config.api_key, orgId, domain, years);
26
26
  success(`Registered ${domain}!\n${JSON.stringify(res, null, 2)}`);
@@ -30,7 +30,7 @@ export async function importDomain(domainArg: string, flags: Record<string, stri
30
30
  const config = requireConfig();
31
31
  const orgId = (flags.org as string) || config.default_org;
32
32
  const domain = domainArg || (config.default_domain as string);
33
- if (!orgId || !domain) error("Missing required arguments.\nUsage: myapi domain import <domain> --org <id> [--namecheap-user <user> --namecheap-key <key>]\n(Or set defaults via: myapi auth config set-org <id> / set-domain <domain>)");
33
+ if (!orgId || !domain) error("Missing required arguments.\nUsage: myapi domain import <domain> --org <id> [--namecheap-user <user> --namecheap-key <key>]\n(Set defaults: myapi auth config set-org <id> / myapi auth config set-domain <domain>)");
34
34
  const payload: { domain: string; namecheap_api_user?: string; namecheap_api_key?: string } = { domain };
35
35
  if (flags['namecheap-user']) payload.namecheap_api_user = flags['namecheap-user'] as string;
36
36
  if (flags['namecheap-key']) payload.namecheap_api_key = flags['namecheap-key'] as string;
@@ -41,7 +41,7 @@ export async function importDomain(domainArg: string, flags: Record<string, stri
41
41
  export async function list(flags: Record<string, string | boolean>) {
42
42
  const config = requireConfig();
43
43
  const orgId = (flags.org as string) || config.default_org;
44
- if (!orgId) error("Missing required arguments.\nUsage: myapi domain list --org <id> [--filter=all|unassigned|org]\n(Or set a default org via: myapi auth config set-org <id>)");
44
+ if (!orgId) error("Missing required arguments.\nUsage: myapi domain list --org <id> [--filter=all|unassigned|org]\n(Set default: myapi auth config set-org <id>)");
45
45
  const filter = flags.filter as 'all' | 'unassigned' | 'org' | undefined;
46
46
  const domains = await sdkDomain.listDomains(config.api_key, orgId, filter);
47
47
  printTable(domains as unknown as Record<string, unknown>[]);
@@ -52,7 +52,7 @@ export async function assign(domainArg: string, flags: Record<string, string | b
52
52
  const orgId = (flags.org as string) || config.default_org;
53
53
  const domain = domainArg || (config.default_domain as string);
54
54
  const targetOrgId = flags.target as string;
55
- if (!orgId || !domain || !targetOrgId) error("Missing required arguments.\nUsage: myapi domain assign <domain> --org <id> --target <target_org_id>\n(Or set defaults via: myapi auth config set-org <id> / set-domain <domain>)");
55
+ if (!orgId || !domain || !targetOrgId) error("Missing required arguments.\nUsage: myapi domain assign <domain> --org <id> --target <target_org_id>\n(Set defaults: myapi auth config set-org <id> / myapi auth config set-domain <domain>)");
56
56
  await sdkDomain.assignDomain(config.api_key, orgId, domain, targetOrgId);
57
57
  success(`Assigned ${domain} to org ${targetOrgId}`);
58
58
  }
@@ -61,7 +61,7 @@ export async function unassign(domainArg: string, flags: Record<string, string |
61
61
  const config = requireConfig();
62
62
  const orgId = (flags.org as string) || config.default_org;
63
63
  const domain = domainArg || (config.default_domain as string);
64
- if (!orgId || !domain) error("Missing required arguments.\nUsage: myapi domain unassign <domain> --org <id>\n(Or set defaults via: myapi auth config set-org <id> / set-domain <domain>)");
64
+ if (!orgId || !domain) error("Missing required arguments.\nUsage: myapi domain unassign <domain> --org <id>\n(Set defaults: myapi auth config set-org <id> / myapi auth config set-domain <domain>)");
65
65
  await sdkDomain.unassignDomain(config.api_key, orgId, domain);
66
66
  success(`Unassigned ${domain} from org ${orgId}`);
67
67
  }
@@ -70,7 +70,7 @@ export async function status(domainArg: string, flags: Record<string, string | b
70
70
  const config = requireConfig();
71
71
  const orgId = (flags.org as string) || config.default_org;
72
72
  const domain = domainArg || (config.default_domain as string);
73
- if (!orgId || !domain) error("Missing required arguments.\nUsage: myapi domain status <domain> --org <id>\n(Or set defaults via: myapi auth config set-org <id> / set-domain <domain>)");
73
+ if (!orgId || !domain) error("Missing required arguments.\nUsage: myapi domain status <domain> --org <id>\n(Set defaults: myapi auth config set-org <id> / myapi auth config set-domain <domain>)");
74
74
  const res = await sdkDomain.getDomainStatus(config.api_key, orgId, domain);
75
75
  const display: Record<string, unknown> = {
76
76
  domain: res.domain,
@@ -84,7 +84,7 @@ export async function settings(domainArg: string, flags: Record<string, string |
84
84
  const config = requireConfig();
85
85
  const orgId = (flags.org as string) || config.default_org;
86
86
  const domain = domainArg || (config.default_domain as string);
87
- if (!orgId || !domain) error("Missing required arguments.\nUsage: myapi domain settings <domain> --org <id>\n(Or set defaults via: myapi auth config set-org <id> / set-domain <domain>)");
87
+ if (!orgId || !domain) error("Missing required arguments.\nUsage: myapi domain settings <domain> --org <id>\n(Set defaults: myapi auth config set-org <id> / myapi auth config set-domain <domain>)");
88
88
  const res = await sdkDomain.getDomainSettings(config.api_key, orgId, domain);
89
89
  printJson(res);
90
90
  }
@@ -93,7 +93,7 @@ export async function updateSettings(domainArg: string, flags: Record<string, st
93
93
  const config = requireConfig();
94
94
  const orgId = (flags.org as string) || config.default_org;
95
95
  const domain = domainArg || (config.default_domain as string);
96
- if (!orgId || !domain) error("Missing required arguments.\nUsage: myapi domain update-settings <domain> --org <id> [--security=...] [--browser-check=...] [--purge-cache]\n(Or set defaults via: myapi auth config set-org <id> / set-domain <domain>)");
96
+ if (!orgId || !domain) error("Missing required arguments.\nUsage: myapi domain update-settings <domain> --org <id> [--security=...] [--browser-check=...] [--purge-cache]\n(Set defaults: myapi auth config set-org <id> / myapi auth config set-domain <domain>)");
97
97
  const payload: any = {};
98
98
  if (flags.security) payload.security_level = flags.security as string;
99
99
  if (flags['browser-check']) payload.browser_check = flags['browser-check'] as string;
@@ -105,7 +105,7 @@ export async function updateSettings(domainArg: string, flags: Record<string, st
105
105
 
106
106
  export async function run(subcommand: string | undefined, args: string[], flags: Record<string, string | boolean>) {
107
107
  if (!subcommand || (flags.help && !subcommand)) {
108
- info('Usage: myapi domain <subcommand>\n\nSubcommands:\n list List domains\n check Check domain availability\n register Register a domain\n import Import an existing domain\n assign Assign domain to org\n unassign Unassign domain from its current org\n status Get domain status\n settings Get domain settings\n update-settings Update domain settings\n\nNote: All domain commands require the --org <id> flag.');
108
+ info('Usage: myapi domain <subcommand>\n\nSubcommands:\n list List domains\n check Check domain availability\n register Register a domain\n import Import an existing domain\n assign Assign domain to org\n unassign Unassign domain from its current org\n status Get domain status\n settings Get domain settings\n update-settings Update domain settings\n\nTip: Set defaults with "myapi auth config set-org <id>" to skip --org on every command.');
109
109
  return;
110
110
  }
111
111
 
@@ -50,7 +50,7 @@ export async function push(id: string, slug: string, flags: Record<string, strin
50
50
  if (!orgId || !funnelId) {
51
51
  error("Missing required arguments.\nUsage: myapi funnel push [funnel_id] [slug] < index.html\n(Defaults to your configured funnel and slug '/' when omitted)");
52
52
  }
53
-
53
+
54
54
  const html = await new Promise<string>((resolve, reject) => {
55
55
  let data = '';
56
56
  process.stdin.setEncoding('utf-8');
@@ -85,17 +85,17 @@ export async function verify(id: string, flags: Record<string, string | boolean>
85
85
 
86
86
  export async function run(subcommand: string | undefined, args: string[], flags: Record<string, string | boolean>) {
87
87
  if (!subcommand || (flags.help && !subcommand)) {
88
- info('Usage: myapi funnel <subcommand>\n\nSubcommands:\n list List funnels\n create Create a funnel\n get Get funnel details\n delete Delete a funnel\n push Push a raw HTML page to a slug\n verify Verify links and webhooks\n\nNote: All funnel commands require the --org <id> flag.');
88
+ info('Usage: myapi funnel <subcommand>\n\nSubcommands:\n list List funnels\n create Create a funnel\n get Get funnel details\n delete Delete a funnel\n push Push a raw HTML page to a slug\n\nNote: Most funnel commands require the --org <id> flag (or set a default via myapi auth config set-org <id>).');
89
89
  return;
90
90
  }
91
-
91
+
92
92
  if (flags.help) {
93
- if (subcommand === 'list') info('Usage: myapi funnel list --org <id>');
94
- else if (subcommand === 'create') info('Usage: myapi funnel create --org <id>');
95
- else if (subcommand === 'get') info('Usage: myapi funnel get <id> --org <id>');
96
- else if (subcommand === 'delete') info('Usage: myapi funnel delete <id> --org <id>');
97
- else if (subcommand === 'push') info('Usage: myapi funnel push [funnel_id] [slug] < index.html\n\nPushes HTML from stdin. Uses your default funnel and slug "/" when omitted.');
98
- else if (subcommand === 'verify') info('Usage: myapi funnel verify <id> --org <id> [--slug <slug>]\n\nVerifies syntax and structure before pushing.');
93
+ if (subcommand === 'list') info('Usage: myapi funnel list --org <id>\n\nLists all funnels in the organization.\n\nFlags:\n --org <id> Organization ID (or set default via myapi auth config set-org)');
94
+ else if (subcommand === 'create') info('Usage: myapi funnel create --org <id>\n\nCreates a new funnel in the organization.\n\nFlags:\n --org <id> Organization ID (or set default via myapi auth config set-org)');
95
+ else if (subcommand === 'get') info('Usage: myapi funnel get <id> --org <id>\n\nFetches details of a specific funnel.\n\nFlags:\n --org <id> Organization ID (or set default via myapi auth config set-org)');
96
+ else if (subcommand === 'delete') info('Usage: myapi funnel delete <id> --org <id>\n\nDeletes a funnel permanently.\n\nFlags:\n --org <id> Organization ID (or set default via myapi auth config set-org)');
97
+ else if (subcommand === 'push') info('Usage: myapi funnel push [funnel_id] [slug] < index.html\n\nPushes an HTML page from stdin to a slug path within a funnel.\nUses your configured default funnel and slug "/" when arguments are omitted.\n\nFlags:\n --org <id> Organization ID\n --slug <path> Target slug path (default: /)');
98
+ else if (subcommand === 'pull') info('Usage: myapi funnel pull [funnel_id] [slug]\n\nFetches the HTML content of a funnel page.');
99
99
  return;
100
100
  }
101
101
 
@@ -5,19 +5,20 @@ import * as readline from 'readline';
5
5
 
6
6
  export async function createNew(flags: Record<string, string | boolean>) {
7
7
  if (flags.help) {
8
- info('Usage: myapi keys create\n\nCreates a new API key. You will be prompted to enter a name for the key.');
8
+ info('Usage: myapi auth api-keys create [--name <name>]\n\nCreates a new API key.\n\nFlags:\n --name <name> Key name (skips prompt)');
9
9
  return;
10
10
  }
11
11
  const config = requireConfig();
12
- const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
13
- const name = await new Promise<string>(resolve => rl.question('Enter a name for the new key: ', resolve));
14
- rl.close();
15
-
12
+ let name = (flags.name as string) || '';
13
+ if (!name) {
14
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
15
+ name = await new Promise<string>(resolve => rl.question('Enter a name for the new key: ', resolve));
16
+ rl.close();
17
+ }
16
18
  if (!name.trim()) {
17
- error('Key name cannot be empty.');
19
+ error('Key name cannot be empty. Use --name <name>');
18
20
  return;
19
21
  }
20
-
21
22
  const keyInfo = await hq.createApiKey(config.api_key, name.trim());
22
23
  success(`New API key created!\n\nName: ${keyInfo.prefix}...\nKey: ${keyInfo.api_key}\n\nMake sure to copy your new API key now. You won't be able to see it again!`);
23
24
  }
@@ -179,14 +179,14 @@ export async function importKey(apiKey: string, flags: Record<string, string | b
179
179
 
180
180
  const wantsSkills = flags['install-skills'] ? true : flags['no-skills'] ? false : true;
181
181
 
182
- addAccount({ api_key: apiKey, account_id: accountId, pin: '', email, default_org: defaultOrg, default_funnel: defaultFunnel, skills_installed: wantsSkills });
182
+ addAccount({ api_key: apiKey, account_id: accountId, email, default_org: defaultOrg, default_funnel: defaultFunnel, skills_installed: wantsSkills });
183
183
  success(`› ✓ Key imported${email ? ` · ${email}` : ''}`);
184
184
  if (wantsSkills) await installSkills();
185
185
  }
186
186
 
187
187
  export async function setup(flags: Record<string, string | boolean> = {}) {
188
188
  if (flags.help) {
189
- info('Usage: myapi auth setup [--anonymous] [--yes] [--install-skills|--no-skills]\n\nFlags:\n --anonymous Skip registration, create anonymous account\n --yes Skip confirmation prompts\n --install-skills Auto-install skills pack\n --no-skills Skip skills installation');
189
+ info('Usage: myapi auth setup [--anonymous] [--yes] [--install-skills|--no-skills]\n\nConfigures your account and stores your default org and funnel so you don\'t need to pass --org or --funnel on every command.\n\nFlags:\n --anonymous Skip registration, create anonymous account\n --yes Skip confirmation prompts\n --install-skills Auto-install skills pack\n --no-skills Skip skills installation');
190
190
  return;
191
191
  }
192
192
 
@@ -238,7 +238,7 @@ export async function setup(flags: Record<string, string | boolean> = {}) {
238
238
 
239
239
  try {
240
240
  const useAnon = flags.anonymous || flags.anon;
241
- const createAns = useAnon ? 'n' : await ask(rl, '› Create an account? (Y/n) ');
241
+ const createAns = useAnon ? 'n' : await ask(rl, '› Register with email? (Y/n, or N to continue anonymously) ');
242
242
 
243
243
  if (yn(createAns)) {
244
244
  const data = await registeredFlow(rl);
@@ -264,7 +264,6 @@ export async function setup(flags: Record<string, string | boolean> = {}) {
264
264
  addAccount({
265
265
  api_key: apiKey,
266
266
  account_id: accountId,
267
- pin: '',
268
267
  email: email || undefined,
269
268
  default_org: defaultOrg,
270
269
  default_funnel: defaultFunnel,
@@ -30,7 +30,11 @@ export async function checkForUpdate(currentVersion: string): Promise<void> {
30
30
  }
31
31
 
32
32
  // myapi update — explicit update, same logic as auto-update.
33
- export async function update(): Promise<void> {
33
+ export async function update(flags: Record<string, string | boolean> = {}): Promise<void> {
34
+ if (flags.help) {
35
+ info('Usage: myapi update\n\nUpdates the MyAPI CLI and skills pack to the latest published version.\nEquivalent to: npm install -g @myapihq/cli');
36
+ return;
37
+ }
34
38
  info('› Checking for updates…');
35
39
  try {
36
40
  const res = await fetch(REGISTRY_URL, { signal: AbortSignal.timeout(5000) });
package/src/config.ts CHANGED
@@ -5,7 +5,6 @@ import * as os from 'os';
5
5
  export interface AccountEntry {
6
6
  api_key: string;
7
7
  account_id: string;
8
- pin: string;
9
8
  email?: string;
10
9
  default_org?: string;
11
10
  default_funnel?: string;
@@ -60,7 +59,7 @@ export function loadConfig(): Config | null {
60
59
  const envKey = process.env.MYAPI_API_KEY || process.env.MYAPI_KEY;
61
60
  const full = loadFullConfig();
62
61
 
63
- if (!full && envKey) return { api_key: envKey, account_id: '', pin: '' };
62
+ if (!full && envKey) return { api_key: envKey, account_id: '' };
64
63
  if (!full) return null;
65
64
 
66
65
  const active = full.accounts[full.active] ?? full.accounts[0];
package/src/index.ts CHANGED
@@ -47,19 +47,28 @@ async function main() {
47
47
  try {
48
48
  switch (command) {
49
49
  case 'auth':
50
- if (!subcommand || flags.help) {
51
- info('Usage: myapi auth <subcommand>\n\nSubcommands:\n setup Configure your account\n whoami Show current account\n signup Upgrade anonymous account to registered\n switch Switch between accounts\n config Manage CLI defaults (org_id, domain…)\n install-skills Install the MyAPI skills pack\n api-keys Manage API keys');
50
+ if (!subcommand || (flags.help && !subcommand)) {
51
+ info('Usage: myapi auth <subcommand>\n\nSubcommands:\n setup Configure your account\n import-key Import an existing API key non-interactively\n whoami Show current account\n signup Upgrade anonymous account to registered\n switch [index] Switch between accounts\n config Manage CLI defaults (org_id, domain…)\n install-skills Install the MyAPI skills pack\n api-keys Manage API keys');
52
52
  break;
53
53
  }
54
- if (subcommand === 'setup') await setupCmd.setup();
55
- else if (subcommand === 'whoami') await authCmd.whoami();
56
- else if (subcommand === 'signup') await authCmd.signup();
57
- else if (subcommand === 'switch') await authCmd.switchCmd();
54
+ if (subcommand === 'setup') await setupCmd.setup(flags);
55
+ else if (subcommand === 'import-key') await setupCmd.importKey(restArgs[0], flags);
56
+ else if (subcommand === 'whoami') await authCmd.whoami(flags);
57
+ else if (subcommand === 'signup') await authCmd.signup(flags);
58
+ else if (subcommand === 'switch') await authCmd.switchCmd(flags, restArgs[0]);
58
59
  else if (subcommand === 'install-skills') {
60
+ if (flags.help) {
61
+ info('Usage: myapi auth install-skills\n\nInstalls the MyAPI skills pack for Claude, Gemini, and Cursor agents.');
62
+ break;
63
+ }
59
64
  await setupCmd.installSkills();
60
65
  success('› Skills installed.');
61
66
  } else if (subcommand === 'config') await configCmd.run(restArgs[0], restArgs.slice(1), flags);
62
67
  else if (subcommand === 'api-keys') {
68
+ if (flags.help && !restArgs[0]) {
69
+ info('Usage: myapi auth api-keys <subcommand>\n\nSubcommands:\n list List all API keys\n create Create a new API key\n revoke <id> Revoke an API key by ID');
70
+ break;
71
+ }
63
72
  if (!restArgs[0]) { info('Usage: myapi auth api-keys <list|create|revoke>'); break; }
64
73
  if (restArgs[0] === 'create') await keysCmd.createNew(flags);
65
74
  else if (restArgs[0] === 'list') await keysCmd.list(flags);
@@ -67,7 +76,7 @@ async function main() {
67
76
  } else info('Unknown subcommand. Run: myapi auth --help');
68
77
  break;
69
78
  case 'update':
70
- await updateCmd.update();
79
+ await updateCmd.update(flags);
71
80
  break;
72
81
  case 'org':
73
82
  if (!subcommand || (flags.help && !subcommand)) {
@@ -98,6 +107,13 @@ async function main() {
98
107
  case 'funnel':
99
108
  await funnelCmd.run(subcommand, restArgs, flags);
100
109
  break;
110
+ // Convenience aliases
111
+ case 'setup':
112
+ await setupCmd.setup(flags);
113
+ break;
114
+ case 'config':
115
+ await configCmd.run(subcommand, restArgs, flags);
116
+ break;
101
117
  default:
102
118
  error(`Unknown command: ${command}. Run "myapi" for available commands.`);
103
119
  }
@@ -117,7 +133,7 @@ function printHelp() {
117
133
  myapi funnel create
118
134
  echo '<h1>Hello!</h1>' | myapi funnel push <funnel_id> /`
119
135
  : `Quick start:
120
- myapi auth setup`;
136
+ myapi auth setup --help`;
121
137
  info(`myapi - MyAPI command-line interface
122
138
 
123
139
  Usage: myapi <command> [subcommand] [args]
package/thank-you.html ADDED
@@ -0,0 +1,56 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Thank You</title>
7
+ <style>
8
+ body {
9
+ font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
10
+ background-color: #f3f4f6;
11
+ color: #1f2937;
12
+ display: flex;
13
+ align-items: center;
14
+ justify-content: center;
15
+ height: 100vh;
16
+ margin: 0;
17
+ text-align: center;
18
+ }
19
+ .container {
20
+ background: white;
21
+ padding: 3rem;
22
+ border-radius: 1rem;
23
+ box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
24
+ max-width: 400px;
25
+ width: 90%;
26
+ }
27
+ h1 {
28
+ margin-top: 0;
29
+ color: #4f46e5;
30
+ font-size: 2.25rem;
31
+ margin-bottom: 0.5rem;
32
+ }
33
+ p {
34
+ color: #6b7280;
35
+ line-height: 1.6;
36
+ margin-bottom: 0;
37
+ font-size: 1.125rem;
38
+ }
39
+ .icon {
40
+ width: 64px;
41
+ height: 64px;
42
+ color: #10b981;
43
+ margin-bottom: 1.5rem;
44
+ }
45
+ </style>
46
+ </head>
47
+ <body>
48
+ <div class="container">
49
+ <svg class="icon" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
50
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"></path>
51
+ </svg>
52
+ <h1>Thank You!</h1>
53
+ <p>We've received your request and will be in touch shortly.</p>
54
+ </div>
55
+ </body>
56
+ </html>