@myapihq/cli 1.0.60 → 1.0.63

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.
@@ -41,7 +41,7 @@ async function patch(path, body, apiKey) {
41
41
  // myapi auth link — upgrade anonymous session to registered account.
42
42
  export async function link(flags = {}, emailArg) {
43
43
  if (flags.help) {
44
- info('Usage: myapi auth link [email]\n\nAttaches a verified email to your current anonymous account, converting it into\na registered account. A one-time code will be sent to the email to confirm.\n\nIf that email already belongs to an existing MyAPI account, you will be signed\ninto that account instead it is added as a second active session alongside\nyour current one.\n\nTo create a brand-new account from scratch, use: myapi auth setup');
44
+ info('Usage: myapi auth link [email]\n\nUpgrades your anonymous account by attaching a verified email address.\nA one-time code will be sent to your inbox — paste it at the prompt to confirm.\nThis is an interactive command; it will ask for the code before completing.\n\nIf that email already belongs to an existing MyAPI account, your anonymous\naccount is NOT merged. Instead, the existing account is added as a second\nactive session and you can switch between them with: myapi auth switch\n\nTo create a completely new account from scratch, use: myapi auth setup');
45
45
  return;
46
46
  }
47
47
  const config = loadConfig();
@@ -144,7 +144,7 @@ export async function whoami(flags = {}) {
144
144
  // myapi auth switch [index] — switch between saved accounts.
145
145
  export async function switchCmd(flags = {}, indexArg) {
146
146
  if (flags.help) {
147
- 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');
147
+ info('Usage: myapi auth switch [index]\n\nSwitches the active account. Run without arguments to see a numbered list\nof accounts and choose interactively.\n\nPass an index number to switch non-interactively:\n myapi auth switch 2\n\nNote: index numbers may change as accounts are added. For scripting,\ncheck the list first with: myapi auth switch (no args)');
148
148
  return;
149
149
  }
150
150
  const accounts = listAccounts();
@@ -4,7 +4,7 @@ import { success, error, info } from '../output.js';
4
4
  const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
5
5
  export async function setOrg(id, flags) {
6
6
  if (!id || flags.help) {
7
- info("Usage: myapi config set-org <id>\n\nSets a default organization ID for subsequent commands.");
7
+ info("Usage: myapi config set-org <id>\n\nSets the default organization for all commands that require --org.\nThe ID is validated against the API before saving.\n\nExample:\n myapi auth config set-org xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx");
8
8
  return;
9
9
  }
10
10
  if (!UUID_RE.test(id))
@@ -18,7 +18,7 @@ export async function setOrg(id, flags) {
18
18
  }
19
19
  export async function setFunnel(id, flags) {
20
20
  if (!id || flags.help) {
21
- info("Usage: myapi config set-funnel <id>\n\nSets a default funnel ID for subsequent commands.");
21
+ info("Usage: myapi config set-funnel <id>\n\nSets the default funnel. The funnel must belong to your current default org.\nThe ID is validated against the API before saving.\n\nExample:\n myapi auth config set-funnel xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx");
22
22
  return;
23
23
  }
24
24
  if (!UUID_RE.test(id))
@@ -35,7 +35,7 @@ export async function setFunnel(id, flags) {
35
35
  }
36
36
  export async function setDomain(domain, flags) {
37
37
  if (!domain || flags.help) {
38
- info("Usage: myapi config set-domain <domain>\n\nSets a default domain for subsequent commands.");
38
+ info("Usage: myapi config set-domain <domain>\n\nSets the default domain used by domain commands when --domain is omitted.\n\nExample:\n myapi auth config set-domain example.com");
39
39
  return;
40
40
  }
41
41
  const config = requireConfig();
@@ -45,7 +45,7 @@ export async function setDomain(domain, flags) {
45
45
  }
46
46
  export async function view(flags) {
47
47
  if (flags.help) {
48
- info("Usage: myapi config view\n\nViews current config settings.");
48
+ info("Usage: myapi config view\n\nShows the currently configured defaults: default org, funnel, and domain.");
49
49
  return;
50
50
  }
51
51
  const config = requireConfig();
@@ -56,7 +56,7 @@ export async function view(flags) {
56
56
  export async function run(subcommand, args, flags) {
57
57
  const via = flags._via || 'auth config';
58
58
  if (!subcommand || (flags.help && !subcommand)) {
59
- info(`Usage: myapi ${via} <subcommand>\n\nSubcommands:\n view View current config\n set-org Set default organization\n set-funnel Set default funnel\n set-domain Set default domain`);
59
+ info(`Usage: myapi ${via} <subcommand>\n\nManages CLI defaults (org, funnel, domain) so you don't have to pass --org / --domain on every command.\n\nSubcommands:\n view Show current defaults\n set-org Set default organization (validates access)\n set-funnel Set default funnel (must be owned by default org)\n set-domain Set default domain\n\nExamples:\n myapi auth config set-org <id>\n myapi auth config set-funnel <id>\n myapi auth config view`);
60
60
  return;
61
61
  }
62
62
  if (subcommand === 'view')
@@ -1,6 +1,5 @@
1
1
  export declare function check(domainArg: string, flags: Record<string, string | boolean>): Promise<void>;
2
2
  export declare function register(domainArg: string, flags: Record<string, string | boolean>): Promise<void>;
3
- export declare function importDomain(domainArg: string, flags: Record<string, string | boolean>): Promise<void>;
4
3
  export declare function list(flags: Record<string, string | boolean>): Promise<void>;
5
4
  export declare function assign(domainArg: string, flags: Record<string, string | boolean>): Promise<void>;
6
5
  export declare function unassign(domainArg: string, flags: Record<string, string | boolean>): Promise<void>;
@@ -35,20 +35,6 @@ export async function register(domainArg, flags) {
35
35
  info(`DNS propagation can take a few minutes — track it with: myapi domain status ${domain}`);
36
36
  info(`Your funnel will be live on https://${domain} once propagation completes.`);
37
37
  }
38
- export async function importDomain(domainArg, flags) {
39
- const config = requireConfig();
40
- const orgId = flags.org || config.default_org;
41
- const domain = domainArg || config.default_domain;
42
- if (!orgId || !domain)
43
- 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>)");
44
- const payload = { domain };
45
- if (flags['namecheap-user'])
46
- payload.namecheap_api_user = flags['namecheap-user'];
47
- if (flags['namecheap-key'])
48
- payload.namecheap_api_key = flags['namecheap-key'];
49
- await sdkDomain.importDomain(config.api_key, orgId, payload);
50
- success(`Imported ${domain}`);
51
- }
52
38
  export async function list(flags) {
53
39
  const config = requireConfig();
54
40
  const orgId = flags.org || config.default_org;
@@ -56,6 +42,10 @@ export async function list(flags) {
56
42
  error("Missing required arguments.\nUsage: myapi domain list --org <id> [--filter=all|unassigned|org]\n(Set default: myapi auth config set-org <id>)");
57
43
  const filter = flags.filter;
58
44
  const domains = await sdkDomain.listDomains(config.api_key, orgId, filter);
45
+ if (flags.json) {
46
+ printJson(domains);
47
+ return;
48
+ }
59
49
  if (domains.length === 0) {
60
50
  info('No domains found in this organization. Register one with: myapi domain register <name>');
61
51
  return;
@@ -95,6 +85,8 @@ export async function status(domainArg, flags) {
95
85
  info(`Status: ${res.status}`);
96
86
  if (res.expires_at)
97
87
  info(`Expires: ${formatDate(res.expires_at)}`);
88
+ if (res.status === 'active')
89
+ info(`Note: if recently activated, the SSL certificate may still be provisioning — allow a few minutes before the site is reachable over HTTPS.`);
98
90
  }
99
91
  export async function settings(domainArg, flags) {
100
92
  const config = requireConfig();
@@ -123,28 +115,26 @@ export async function updateSettings(domainArg, flags) {
123
115
  }
124
116
  export async function run(subcommand, args, flags) {
125
117
  if (!subcommand || (flags.help && !subcommand)) {
126
- 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 an 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.');
118
+ info('Usage: myapi domain <subcommand>\n\nSubcommands:\n list List domains\n check Check domain availability\n register Register a domain\n assign Assign domain to an org\n unassign Unassign domain from its current org\n status Get domain status\n settings Get domain settings\n update-settings Update edge/CDN settings\n\nTip: Set defaults with "myapi auth config set-org <id>" to skip --org on every command.');
127
119
  return;
128
120
  }
129
121
  if (flags.help) {
130
122
  if (subcommand === 'list')
131
- info('Usage: myapi domain list --org <id> [--filter=all|unassigned|org]\n\nLists all registered domains in your account.\n --filter=all Lists all domains owned by the account.\n --filter=unassigned Lists domains not assigned to an org.\n --filter=org (Default) Lists domains assigned to the current org.');
123
+ info('Usage: myapi domain list --org <id> [--filter=all|unassigned|org] [--json]\n\nLists all registered domains in your account.\n --filter=all Lists all domains owned by the account.\n --filter=unassigned Lists domains not assigned to an org.\n --filter=org (Default) Lists domains assigned to the current org.\n --json Output raw JSON');
132
124
  else if (subcommand === 'check')
133
125
  info('Usage: myapi domain check <domain> --org <id> [--json]\n\nChecks if a domain name is available for registration.\n\nFlags:\n --json Output raw JSON');
134
126
  else if (subcommand === 'register')
135
- info('Usage: myapi domain register <domain> --org <id> [--years <num>]\n\nRegisters a new domain name.');
136
- else if (subcommand === 'import')
137
- info('Usage: myapi domain import <domain> --org <id> --namecheap-user <user> --namecheap-key <key>\n\nImports an existing domain from Namecheap.');
127
+ info('Usage: myapi domain register <domain> --org <id> [--years <num>]\n\nRegisters a new domain name under your account.\n\nFlags:\n --years <num> Number of years to register for (default: 1)\n\nPrerequisites:\n - You must have sufficient balance (myapi billing balance)\n - The domain must be available (myapi domain check <domain>)\n\nAfter registering, assign the domain to your org:\n myapi domain assign <domain> --org <id>\n\nDNS propagation takes a few minutes. Track it with:\n myapi domain status <domain>');
138
128
  else if (subcommand === 'assign')
139
- info('Usage: myapi domain assign <domain> --org <id>\n\nAssigns a domain to the specified organization.');
129
+ info('Usage: myapi domain assign <domain> --org <id>\n\nAssigns a registered domain to an organization. The domain must already be\nregistered under your account. Once assigned, your funnel will be served at\nhttps://<domain> after DNS propagation completes.\n\nTo transfer a domain to a different org: unassign it first, then assign to the new org.');
140
130
  else if (subcommand === 'unassign')
141
- info('Usage: myapi domain unassign <domain> --org <id>\n\nUnassigns a domain from its current organization.');
131
+ info('Usage: myapi domain unassign <domain> --org <id>\n\nUnassigns a domain from its current organization. The domain remains registered\nunder your account and can be reassigned to a different org at any time.');
142
132
  else if (subcommand === 'status')
143
133
  info('Usage: myapi domain status <domain> --org <id> [--json]\n\nGets the registration status of a domain.\n\nFlags:\n --json Output raw JSON');
144
134
  else if (subcommand === 'settings')
145
135
  info('Usage: myapi domain settings <domain> --org <id>\n\nGets the DNS settings and configuration for a domain.');
146
136
  else if (subcommand === 'update-settings')
147
- info('Usage: myapi domain update-settings <domain> --org <id> [--security=essentially_off|medium|high|under_attack] [--browser-check=on|off] [--purge-cache]\n\nUpdates edge settings for a domain.');
137
+ info('Usage: myapi domain update-settings <domain> --org <id> [flags]\n\nUpdates edge/CDN settings for a domain.\n\nFlags:\n --security=<level> CDN security level. Controls bot/threat filtering.\n Values: essentially_off | low | medium | high | under_attack\n Default (if unset): medium\n --browser-check=<on|off> Enable or disable browser integrity challenge for suspicious traffic.\n Default: on\n --purge-cache Immediately clears the CDN cache for this domain.\n Use after deploying changes that are not yet visible.\n\nExample:\n myapi domain update-settings example.com --org <id> --security=high --purge-cache');
148
138
  return;
149
139
  }
150
140
  if (subcommand === 'list')
@@ -153,8 +143,6 @@ export async function run(subcommand, args, flags) {
153
143
  await check(args[0], flags);
154
144
  else if (subcommand === 'register')
155
145
  await register(args[0], flags);
156
- else if (subcommand === 'import')
157
- await importDomain(args[0], flags);
158
146
  else if (subcommand === 'assign')
159
147
  await assign(args[0], flags);
160
148
  else if (subcommand === 'unassign')
@@ -8,6 +8,10 @@ export async function list(flags) {
8
8
  if (!orgId)
9
9
  error("Missing required arguments.\nUsage: myapi funnel list --org <id>\n(Or set defaults via: myapi config set-org <id>)");
10
10
  const funnels = await sdkFunnel.listFunnels(config.api_key, orgId);
11
+ if (flags.json) {
12
+ printJson(funnels);
13
+ return;
14
+ }
11
15
  const rows = funnels.map(f => ({ id: f.id, created_at: formatDate(f.created_at), updated_at: formatDate(f.updated_at) }));
12
16
  if (rows.length === 0) {
13
17
  info('No funnels found. Create one with: myapi funnel create');
@@ -102,15 +106,15 @@ export async function run(subcommand, args, flags) {
102
106
  }
103
107
  if (flags.help) {
104
108
  if (subcommand === 'list')
105
- 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)');
109
+ info('Usage: myapi funnel list --org <id> [--json]\n\nLists all funnels (websites) in the organization.\n\nFlags:\n --org <id> Organization ID (or set default via myapi auth config set-org)\n --json Output raw JSON');
106
110
  else if (subcommand === 'create')
107
111
  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)');
108
112
  else if (subcommand === 'get')
109
- 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)');
113
+ info('Usage: myapi funnel get <id> --org <id>\n\nFetches details of a specific funnel including its pages and settings.\n\nFlags:\n --org <id> Organization ID (or set default via myapi auth config set-org)');
110
114
  else if (subcommand === 'delete')
111
115
  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)');
112
116
  else if (subcommand === 'push')
113
- 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: /)');
117
+ info('Usage: myapi funnel push [funnel_id] [slug] < page.html\n or: echo \'<h1>Hi</h1>\' | myapi funnel push [slug]\n\nPublishes an HTML page from stdin to a path within your funnel (website).\nBoth arguments are optional — omitting them uses your configured defaults.\n\nArguments:\n funnel_id UUID of the target funnel (default: your configured default funnel)\n slug URL path to publish to, e.g. /about (default: /)\n\nFlags:\n --org <id> Organization ID (or set default via myapi auth config set-org)\n --slug <path> Alternative way to specify the slug\n\nExamples:\n echo \'<h1>Hello</h1>\' | myapi funnel push /\n cat index.html | myapi funnel push /about\n myapi funnel push < index.html');
114
118
  else if (subcommand === 'pull')
115
119
  info('Usage: myapi funnel pull [funnel_id] [slug]\n\nFetches the HTML content of a funnel page.');
116
120
  return;
@@ -1,10 +1,11 @@
1
- import { hq } from '@myapihq/sdk';
2
- import { requireConfig } from '../config.js';
1
+ import * as readline from 'readline';
2
+ import { hq, funnel as sdkFunnel } from '@myapihq/sdk';
3
+ import { requireConfig, saveConfig } from '../config.js';
3
4
  import { success, error, printTable, printJson, info } from '../output.js';
4
5
  import { sleep, formatDate } from '../utils.js';
5
6
  export async function create(flags) {
6
7
  if (flags.help) {
7
- info('Usage: myapi org create --name="My Org" [options]\n\nOptions:\n --name Organization name (required)\n --tagline Short tagline\n --description Detailed description\n --business-sector Sector (e.g. Technology)\n --logo-url URL to logo image');
8
+ info('Usage: myapi org create --name <name> [options]\n\nCreates a new organization. A funnel (website) is automatically created alongside it.\n\nOptions:\n --name Organization name (required). Use quotes for names with spaces.\n --tagline Short tagline\n --description Detailed description\n --business-sector Sector (e.g. Technology)\n --logo-url URL to logo image\n --yes Skip the "set as default?" prompt (useful in CI / agent workflows)\n\nExamples:\n myapi org create --name "Acme Inc"\n myapi org create --name "Acme Inc" --yes');
8
9
  return;
9
10
  }
10
11
  if (!flags.name) {
@@ -26,14 +27,33 @@ export async function create(flags) {
26
27
  if (org.preview_subdomain) {
27
28
  info(`Preview domain: https://${org.preview_subdomain}.makeautonomous.com`);
28
29
  }
30
+ const setDefault = flags.yes || await new Promise(resolve => {
31
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
32
+ rl.question(`› Set as default org and funnel? (Y/n) `, ans => {
33
+ rl.close();
34
+ resolve(ans.trim().toLowerCase() !== 'n');
35
+ });
36
+ });
37
+ if (setDefault) {
38
+ config.default_org = org.id;
39
+ const funnels = await sdkFunnel.listFunnels(config.api_key, org.id);
40
+ if (funnels.length > 0)
41
+ config.default_funnel = funnels[0].id;
42
+ saveConfig(config);
43
+ success(`Default org${funnels.length > 0 ? ' and funnel' : ''} updated.`);
44
+ }
29
45
  }
30
46
  export async function list(flags) {
31
47
  if (flags.help) {
32
- info('Usage: myapi org list\n\nLists all organizations in your account.');
48
+ info('Usage: myapi org list [--json]\n\nLists all organizations in your account.\n\nFlags:\n --json Output raw JSON');
33
49
  return;
34
50
  }
35
51
  const config = requireConfig();
36
52
  const orgs = await hq.listOrgs(config.api_key);
53
+ if (flags.json) {
54
+ printJson(orgs);
55
+ return;
56
+ }
37
57
  const rows = orgs.map((o) => ({
38
58
  id: o.id,
39
59
  name: o.name,
@@ -67,7 +87,7 @@ export async function get(id, flags) {
67
87
  }
68
88
  export async function del(id, flags) {
69
89
  if (flags.help) {
70
- info('Usage: myapi org delete <id>\n\nDeletes an organization.');
90
+ info('Usage: myapi org delete <id>\n\nPermanently deletes an organization and its associated funnels.\nNote: any registered domains assigned to this org must be unassigned first.\n\nNo confirmation prompt is shown — this action is immediate.');
71
91
  return;
72
92
  }
73
93
  if (!id) {
@@ -80,7 +100,7 @@ export async function del(id, flags) {
80
100
  }
81
101
  export async function importOrg(args, flags) {
82
102
  if (flags.help) {
83
- info('Usage: myapi org import <domain> --org <id>\n\nAutomatically extracts brand info from an existing website and updates the organization.\n\nNote: You must create a placeholder organization first using `myapi org create` to get an org_id.');
103
+ info('Usage: myapi org import <domain> --org <id>\n\nSyncs brand information from an existing website into an organization.\nMyAPI fetches the site, extracts name, logo, description, and other brand signals,\nthen updates the org profile automatically.\n\nThis is a profile-enrichment tool, not a domain transfer. The domain does not\nneed to be registered with MyAPI.\n\nPrerequisite: an org must already exist. Create one with: myapi org create --name "..."');
84
104
  return;
85
105
  }
86
106
  const config = requireConfig();
@@ -41,7 +41,7 @@ export async function checkForUpdate(currentVersion) {
41
41
  // myapi update — explicit update, same logic as auto-update.
42
42
  export async function update(flags = {}) {
43
43
  if (flags.help) {
44
- info('Usage: myapi update\n\nUpdates the MyAPI CLI to the latest published version.\nEquivalent to: npm install -g @myapihq/cli@latest');
44
+ info('Usage: myapi update\n\nUpdates the MyAPI CLI and installed skills to the latest published version.\nEquivalent to: npm install -g @myapihq/cli@latest\n\nNote: version pinning and rollback are not supported — always installs the latest.\nThe CLI also auto-updates silently on each command when a newer version is detected.');
45
45
  return;
46
46
  }
47
47
  info('› Checking for updates…');
package/dist/index.js CHANGED
@@ -61,7 +61,7 @@ async function main() {
61
61
  switch (command) {
62
62
  case 'auth':
63
63
  if (!subcommand || (flags.help && !subcommand)) {
64
- 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 link [email] Attach an email to your anonymous account (upgrades it to registered)\n If the email already has an account, signs you into it as a second session\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');
64
+ 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 · supports --json\n link [email] Upgrade anonymous account to registered (or add a second session)\n Use myapi auth setup to create a completely new account\n switch [index] Switch active account by index or email\n config Manage CLI defaults (org, funnel, domain) · supports set-org / set-funnel / set-domain\n install-skills Install or update the MyAPI skills pack for AI agents\n api-keys Manage API keys · list / create / revoke\n keys Alias for api-keys');
65
65
  break;
66
66
  }
67
67
  if (subcommand === 'setup')
@@ -76,7 +76,7 @@ async function main() {
76
76
  await authCmd.switchCmd(flags, restArgs[0]);
77
77
  else if (subcommand === 'install-skills') {
78
78
  if (flags.help) {
79
- info('Usage: myapi auth install-skills\n\nInstalls the MyAPI skills pack for Claude, Gemini, and Cursor agents.');
79
+ info('Usage: myapi auth install-skills\n\nInstalls the MyAPI skills pack for AI coding agents (Claude, Gemini, Cursor).\n\nThis command writes skill definition files to:\n ~/.agents/skills/myapi/\n\nAnd creates symlinks in the appropriate agent config directories:\n ~/.claude/ (Claude)\n ~/.gemini/ (Gemini)\n ~/.cursor/ (Cursor, if detected)\n\nThese files teach agents how to use the MyAPI CLI and API directly.\nRun this command again to update existing skills to the latest version.');
80
80
  break;
81
81
  }
82
82
  await setupCmd.installSkills();
@@ -86,11 +86,11 @@ async function main() {
86
86
  await configCmd.run(restArgs[0], restArgs.slice(1), flags);
87
87
  else if (subcommand === 'api-keys') {
88
88
  if (flags.help && !restArgs[0]) {
89
- 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');
89
+ info('Usage: myapi auth api-keys <subcommand>\n\nManage programmatic API keys for your account. API keys are used to authenticate\nrequests to the MyAPI SDK and REST API.\n\nSubcommands:\n list List all API keys with their IDs and creation dates\n create Create a new API key (the key value is shown once)\n revoke <id> Permanently revoke an API key by ID\n\nExamples:\n myapi auth api-keys list\n myapi auth api-keys create\n myapi auth api-keys revoke xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx');
90
90
  break;
91
91
  }
92
92
  if (!restArgs[0]) {
93
- info('Usage: myapi auth api-keys <list|create|revoke>');
93
+ info('Run: myapi auth api-keys --help');
94
94
  break;
95
95
  }
96
96
  if (restArgs[0] === 'create')
@@ -108,7 +108,7 @@ async function main() {
108
108
  break;
109
109
  case 'org':
110
110
  if (!subcommand || (flags.help && !subcommand)) {
111
- info('Usage: myapi org <subcommand>\n\nSubcommands:\n list List organizations\n create Create an organization\n get Get details of an organization\n delete Delete an organization\n import Extract org from domain');
111
+ info('Usage: myapi org <subcommand>\n\nSubcommands:\n list List organizations\n create Create an organization (use --yes to auto-set it as your default org and funnel)\n get Get details of an organization\n delete Delete an organization\n import Extract org from domain');
112
112
  break;
113
113
  }
114
114
  if (subcommand === 'list')
@@ -154,8 +154,8 @@ async function main() {
154
154
  await authCmd.whoami(flags);
155
155
  break;
156
156
  case 'keys':
157
- if (!subcommand) {
158
- info('Usage: myapi keys <list|create|revoke>');
157
+ if (!subcommand || flags.help) {
158
+ info('Usage: myapi keys <subcommand>\n\nManage programmatic API keys for your account. API keys are used to authenticate\nrequests to the MyAPI SDK and REST API.\n\nSubcommands:\n list List all API keys with their IDs and creation dates\n create Create a new API key (the key value is shown once)\n revoke <id> Permanently revoke an API key by ID\n\nExamples:\n myapi keys list\n myapi keys create\n myapi keys revoke xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n\nAlias for: myapi auth api-keys');
159
159
  break;
160
160
  }
161
161
  if (subcommand === 'create')
@@ -210,10 +210,10 @@ Usage: myapi <command> [subcommand] [args]
210
210
  Commands:
211
211
  auth Manage account · setup · whoami · link
212
212
  billing Check balance and manage billing
213
- org Manage organizations
213
+ org Manage organizations (tip: myapi org create "name" --yes to auto-set as default)
214
214
  update Update CLI and skills to the latest version
215
215
  domain Manage domain configurations
216
- funnel Manage headless funnels and pages
216
+ funnel Manage websites (publish pages, custom domains, funnels)
217
217
 
218
218
  Aliases:
219
219
  whoami → myapi auth whoami
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@myapihq/cli",
3
- "version": "1.0.60",
3
+ "version": "1.0.63",
4
4
  "description": "MyAPI command-line interface",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -44,7 +44,7 @@ async function patch(path: string, body: unknown, apiKey: string): Promise<unkno
44
44
  // myapi auth link — upgrade anonymous session to registered account.
45
45
  export async function link(flags: Record<string, string | boolean> = {}, emailArg?: string) {
46
46
  if (flags.help) {
47
- info('Usage: myapi auth link [email]\n\nAttaches a verified email to your current anonymous account, converting it into\na registered account. A one-time code will be sent to the email to confirm.\n\nIf that email already belongs to an existing MyAPI account, you will be signed\ninto that account instead it is added as a second active session alongside\nyour current one.\n\nTo create a brand-new account from scratch, use: myapi auth setup');
47
+ info('Usage: myapi auth link [email]\n\nUpgrades your anonymous account by attaching a verified email address.\nA one-time code will be sent to your inbox — paste it at the prompt to confirm.\nThis is an interactive command; it will ask for the code before completing.\n\nIf that email already belongs to an existing MyAPI account, your anonymous\naccount is NOT merged. Instead, the existing account is added as a second\nactive session and you can switch between them with: myapi auth switch\n\nTo create a completely new account from scratch, use: myapi auth setup');
48
48
  return;
49
49
  }
50
50
  const config = loadConfig();
@@ -152,7 +152,7 @@ export async function whoami(flags: Record<string, string | boolean> = {}) {
152
152
  // myapi auth switch [index] — switch between saved accounts.
153
153
  export async function switchCmd(flags: Record<string, string | boolean> = {}, indexArg?: string) {
154
154
  if (flags.help) {
155
- 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');
155
+ info('Usage: myapi auth switch [index]\n\nSwitches the active account. Run without arguments to see a numbered list\nof accounts and choose interactively.\n\nPass an index number to switch non-interactively:\n myapi auth switch 2\n\nNote: index numbers may change as accounts are added. For scripting,\ncheck the list first with: myapi auth switch (no args)');
156
156
  return;
157
157
  }
158
158
  const accounts = listAccounts();
@@ -6,7 +6,7 @@ const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/
6
6
 
7
7
  export async function setOrg(id: string, flags: Record<string, string | boolean>) {
8
8
  if (!id || flags.help) {
9
- info("Usage: myapi config set-org <id>\n\nSets a default organization ID for subsequent commands.");
9
+ info("Usage: myapi config set-org <id>\n\nSets the default organization for all commands that require --org.\nThe ID is validated against the API before saving.\n\nExample:\n myapi auth config set-org xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx");
10
10
  return;
11
11
  }
12
12
  if (!UUID_RE.test(id)) error(`Invalid organization ID: "${id}". Expected a UUID (e.g. xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx).`);
@@ -20,7 +20,7 @@ export async function setOrg(id: string, flags: Record<string, string | boolean>
20
20
 
21
21
  export async function setFunnel(id: string, flags: Record<string, string | boolean>) {
22
22
  if (!id || flags.help) {
23
- info("Usage: myapi config set-funnel <id>\n\nSets a default funnel ID for subsequent commands.");
23
+ info("Usage: myapi config set-funnel <id>\n\nSets the default funnel. The funnel must belong to your current default org.\nThe ID is validated against the API before saving.\n\nExample:\n myapi auth config set-funnel xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx");
24
24
  return;
25
25
  }
26
26
  if (!UUID_RE.test(id)) error(`Invalid funnel ID: "${id}". Expected a UUID (e.g. xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx).`);
@@ -36,7 +36,7 @@ export async function setFunnel(id: string, flags: Record<string, string | boole
36
36
 
37
37
  export async function setDomain(domain: string, flags: Record<string, string | boolean>) {
38
38
  if (!domain || flags.help) {
39
- info("Usage: myapi config set-domain <domain>\n\nSets a default domain for subsequent commands.");
39
+ info("Usage: myapi config set-domain <domain>\n\nSets the default domain used by domain commands when --domain is omitted.\n\nExample:\n myapi auth config set-domain example.com");
40
40
  return;
41
41
  }
42
42
  const config = requireConfig();
@@ -47,7 +47,7 @@ export async function setDomain(domain: string, flags: Record<string, string | b
47
47
 
48
48
  export async function view(flags: Record<string, string | boolean>) {
49
49
  if (flags.help) {
50
- info("Usage: myapi config view\n\nViews current config settings.");
50
+ info("Usage: myapi config view\n\nShows the currently configured defaults: default org, funnel, and domain.");
51
51
  return;
52
52
  }
53
53
  const config = requireConfig();
@@ -59,10 +59,10 @@ export async function view(flags: Record<string, string | boolean>) {
59
59
  export async function run(subcommand: string | undefined, args: string[], flags: Record<string, string | boolean>) {
60
60
  const via = (flags._via as string) || 'auth config';
61
61
  if (!subcommand || (flags.help && !subcommand)) {
62
- info(`Usage: myapi ${via} <subcommand>\n\nSubcommands:\n view View current config\n set-org Set default organization\n set-funnel Set default funnel\n set-domain Set default domain`);
62
+ info(`Usage: myapi ${via} <subcommand>\n\nManages CLI defaults (org, funnel, domain) so you don't have to pass --org / --domain on every command.\n\nSubcommands:\n view Show current defaults\n set-org Set default organization (validates access)\n set-funnel Set default funnel (must be owned by default org)\n set-domain Set default domain\n\nExamples:\n myapi auth config set-org <id>\n myapi auth config set-funnel <id>\n myapi auth config view`);
63
63
  return;
64
64
  }
65
-
65
+
66
66
  if (subcommand === 'view') await view(flags);
67
67
  else if (subcommand === 'set-org') await setOrg(args[0], flags);
68
68
  else if (subcommand === 'set-funnel') await setFunnel(args[0], flags);
@@ -35,17 +35,6 @@ export async function register(domainArg: string, flags: Record<string, string |
35
35
  info(`Your funnel will be live on https://${domain} once propagation completes.`);
36
36
  }
37
37
 
38
- export async function importDomain(domainArg: string, flags: Record<string, string | boolean>) {
39
- const config = requireConfig();
40
- const orgId = (flags.org as string) || config.default_org;
41
- const domain = domainArg || (config.default_domain as string);
42
- 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>)");
43
- const payload: { domain: string; namecheap_api_user?: string; namecheap_api_key?: string } = { domain };
44
- if (flags['namecheap-user']) payload.namecheap_api_user = flags['namecheap-user'] as string;
45
- if (flags['namecheap-key']) payload.namecheap_api_key = flags['namecheap-key'] as string;
46
- await sdkDomain.importDomain(config.api_key, orgId, payload);
47
- success(`Imported ${domain}`);
48
- }
49
38
 
50
39
  export async function list(flags: Record<string, string | boolean>) {
51
40
  const config = requireConfig();
@@ -53,6 +42,7 @@ export async function list(flags: Record<string, string | boolean>) {
53
42
  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>)");
54
43
  const filter = flags.filter as 'all' | 'unassigned' | 'org' | undefined;
55
44
  const domains = await sdkDomain.listDomains(config.api_key, orgId, filter);
45
+ if (flags.json) { printJson(domains); return; }
56
46
  if ((domains as unknown[]).length === 0) { info('No domains found in this organization. Register one with: myapi domain register <name>'); return; }
57
47
  printTable(domains as unknown as Record<string, unknown>[]);
58
48
  }
@@ -88,6 +78,7 @@ export async function status(domainArg: string, flags: Record<string, string | b
88
78
  info(`Domain: ${res.domain}`);
89
79
  info(`Status: ${res.status}`);
90
80
  if ((res as any).expires_at) info(`Expires: ${formatDate((res as any).expires_at)}`);
81
+ if (res.status === 'active') info(`Note: if recently activated, the SSL certificate may still be provisioning — allow a few minutes before the site is reachable over HTTPS.`);
91
82
  }
92
83
 
93
84
  export async function settings(domainArg: string, flags: Record<string, string | boolean>) {
@@ -115,27 +106,25 @@ export async function updateSettings(domainArg: string, flags: Record<string, st
115
106
 
116
107
  export async function run(subcommand: string | undefined, args: string[], flags: Record<string, string | boolean>) {
117
108
  if (!subcommand || (flags.help && !subcommand)) {
118
- 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 an 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
+ info('Usage: myapi domain <subcommand>\n\nSubcommands:\n list List domains\n check Check domain availability\n register Register a domain\n assign Assign domain to an org\n unassign Unassign domain from its current org\n status Get domain status\n settings Get domain settings\n update-settings Update edge/CDN settings\n\nTip: Set defaults with "myapi auth config set-org <id>" to skip --org on every command.');
119
110
  return;
120
111
  }
121
112
 
122
113
  if (flags.help) {
123
- if (subcommand === 'list') info('Usage: myapi domain list --org <id> [--filter=all|unassigned|org]\n\nLists all registered domains in your account.\n --filter=all Lists all domains owned by the account.\n --filter=unassigned Lists domains not assigned to an org.\n --filter=org (Default) Lists domains assigned to the current org.');
114
+ if (subcommand === 'list') info('Usage: myapi domain list --org <id> [--filter=all|unassigned|org] [--json]\n\nLists all registered domains in your account.\n --filter=all Lists all domains owned by the account.\n --filter=unassigned Lists domains not assigned to an org.\n --filter=org (Default) Lists domains assigned to the current org.\n --json Output raw JSON');
124
115
  else if (subcommand === 'check') info('Usage: myapi domain check <domain> --org <id> [--json]\n\nChecks if a domain name is available for registration.\n\nFlags:\n --json Output raw JSON');
125
- else if (subcommand === 'register') info('Usage: myapi domain register <domain> --org <id> [--years <num>]\n\nRegisters a new domain name.');
126
- else if (subcommand === 'import') info('Usage: myapi domain import <domain> --org <id> --namecheap-user <user> --namecheap-key <key>\n\nImports an existing domain from Namecheap.');
127
- else if (subcommand === 'assign') info('Usage: myapi domain assign <domain> --org <id>\n\nAssigns a domain to the specified organization.');
128
- else if (subcommand === 'unassign') info('Usage: myapi domain unassign <domain> --org <id>\n\nUnassigns a domain from its current organization.');
116
+ else if (subcommand === 'register') info('Usage: myapi domain register <domain> --org <id> [--years <num>]\n\nRegisters a new domain name under your account.\n\nFlags:\n --years <num> Number of years to register for (default: 1)\n\nPrerequisites:\n - You must have sufficient balance (myapi billing balance)\n - The domain must be available (myapi domain check <domain>)\n\nAfter registering, assign the domain to your org:\n myapi domain assign <domain> --org <id>\n\nDNS propagation takes a few minutes. Track it with:\n myapi domain status <domain>');
117
+ else if (subcommand === 'assign') info('Usage: myapi domain assign <domain> --org <id>\n\nAssigns a registered domain to an organization. The domain must already be\nregistered under your account. Once assigned, your funnel will be served at\nhttps://<domain> after DNS propagation completes.\n\nTo transfer a domain to a different org: unassign it first, then assign to the new org.');
118
+ else if (subcommand === 'unassign') info('Usage: myapi domain unassign <domain> --org <id>\n\nUnassigns a domain from its current organization. The domain remains registered\nunder your account and can be reassigned to a different org at any time.');
129
119
  else if (subcommand === 'status') info('Usage: myapi domain status <domain> --org <id> [--json]\n\nGets the registration status of a domain.\n\nFlags:\n --json Output raw JSON');
130
120
  else if (subcommand === 'settings') info('Usage: myapi domain settings <domain> --org <id>\n\nGets the DNS settings and configuration for a domain.');
131
- else if (subcommand === 'update-settings') info('Usage: myapi domain update-settings <domain> --org <id> [--security=essentially_off|medium|high|under_attack] [--browser-check=on|off] [--purge-cache]\n\nUpdates edge settings for a domain.');
121
+ else if (subcommand === 'update-settings') info('Usage: myapi domain update-settings <domain> --org <id> [flags]\n\nUpdates edge/CDN settings for a domain.\n\nFlags:\n --security=<level> CDN security level. Controls bot/threat filtering.\n Values: essentially_off | low | medium | high | under_attack\n Default (if unset): medium\n --browser-check=<on|off> Enable or disable browser integrity challenge for suspicious traffic.\n Default: on\n --purge-cache Immediately clears the CDN cache for this domain.\n Use after deploying changes that are not yet visible.\n\nExample:\n myapi domain update-settings example.com --org <id> --security=high --purge-cache');
132
122
  return;
133
123
  }
134
124
 
135
125
  if (subcommand === 'list') await list(flags);
136
126
  else if (subcommand === 'check') await check(args[0], flags);
137
127
  else if (subcommand === 'register') await register(args[0], flags);
138
- else if (subcommand === 'import') await importDomain(args[0], flags);
139
128
  else if (subcommand === 'assign') await assign(args[0], flags);
140
129
  else if (subcommand === 'unassign') await unassign(args[0], flags);
141
130
  else if (subcommand === 'status') await status(args[0], flags);
@@ -9,6 +9,7 @@ export async function list(flags: Record<string, string | boolean>) {
9
9
  const orgId = (flags.org as string) || config.default_org;
10
10
  if (!orgId) error("Missing required arguments.\nUsage: myapi funnel list --org <id>\n(Or set defaults via: myapi config set-org <id>)");
11
11
  const funnels = await sdkFunnel.listFunnels(config.api_key, orgId);
12
+ if (flags.json) { printJson(funnels); return; }
12
13
  const rows = funnels.map(f => ({ id: f.id, created_at: formatDate(f.created_at), updated_at: formatDate(f.updated_at) }));
13
14
  if (rows.length === 0) { info('No funnels found. Create one with: myapi funnel create'); return; }
14
15
  printTable(rows as unknown as Record<string, unknown>[]);
@@ -103,11 +104,11 @@ export async function run(subcommand: string | undefined, args: string[], flags:
103
104
  }
104
105
 
105
106
  if (flags.help) {
106
- 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)');
107
+ if (subcommand === 'list') info('Usage: myapi funnel list --org <id> [--json]\n\nLists all funnels (websites) in the organization.\n\nFlags:\n --org <id> Organization ID (or set default via myapi auth config set-org)\n --json Output raw JSON');
107
108
  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)');
108
- 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)');
109
+ else if (subcommand === 'get') info('Usage: myapi funnel get <id> --org <id>\n\nFetches details of a specific funnel including its pages and settings.\n\nFlags:\n --org <id> Organization ID (or set default via myapi auth config set-org)');
109
110
  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)');
110
- 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: /)');
111
+ else if (subcommand === 'push') info('Usage: myapi funnel push [funnel_id] [slug] < page.html\n or: echo \'<h1>Hi</h1>\' | myapi funnel push [slug]\n\nPublishes an HTML page from stdin to a path within your funnel (website).\nBoth arguments are optional — omitting them uses your configured defaults.\n\nArguments:\n funnel_id UUID of the target funnel (default: your configured default funnel)\n slug URL path to publish to, e.g. /about (default: /)\n\nFlags:\n --org <id> Organization ID (or set default via myapi auth config set-org)\n --slug <path> Alternative way to specify the slug\n\nExamples:\n echo \'<h1>Hello</h1>\' | myapi funnel push /\n cat index.html | myapi funnel push /about\n myapi funnel push < index.html');
111
112
  else if (subcommand === 'pull') info('Usage: myapi funnel pull [funnel_id] [slug]\n\nFetches the HTML content of a funnel page.');
112
113
  return;
113
114
  }
@@ -1,11 +1,12 @@
1
- import { hq } from '@myapihq/sdk';
2
- import { requireConfig } from '../config.js';
1
+ import * as readline from 'readline';
2
+ import { hq, funnel as sdkFunnel } from '@myapihq/sdk';
3
+ import { requireConfig, saveConfig } from '../config.js';
3
4
  import { success, error, printTable, printJson, info } from '../output.js';
4
5
  import { sleep, formatDate } from '../utils.js';
5
6
 
6
7
  export async function create(flags: Record<string, string | boolean>) {
7
8
  if (flags.help) {
8
- info('Usage: myapi org create --name="My Org" [options]\n\nOptions:\n --name Organization name (required)\n --tagline Short tagline\n --description Detailed description\n --business-sector Sector (e.g. Technology)\n --logo-url URL to logo image');
9
+ info('Usage: myapi org create --name <name> [options]\n\nCreates a new organization. A funnel (website) is automatically created alongside it.\n\nOptions:\n --name Organization name (required). Use quotes for names with spaces.\n --tagline Short tagline\n --description Detailed description\n --business-sector Sector (e.g. Technology)\n --logo-url URL to logo image\n --yes Skip the "set as default?" prompt (useful in CI / agent workflows)\n\nExamples:\n myapi org create --name "Acme Inc"\n myapi org create --name "Acme Inc" --yes');
9
10
  return;
10
11
  }
11
12
  if (!flags.name) {
@@ -24,15 +25,32 @@ export async function create(flags: Record<string, string | boolean>) {
24
25
  if (org.preview_subdomain) {
25
26
  info(`Preview domain: https://${org.preview_subdomain}.makeautonomous.com`);
26
27
  }
28
+
29
+ const setDefault = flags.yes || await new Promise<boolean>(resolve => {
30
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
31
+ rl.question(`› Set as default org and funnel? (Y/n) `, ans => {
32
+ rl.close();
33
+ resolve(ans.trim().toLowerCase() !== 'n');
34
+ });
35
+ });
36
+
37
+ if (setDefault) {
38
+ config.default_org = org.id;
39
+ const funnels = await sdkFunnel.listFunnels(config.api_key, org.id);
40
+ if (funnels.length > 0) config.default_funnel = funnels[0].id;
41
+ saveConfig(config);
42
+ success(`Default org${funnels.length > 0 ? ' and funnel' : ''} updated.`);
43
+ }
27
44
  }
28
45
 
29
46
  export async function list(flags: Record<string, string | boolean>) {
30
47
  if (flags.help) {
31
- info('Usage: myapi org list\n\nLists all organizations in your account.');
48
+ info('Usage: myapi org list [--json]\n\nLists all organizations in your account.\n\nFlags:\n --json Output raw JSON');
32
49
  return;
33
50
  }
34
51
  const config = requireConfig();
35
52
  const orgs = await hq.listOrgs(config.api_key);
53
+ if (flags.json) { printJson(orgs); return; }
36
54
  const rows = orgs.map((o: any) => ({
37
55
  id: o.id,
38
56
  name: o.name,
@@ -65,7 +83,7 @@ export async function get(id: string, flags: Record<string, string | boolean>) {
65
83
 
66
84
  export async function del(id: string, flags: Record<string, string | boolean>) {
67
85
  if (flags.help) {
68
- info('Usage: myapi org delete <id>\n\nDeletes an organization.');
86
+ info('Usage: myapi org delete <id>\n\nPermanently deletes an organization and its associated funnels.\nNote: any registered domains assigned to this org must be unassigned first.\n\nNo confirmation prompt is shown — this action is immediate.');
69
87
  return;
70
88
  }
71
89
  if (!id) {
@@ -79,7 +97,7 @@ export async function del(id: string, flags: Record<string, string | boolean>) {
79
97
 
80
98
  export async function importOrg(args: string[], flags: Record<string, string | boolean>) {
81
99
  if (flags.help) {
82
- info('Usage: myapi org import <domain> --org <id>\n\nAutomatically extracts brand info from an existing website and updates the organization.\n\nNote: You must create a placeholder organization first using `myapi org create` to get an org_id.');
100
+ info('Usage: myapi org import <domain> --org <id>\n\nSyncs brand information from an existing website into an organization.\nMyAPI fetches the site, extracts name, logo, description, and other brand signals,\nthen updates the org profile automatically.\n\nThis is a profile-enrichment tool, not a domain transfer. The domain does not\nneed to be registered with MyAPI.\n\nPrerequisite: an org must already exist. Create one with: myapi org create --name "..."');
83
101
  return;
84
102
  }
85
103
  const config = requireConfig();
@@ -43,7 +43,7 @@ export async function checkForUpdate(currentVersion: string): Promise<void> {
43
43
  // myapi update — explicit update, same logic as auto-update.
44
44
  export async function update(flags: Record<string, string | boolean> = {}): Promise<void> {
45
45
  if (flags.help) {
46
- info('Usage: myapi update\n\nUpdates the MyAPI CLI to the latest published version.\nEquivalent to: npm install -g @myapihq/cli@latest');
46
+ info('Usage: myapi update\n\nUpdates the MyAPI CLI and installed skills to the latest published version.\nEquivalent to: npm install -g @myapihq/cli@latest\n\nNote: version pinning and rollback are not supported — always installs the latest.\nThe CLI also auto-updates silently on each command when a newer version is detected.');
47
47
  return;
48
48
  }
49
49
  info('› Checking for updates…');
package/src/index.ts CHANGED
@@ -70,7 +70,7 @@ async function main() {
70
70
  switch (command) {
71
71
  case 'auth':
72
72
  if (!subcommand || (flags.help && !subcommand)) {
73
- 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 link [email] Attach an email to your anonymous account (upgrades it to registered)\n If the email already has an account, signs you into it as a second session\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');
73
+ 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 · supports --json\n link [email] Upgrade anonymous account to registered (or add a second session)\n Use myapi auth setup to create a completely new account\n switch [index] Switch active account by index or email\n config Manage CLI defaults (org, funnel, domain) · supports set-org / set-funnel / set-domain\n install-skills Install or update the MyAPI skills pack for AI agents\n api-keys Manage API keys · list / create / revoke\n keys Alias for api-keys');
74
74
  break;
75
75
  }
76
76
  if (subcommand === 'setup') await setupCmd.setup(flags);
@@ -80,7 +80,7 @@ async function main() {
80
80
  else if (subcommand === 'switch') await authCmd.switchCmd(flags, restArgs[0]);
81
81
  else if (subcommand === 'install-skills') {
82
82
  if (flags.help) {
83
- info('Usage: myapi auth install-skills\n\nInstalls the MyAPI skills pack for Claude, Gemini, and Cursor agents.');
83
+ info('Usage: myapi auth install-skills\n\nInstalls the MyAPI skills pack for AI coding agents (Claude, Gemini, Cursor).\n\nThis command writes skill definition files to:\n ~/.agents/skills/myapi/\n\nAnd creates symlinks in the appropriate agent config directories:\n ~/.claude/ (Claude)\n ~/.gemini/ (Gemini)\n ~/.cursor/ (Cursor, if detected)\n\nThese files teach agents how to use the MyAPI CLI and API directly.\nRun this command again to update existing skills to the latest version.');
84
84
  break;
85
85
  }
86
86
  await setupCmd.installSkills();
@@ -88,10 +88,10 @@ async function main() {
88
88
  } else if (subcommand === 'config') await configCmd.run(restArgs[0], restArgs.slice(1), flags);
89
89
  else if (subcommand === 'api-keys') {
90
90
  if (flags.help && !restArgs[0]) {
91
- 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');
91
+ info('Usage: myapi auth api-keys <subcommand>\n\nManage programmatic API keys for your account. API keys are used to authenticate\nrequests to the MyAPI SDK and REST API.\n\nSubcommands:\n list List all API keys with their IDs and creation dates\n create Create a new API key (the key value is shown once)\n revoke <id> Permanently revoke an API key by ID\n\nExamples:\n myapi auth api-keys list\n myapi auth api-keys create\n myapi auth api-keys revoke xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx');
92
92
  break;
93
93
  }
94
- if (!restArgs[0]) { info('Usage: myapi auth api-keys <list|create|revoke>'); break; }
94
+ if (!restArgs[0]) { info('Run: myapi auth api-keys --help'); break; }
95
95
  if (restArgs[0] === 'create') await keysCmd.createNew(flags);
96
96
  else if (restArgs[0] === 'list') await keysCmd.list(flags);
97
97
  else if (restArgs[0] === 'revoke') await keysCmd.revoke(restArgs[1], flags);
@@ -102,7 +102,7 @@ async function main() {
102
102
  break;
103
103
  case 'org':
104
104
  if (!subcommand || (flags.help && !subcommand)) {
105
- info('Usage: myapi org <subcommand>\n\nSubcommands:\n list List organizations\n create Create an organization\n get Get details of an organization\n delete Delete an organization\n import Extract org from domain');
105
+ info('Usage: myapi org <subcommand>\n\nSubcommands:\n list List organizations\n create Create an organization (use --yes to auto-set it as your default org and funnel)\n get Get details of an organization\n delete Delete an organization\n import Extract org from domain');
106
106
  break;
107
107
  }
108
108
  if (subcommand === 'list') await orgCmd.list(flags);
@@ -137,7 +137,10 @@ async function main() {
137
137
  await authCmd.whoami(flags);
138
138
  break;
139
139
  case 'keys':
140
- if (!subcommand) { info('Usage: myapi keys <list|create|revoke>'); break; }
140
+ if (!subcommand || flags.help) {
141
+ info('Usage: myapi keys <subcommand>\n\nManage programmatic API keys for your account. API keys are used to authenticate\nrequests to the MyAPI SDK and REST API.\n\nSubcommands:\n list List all API keys with their IDs and creation dates\n create Create a new API key (the key value is shown once)\n revoke <id> Permanently revoke an API key by ID\n\nExamples:\n myapi keys list\n myapi keys create\n myapi keys revoke xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n\nAlias for: myapi auth api-keys');
142
+ break;
143
+ }
141
144
  if (subcommand === 'create') await keysCmd.createNew(flags);
142
145
  else if (subcommand === 'list') await keysCmd.list(flags);
143
146
  else if (subcommand === 'revoke') await keysCmd.revoke(restArgs[0], flags);
@@ -181,10 +184,10 @@ Usage: myapi <command> [subcommand] [args]
181
184
  Commands:
182
185
  auth Manage account · setup · whoami · link
183
186
  billing Check balance and manage billing
184
- org Manage organizations
187
+ org Manage organizations (tip: myapi org create "name" --yes to auto-set as default)
185
188
  update Update CLI and skills to the latest version
186
189
  domain Manage domain configurations
187
- funnel Manage headless funnels and pages
190
+ funnel Manage websites (publish pages, custom domains, funnels)
188
191
 
189
192
  Aliases:
190
193
  whoami → myapi auth whoami