@heyamiko/amiko-cli 0.9.0-beta.0 → 0.9.0-beta.5

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.
package/README.md CHANGED
@@ -35,18 +35,18 @@ amiko credits balance
35
35
  amiko credits topup 10000 --token AMIKO --yes
36
36
 
37
37
  # Search X/Twitter (1 AMIKO, pass --wallet)
38
- amiko search "AI agents" --wallet <solana-address>
38
+ amiko market search "AI agents" --wallet <solana-address>
39
39
 
40
40
  # Generate an image (5 AMIKO)
41
- amiko image "a sunset over mountains" --wallet <solana-address>
41
+ amiko market image "a sunset over mountains" --wallet <solana-address>
42
42
 
43
43
  # Swap tokens on Solana
44
- amiko swap quote 1.0 SOL USDC
45
- amiko swap send 1.0 SOL USDC --yes
44
+ amiko wallets swap quote 1.0 SOL USDC
45
+ amiko wallets swap send 1.0 SOL USDC --yes
46
46
 
47
47
  # Call any MPP service
48
- amiko service list
49
- amiko service call POST /v1/sfx '{"text":"thunder","duration_seconds":5}'
48
+ amiko market service list
49
+ amiko market service call POST /v1/sfx '{"text":"thunder","duration_seconds":5}'
50
50
  ```
51
51
 
52
52
  ## Credits
@@ -93,9 +93,9 @@ amiko credits topup 10000 --wallet Gu2b...QVya # specific wallet
93
93
  ## Search
94
94
 
95
95
  ```bash
96
- amiko search "AI agents" # search X/Twitter (1 AMIKO)
97
- amiko search "bitcoin" --token USDC # pay with USDC instead
98
- amiko search "news" --raw # raw JSON output
96
+ amiko market search "AI agents" # search X/Twitter (1 AMIKO)
97
+ amiko market search "bitcoin" --token USDC # pay with USDC instead
98
+ amiko market search "news" --raw # raw JSON output
99
99
  ```
100
100
 
101
101
  Pays 1 AMIKO per search via Crossmint wallet transfer. Tries Solana wallet first, falls back to EVM.
@@ -103,12 +103,12 @@ Pays 1 AMIKO per search via Crossmint wallet transfer. Tries Solana wallet first
103
103
  ## Image Generation
104
104
 
105
105
  ```bash
106
- amiko image "a sunset over mountains" # gpt-image-1 (default)
107
- amiko image "logo" --background transparent # transparent background
108
- amiko image "cat" --model dall-e-3 # DALL-E 3
109
- amiko image "portrait" --size 1024x1792 --quality high # portrait, high quality
110
- amiko image "icon" --format webp # webp output
111
- amiko image "banner" --raw # raw JSON
106
+ amiko market image "a sunset over mountains" # gpt-image-1 (default)
107
+ amiko market image "logo" --background transparent # transparent background
108
+ amiko market image "cat" --model dall-e-3 # DALL-E 3
109
+ amiko market image "portrait" --size 1024x1792 --quality high # portrait, high quality
110
+ amiko market image "icon" --format webp # webp output
111
+ amiko market image "banner" --raw # raw JSON
112
112
  ```
113
113
 
114
114
  Costs 5 AMIKO per image. Returns a Supabase Storage URL.
@@ -118,24 +118,24 @@ Image generation typically takes 20–60s. In non-TTY environments (agents, pipe
118
118
  ## Amazon
119
119
 
120
120
  ```bash
121
- amiko amazon search "usb c cable" # product search (1 AMIKO)
122
- amiko amazon quote B01GGKYKQM # price quote (free)
121
+ amiko market amazon search "usb c cable" # product search (1 AMIKO)
122
+ amiko market amazon quote B01GGKYKQM # price quote (free)
123
123
  ```
124
124
 
125
125
  ## Swap
126
126
 
127
127
  ```bash
128
- amiko swap quote <amount> <from> <to> # get Jupiter quote
129
- amiko swap send <amount> <from> <to> # execute swap via Crossmint
130
- amiko swap tokens # list supported tokens
128
+ amiko wallets swap quote <amount> <from> <to> # get Jupiter quote
129
+ amiko wallets swap send <amount> <from> <to> # execute swap via Crossmint
130
+ amiko wallets swap tokens # list supported tokens
131
131
  ```
132
132
 
133
133
  **Examples:**
134
134
 
135
135
  ```bash
136
- amiko swap quote 1.0 SOL USDC
137
- amiko swap send 0.5 USDC AMIKO --yes
138
- amiko swap send 100 AMIKO SOL --slippage 100
136
+ amiko wallets swap quote 1.0 SOL USDC
137
+ amiko wallets swap send 0.5 USDC AMIKO --yes
138
+ amiko wallets swap send 100 AMIKO SOL --slippage 100
139
139
  ```
140
140
 
141
141
  Swaps execute via Jupiter on Solana. Supports SOL, USDC, USDT, AMIKO, PYUSD, BONK, JUP, RAY, JitoSOL, mSOL, or any mint address. `swap send` is hard-gated: in a non-interactive shell you must pass `--yes` after quoting the cost to the user (`Solana gas + 10bps platform fee`).
@@ -143,12 +143,12 @@ Swaps execute via Jupiter on Solana. Supports SOL, USDC, USDT, AMIKO, PYUSD, BON
143
143
  ## Bridge
144
144
 
145
145
  ```bash
146
- amiko bridge quote <amount> # cross-chain USDC quote via Across Protocol
147
- amiko bridge send <amount> # execute bridge transfer (gated — requires --yes in non-TTY)
148
- amiko bridge send <amount> --raw # print transaction JSON without sending (no gate)
149
- amiko bridge status <txHash> # check bridge status
150
- amiko bridge routes # available bridge routes
151
- amiko bridge limits # min/max limits per route
146
+ amiko wallets bridge quote <amount> # cross-chain USDC quote via Across Protocol
147
+ amiko wallets bridge send <amount> # execute bridge transfer (gated — requires --yes in non-TTY)
148
+ amiko wallets bridge send <amount> --raw # print transaction JSON without sending (no gate)
149
+ amiko wallets bridge status <txHash> # check bridge status
150
+ amiko wallets bridge routes # available bridge routes
151
+ amiko wallets bridge limits # min/max limits per route
152
152
  ```
153
153
 
154
154
  Default route: Solana → Tempo. Use `--from` and `--to` flags for other chains. Like `swap send`, `bridge send` refuses to run in a non-interactive shell without `--yes` so agents must quote the Across fee + gas to the user before executing.
@@ -158,24 +158,24 @@ Default route: Solana → Tempo. Use `--from` and `--to` flags for other chains.
158
158
  Call any endpoint on the Amiko marketplace with automatic AMIKO payment:
159
159
 
160
160
  ```bash
161
- amiko service list # all services + prices
162
- amiko service call <METHOD> <path> [body]
161
+ amiko market service list # all services + prices
162
+ amiko market service call <METHOD> <path> [body]
163
163
  ```
164
164
 
165
165
  **Examples:**
166
166
 
167
167
  ```bash
168
168
  # Sound effects ($0.05) — returns { url, format, service }
169
- amiko service call POST /v1/sfx '{"text":"Thunder with heavy rain","duration_seconds":5}'
169
+ amiko market service call POST /v1/sfx '{"text":"Thunder with heavy rain","duration_seconds":5}'
170
170
 
171
171
  # Music generation ($0.10) — returns { url, format, service }
172
- amiko service call POST /v1/music '{"prompt":"Lo-fi chill beat","music_length_ms":30000}'
172
+ amiko market service call POST /v1/music '{"prompt":"Lo-fi chill beat","music_length_ms":30000}'
173
173
 
174
174
  # Text-to-speech (1 AMIKO) — returns { url, format, service }
175
- amiko service tts 21m00Tcm4TlvDq8ikWAM "Hello world"
175
+ amiko market service tts 21m00Tcm4TlvDq8ikWAM "Hello world"
176
176
 
177
177
  # Composition plan ($0.02)
178
- amiko service call POST /v1/music/plan '{"prompt":"Epic orchestral piece"}'
178
+ amiko market service call POST /v1/music/plan '{"prompt":"Epic orchestral piece"}'
179
179
  ```
180
180
 
181
181
  Audio and image endpoints upload to Supabase Storage and return permanent URLs.
@@ -194,7 +194,7 @@ Every paid / value-moving command (`image`, `search`, `amazon search`, `service
194
194
  Action: Generate image: a sunset over mountains
195
195
 
196
196
  Quote the cost to the user, get their explicit approval, then re-run with --yes:
197
- amiko image "a sunset over mountains" --yes
197
+ amiko market image "a sunset over mountains" --yes
198
198
  ```
199
199
 
200
200
  This makes cost confirmation effectively mandatory regardless of which model drives the agent — weak models can no longer silently burn tokens by ignoring the skill docs. The same refusal fires for `swap send` (Solana gas + 10 bps platform fee) and `bridge send` (Across fee + gas), so an agent cannot move tokens without a round-trip through user approval.
@@ -215,7 +215,7 @@ JSON `error` / `message` / `detail` fields are extracted when present; raw body
215
215
  ## Other Commands
216
216
 
217
217
  ```bash
218
- amiko discovery # MPP service info + pricing
218
+ amiko market discover # MPP service info + pricing
219
219
  amiko config show # view config
220
220
  amiko config set <key> <value> # set config value
221
221
  amiko update # update CLI to latest (full twin refresh — no restart needed)
@@ -252,7 +252,7 @@ Agents auto-authenticate via `.amiko.json` — no manual connect needed. The pla
252
252
  ```bash
253
253
  # Agent environment — just works
254
254
  amiko credits balance
255
- amiko search "trending topics"
255
+ amiko market search "trending topics"
256
256
  amiko credits topup 10000 --token AMIKO --yes
257
257
  ```
258
258
 
@@ -265,7 +265,6 @@ Supported keys (both camelCase and SCREAMING_SNAKE_CASE):
265
265
  - `amikoTwinId` / `AMIKO_TWIN_ID` — twin identifier (needed for paid ops)
266
266
  - `amikoUserId` / `AMIKO_USER_ID` — user identifier (optional, for MPP topup)
267
267
  - `amikoPlatformUrl` / `AMIKO_PLATFORM_URL` — platform base URL override
268
- - `billingBase` — billing API URL override
269
268
  - `apiBase` — MPP service URL override
270
269
 
271
270
  ## Configuration
@@ -274,7 +273,6 @@ Defaults (no config file needed — override in `.amiko.json` if needed):
274
273
 
275
274
  | Key | Default |
276
275
  |-----|---------|
277
- | `billingBase` | `https://billing.heyamiko.com` |
278
276
  | `apiBase` | `https://mpp.amikomarkets.com` |
279
277
  | `platformUrl` | `https://platform.heyamiko.com` |
280
278
 
@@ -372,9 +370,8 @@ Every new command accepts `--json` for structured output and `--twin <id>` where
372
370
 
373
371
  | Client | Base URL | Purpose |
374
372
  |--------|----------|---------|
375
- | Amiko Web | `platform.heyamiko.com` | Twin identity, wallet balances, docs, voice, avatar, friends, feed, Composio |
376
- | MPP API | `mpp.amikomarkets.com` | Marketplace services, search, image, audio |
377
- | Billing API | `billing.heyamiko.com` | Credits, topup, wallet transfers/swaps, keys |
373
+ | Platform | `platform.heyamiko.com` | Twin identity, wallets, credits, transfers/swaps, docs, voice, avatar, friends, feed, Composio |
374
+ | MPP API | `mpp.amikomarkets.com` | Marketplace services: search, image, amazon, audio |
378
375
 
379
376
  ## Build
380
377
 
package/dist/index.js CHANGED
@@ -17287,7 +17287,6 @@ function resolveAuth() {
17287
17287
  twinId: asString(parsed.amikoTwinId) ?? asString(parsed.AMIKO_TWIN_ID),
17288
17288
  userId: asString(parsed.amikoUserId) ?? asString(parsed.AMIKO_USER_ID),
17289
17289
  platformUrl: asString(parsed.amikoPlatformUrl) ?? asString(parsed.AMIKO_PLATFORM_URL),
17290
- billingBase: asString(parsed.billingBase),
17291
17290
  apiBase: asString(parsed.apiBase)
17292
17291
  };
17293
17292
  }
@@ -17305,7 +17304,6 @@ function requireAuth() {
17305
17304
  // src/lib/config.ts
17306
17305
  var DEFAULTS = {
17307
17306
  apiBase: "https://mpp.amikomarkets.com",
17308
- billingBase: "https://billing.heyamiko.com",
17309
17307
  platformUrl: "https://platform.heyamiko.com",
17310
17308
  siteBase: "https://platform.heyamiko.com"
17311
17309
  };
@@ -17313,7 +17311,6 @@ function loadConfig() {
17313
17311
  const auth = resolveAuth();
17314
17312
  return {
17315
17313
  apiBase: auth.apiBase ?? DEFAULTS.apiBase,
17316
- billingBase: auth.billingBase ?? DEFAULTS.billingBase,
17317
17314
  platformUrl: auth.platformUrl ?? DEFAULTS.platformUrl,
17318
17315
  siteBase: DEFAULTS.siteBase,
17319
17316
  twinToken: auth.twinToken,
@@ -17385,7 +17382,6 @@ function registerConfigCommand(program2) {
17385
17382
  console.log("");
17386
17383
  console.log(heading("Endpoints"));
17387
17384
  console.log(label(" MPP service", config.apiBase));
17388
- console.log(label(" Billing API", config.billingBase));
17389
17385
  console.log(label(" Platform", config.platformUrl));
17390
17386
  console.log("");
17391
17387
  console.log(heading("Identity"));
@@ -18698,8 +18694,8 @@ function registerBridgeCommand(program2) {
18698
18694
  }
18699
18695
  if (quote.swapTx) {
18700
18696
  console.log("");
18701
- console.log(dim('Transaction ready. Run "amiko bridge send" to execute.'));
18702
- console.log(dim(` amiko bridge send ${amountStr} --from ${opts.from} --to ${opts.to}`));
18697
+ console.log(dim('Transaction ready. Run "amiko wallets bridge send" to execute.'));
18698
+ console.log(dim(` amiko wallets bridge send ${amountStr} --from ${opts.from} --to ${opts.to}`));
18703
18699
  }
18704
18700
  } catch (err) {
18705
18701
  spinner.stop();
@@ -18752,7 +18748,7 @@ function registerBridgeCommand(program2) {
18752
18748
  cost: quote.fees?.total ? `${formatUsdcAmount(quote.fees.total.amount)} USDC bridge fee + gas` : "gas + Across fee",
18753
18749
  summary: `bridge ${formatUsdcAmount(quote.inputAmount)} USDC ${originName} → ${destName}`,
18754
18750
  yes: opts.yes,
18755
- commandExample: `amiko bridge send ${amountStr} --from ${opts.from} --to ${opts.to}`
18751
+ commandExample: `amiko wallets bridge send ${amountStr} --from ${opts.from} --to ${opts.to}`
18756
18752
  });
18757
18753
  }
18758
18754
  if (opts.raw) {
@@ -18831,7 +18827,7 @@ function registerBridgeCommand(program2) {
18831
18827
  console.log(dim(output.trim()));
18832
18828
  console.log("");
18833
18829
  console.log(dim("Track status:"));
18834
- console.log(dim(` amiko bridge status <txHash> --chain ${originChainId}`));
18830
+ console.log(dim(` amiko wallets bridge status <txHash> --chain ${originChainId}`));
18835
18831
  } catch (err) {
18836
18832
  bridgeSpinner.fail("Bridge transaction failed");
18837
18833
  console.error(error(err instanceof Error ? err.message : "Transaction failed"));
@@ -19057,15 +19053,9 @@ function formatError(status, body, path) {
19057
19053
  async function fetchCreditsBalance(auth) {
19058
19054
  if (!auth.twinToken)
19059
19055
  return null;
19060
- const base = (auth.billingBase || "https://billing.heyamiko.com").replace(/\/$/, "");
19061
19056
  try {
19062
- const res = await fetch(`${base}/api/credits`, {
19063
- headers: { Authorization: `Bearer ${auth.twinToken}` }
19064
- });
19065
- if (!res.ok)
19066
- return null;
19067
- const data = await res.json();
19068
- const raw = data.displayBalance ?? Number(data.credits?.balance ?? 0);
19057
+ const data = await amikoWebFetch(auth, `/api/proxy/service/api/credits`);
19058
+ const raw = data.displayBalance;
19069
19059
  return typeof raw === "number" && isFinite(raw) ? Math.round(raw) : null;
19070
19060
  } catch {
19071
19061
  return null;
@@ -19077,8 +19067,7 @@ async function printBalanceRemaining(auth) {
19077
19067
  console.log(dim("Balance: (could not fetch)"));
19078
19068
  return;
19079
19069
  }
19080
- const usd2 = (balance / 1e4).toFixed(2);
19081
- console.log(label("Balance", `${balance.toLocaleString()} credits (~$${usd2})`));
19070
+ console.log(label("Balance", `${balance.toLocaleString()} credits`));
19082
19071
  }
19083
19072
 
19084
19073
  // src/lib/mpp-topup.ts
@@ -19170,8 +19159,7 @@ function registerCreditsCommand(program2) {
19170
19159
  console.log(dim(" Could not fetch credit balance"));
19171
19160
  return;
19172
19161
  }
19173
- const usd2 = (balance / 1e4).toFixed(2);
19174
- console.log(label("Balance", `${source_default.bold(balance.toLocaleString())} credits (~$${usd2})`));
19162
+ console.log(label("Balance", source_default.bold(`${balance.toLocaleString()} credits`)));
19175
19163
  });
19176
19164
  credits.command("topup [amount]").description("Top up credits by spending tokens from your agent wallet. <amount> is in credits (10,000 = $1.00). Use --usd <n> to specify dollars, or --spend <n> to specify a token amount (e.g. 1 SOL worth).").option("--token <TOKEN>", "Token to use for top-up").option("--chain <CHAIN>", "Chain to use for top-up").option("--wallet <ADDR>", "Wallet address to use").option("--method <METHOD>", "Payment method: auto, crossmint, mpp", "auto").option("--key-id <ID>", "Platform API key ID (required for --method mpp)").option("--usd <amount>", "Amount in USD instead of credits (e.g. --usd 1 = 10,000 credits)").option("--spend <amount>", "Spend this many units of --token and convert to credits at current price").option("--yes", "Skip the interactive Proceed? prompt").action(async (amountStr, options) => {
19177
19165
  const inputs = [amountStr, options.usd, options.spend].filter((v) => v != null && v !== "");
@@ -19465,7 +19453,7 @@ function registerSwapCommand(program2) {
19465
19453
  console.log(label("Route", dim(route)));
19466
19454
  }
19467
19455
  console.log("");
19468
- console.log(dim(`To execute: amiko swap send ${amountStr} ${fromToken} ${toToken}`));
19456
+ console.log(dim(`To execute: amiko wallets swap send ${amountStr} ${fromToken} ${toToken}`));
19469
19457
  } catch (err) {
19470
19458
  spinner.stop();
19471
19459
  console.error(error(err instanceof Error ? err.message : "Failed to get quote"));
@@ -19514,7 +19502,7 @@ function registerSwapCommand(program2) {
19514
19502
  cost: "Solana gas + 10bps platform fee",
19515
19503
  summary: `swap ${amountStr} ${fromToken.toUpperCase()} → ~${(Number(quote.outAmount) / 10 ** output.decimals).toFixed(6)} ${output.symbol}`,
19516
19504
  yes: opts.yes,
19517
- commandExample: `amiko swap send ${amountStr} ${fromToken} ${toToken}`
19505
+ commandExample: `amiko wallets swap send ${amountStr} ${fromToken} ${toToken}`
19518
19506
  });
19519
19507
  const swapSpinner = ora("Executing swap via platform...").start();
19520
19508
  let swapData;
@@ -19561,7 +19549,7 @@ function registerSwapCommand(program2) {
19561
19549
  console.log(` ${source_default.cyan(t.symbol.padEnd(10))} ${t.name.padEnd(25)} ${dim(truncAddr(t.address))}`);
19562
19550
  }
19563
19551
  console.log("");
19564
- console.log(dim("Use symbol or mint address: amiko swap quote 5 usdt usdc"));
19552
+ console.log(dim("Use symbol or mint address: amiko wallets swap quote 5 usdt usdc"));
19565
19553
  } catch (err) {
19566
19554
  spinner.stop();
19567
19555
  console.error(error(err instanceof Error ? err.message : "Failed to fetch tokens"));
@@ -19696,7 +19684,7 @@ function registerSearchCommand(program2) {
19696
19684
  cost: `1 ${opts.token || "AMIKO"}`,
19697
19685
  summary: `X/Twitter search: ${query.slice(0, 80)}${query.length > 80 ? "…" : ""}`,
19698
19686
  yes: opts.yes,
19699
- commandExample: `amiko search ${JSON.stringify(query)}${opts.token && opts.token !== "AMIKO" ? ` --token ${opts.token}` : ""}`
19687
+ commandExample: `amiko market search ${JSON.stringify(query)}${opts.token && opts.token !== "AMIKO" ? ` --token ${opts.token}` : ""}`
19700
19688
  });
19701
19689
  const spinner = ora("X Search...").start();
19702
19690
  try {
@@ -19795,7 +19783,7 @@ function registerImageCommand(program2) {
19795
19783
  cost: "5 AMIKO",
19796
19784
  summary: `Generate image: ${prompt.slice(0, 80)}${prompt.length > 80 ? "…" : ""}`,
19797
19785
  yes: opts.yes,
19798
- commandExample: `amiko image ${JSON.stringify(prompt)}`
19786
+ commandExample: `amiko market image ${JSON.stringify(prompt)}`
19799
19787
  });
19800
19788
  const isTTY = process.stderr.isTTY;
19801
19789
  const spinner = isTTY ? ora("Generating image...").start() : null;
@@ -19899,7 +19887,7 @@ function registerImageCommand(program2) {
19899
19887
  console.log(label("URL", img.url));
19900
19888
  } else if (img.b64_json) {
19901
19889
  console.log(label("Format", "base64 (inline image data)"));
19902
- console.log(dim(` ${img.b64_json.length.toLocaleString()} chars — save with: amiko image "..." --raw | jq -r '.images[0].b64_json' | base64 -d > image.png`));
19890
+ console.log(dim(` ${img.b64_json.length.toLocaleString()} chars — save with: amiko market image "..." --raw | jq -r '.images[0].b64_json' | base64 -d > image.png`));
19903
19891
  }
19904
19892
  if (img.revised_prompt && img.revised_prompt !== prompt) {
19905
19893
  console.log(label("Revised", dim(img.revised_prompt)));
@@ -19934,7 +19922,7 @@ function registerAmazonCommand(program2) {
19934
19922
  cost: "1 AMIKO",
19935
19923
  summary: `Amazon product search: ${query.slice(0, 80)}${query.length > 80 ? "…" : ""}`,
19936
19924
  yes: opts.yes,
19937
- commandExample: `amiko amazon search ${JSON.stringify(query)}`
19925
+ commandExample: `amiko market amazon search ${JSON.stringify(query)}`
19938
19926
  });
19939
19927
  const spinner = ora("Searching Amazon...").start();
19940
19928
  try {
@@ -20126,7 +20114,7 @@ function registerServicesCommand(program2) {
20126
20114
  cost: "1 AMIKO",
20127
20115
  summary: `Text-to-speech (voice ${voiceId}): "${text.slice(0, 60)}${text.length > 60 ? "…" : ""}"`,
20128
20116
  yes: opts.yes,
20129
- commandExample: `amiko service tts ${voiceId} ${JSON.stringify(text)}`
20117
+ commandExample: `amiko market service tts ${voiceId} ${JSON.stringify(text)}`
20130
20118
  });
20131
20119
  await callService({
20132
20120
  name: "Text-to-Speech",
@@ -20142,7 +20130,7 @@ function registerServicesCommand(program2) {
20142
20130
  cost: "1 AMIKO",
20143
20131
  summary: `Speech-to-text on ${audioUrl}`,
20144
20132
  yes: opts.yes,
20145
- commandExample: `amiko service stt ${JSON.stringify(audioUrl)}`
20133
+ commandExample: `amiko market service stt ${JSON.stringify(audioUrl)}`
20146
20134
  });
20147
20135
  await callService({
20148
20136
  name: "Speech-to-Text",
@@ -20176,7 +20164,7 @@ function registerServicesCommand(program2) {
20176
20164
  cost: "1 AMIKO",
20177
20165
  summary: `AI chat${opts.model ? ` (model ${opts.model})` : ""}: "${message.slice(0, 60)}${message.length > 60 ? "…" : ""}"`,
20178
20166
  yes: opts.yes,
20179
- commandExample: `amiko service chat ${JSON.stringify(message)}${opts.model ? ` --model ${opts.model}` : ""}`
20167
+ commandExample: `amiko market service chat ${JSON.stringify(message)}${opts.model ? ` --model ${opts.model}` : ""}`
20180
20168
  });
20181
20169
  const body = { message };
20182
20170
  if (opts.model)
@@ -20196,7 +20184,7 @@ function registerServicesCommand(program2) {
20196
20184
  cost: costLabel,
20197
20185
  summary: `${method.toUpperCase()} ${path2}`,
20198
20186
  yes: opts.yes,
20199
- commandExample: `amiko service call ${method.toUpperCase()} ${path2}${bodyStr ? ` ${JSON.stringify(bodyStr)}` : ""}${opts.amiko ? ` --amiko ${opts.amiko}` : ""}${opts.usdc ? ` --usdc ${opts.usdc}` : ""}`
20187
+ commandExample: `amiko market service call ${method.toUpperCase()} ${path2}${bodyStr ? ` ${JSON.stringify(bodyStr)}` : ""}${opts.amiko ? ` --amiko ${opts.amiko}` : ""}${opts.usdc ? ` --usdc ${opts.usdc}` : ""}`
20200
20188
  });
20201
20189
  let body;
20202
20190
  if (bodyStr) {
@@ -21145,6 +21133,98 @@ function registerComposioCommand(program2) {
21145
21133
  });
21146
21134
  }
21147
21135
 
21136
+ // src/commands/wallets.ts
21137
+ function formatBalance(b) {
21138
+ const n = Number(b.amount) / 10 ** b.decimals;
21139
+ if (!isFinite(n))
21140
+ return b.amount;
21141
+ return n.toLocaleString(undefined, { maximumFractionDigits: 6 });
21142
+ }
21143
+ function registerWalletsBalanceCommand(program2) {
21144
+ program2.command("balance <address>").description("Sync and show balance for a single wallet").option("--json", "Output raw JSON").action(async (address2, opts) => {
21145
+ let auth;
21146
+ try {
21147
+ auth = requireAuth();
21148
+ } catch (e) {
21149
+ console.error(error(e instanceof Error ? e.message : String(e)));
21150
+ process.exit(1);
21151
+ }
21152
+ const spinner = opts.json ? null : ora("Syncing wallet balance...").start();
21153
+ try {
21154
+ const data = await amikoWebFetch(auth, `/api/agents/${encodeURIComponent(auth.twinId)}/wallets/${encodeURIComponent(address2)}/balance`);
21155
+ spinner?.stop();
21156
+ if (opts.json) {
21157
+ console.log(JSON.stringify(data, null, 2));
21158
+ return;
21159
+ }
21160
+ console.log(heading("Wallet Balance"));
21161
+ console.log("");
21162
+ console.log(label("Address", data.walletAddress));
21163
+ console.log(label("Chain", data.chain_type));
21164
+ if (data.last_synced_at) {
21165
+ console.log(label("Synced", data.last_synced_at));
21166
+ }
21167
+ const entries = Object.entries(data.balances || {});
21168
+ if (entries.length === 0) {
21169
+ console.log(dim(" No balances."));
21170
+ return;
21171
+ }
21172
+ console.log("");
21173
+ const rows = entries.map(([key, v]) => [` ${key}`, formatBalance(v)]);
21174
+ console.log(table(rows));
21175
+ } catch (e) {
21176
+ spinner?.stop();
21177
+ console.error(error(e instanceof Error ? e.message : "Failed to fetch balance"));
21178
+ process.exit(1);
21179
+ }
21180
+ });
21181
+ }
21182
+ function registerWalletsListCommand(program2) {
21183
+ program2.command("list").alias("ls").description("List wallets for the authenticated twin").option("--json", "Output raw JSON").action(async (opts) => {
21184
+ let auth;
21185
+ try {
21186
+ auth = requireAuth();
21187
+ } catch (e) {
21188
+ console.error(error(e instanceof Error ? e.message : String(e)));
21189
+ process.exit(1);
21190
+ }
21191
+ const spinner = opts.json ? null : ora("Fetching wallets...").start();
21192
+ try {
21193
+ const data = await amikoWebFetch(auth, `/api/agents/${encodeURIComponent(auth.twinId)}/wallets`);
21194
+ spinner?.stop();
21195
+ if (opts.json) {
21196
+ console.log(JSON.stringify(data, null, 2));
21197
+ return;
21198
+ }
21199
+ const wallets = data.wallets || [];
21200
+ if (wallets.length === 0) {
21201
+ console.log(dim("No wallets found."));
21202
+ return;
21203
+ }
21204
+ console.log(heading("Wallets"));
21205
+ console.log("");
21206
+ for (const w of wallets) {
21207
+ console.log(label("Chain", `${w.chain} (${w.chain_type})`));
21208
+ if (w.name)
21209
+ console.log(label("Name", w.name));
21210
+ console.log(label("Address", w.wallet_address));
21211
+ console.log(label("Short", truncAddr(w.wallet_address)));
21212
+ const balances = Object.entries(w.balance || {}).filter(([, v]) => Number(v.amount) > 0);
21213
+ if (balances.length > 0) {
21214
+ console.log(dim(" Balances:"));
21215
+ const rows = balances.map(([key, v]) => [` ${key}`, formatBalance(v)]);
21216
+ console.log(table(rows));
21217
+ }
21218
+ console.log("");
21219
+ }
21220
+ } catch (e) {
21221
+ spinner?.stop();
21222
+ console.error(error(e instanceof Error ? e.message : "Failed to list wallets"));
21223
+ process.exit(1);
21224
+ }
21225
+ });
21226
+ }
21227
+
21148
21228
  // src/index.ts
21149
21229
  var require2 = createRequire2(import.meta.url);
21150
21230
  var { version: PKG_VERSION } = require2("../package.json");
@@ -21152,16 +21232,20 @@ var didOnboard = await runOnboarding(process.argv);
21152
21232
  if (didOnboard)
21153
21233
  process.exit(0);
21154
21234
  var program2 = new Command;
21155
- program2.name("amiko").description("Amiko CLI — swap tokens, manage credits, bridge cross-chain, and call MPP services").version(PKG_VERSION);
21235
+ program2.name("amiko").description("Amiko CLI — swap tokens, manage credits, bridge cross-chain, and call marketplace services").version(PKG_VERSION);
21236
+ var market = program2.command("market").description("MPP marketplace — discover and call paid AMIKO services");
21237
+ var wallets = program2.command("wallets").description("Manage twin wallets — list, swap, bridge");
21156
21238
  registerCreditsCommand(program2);
21157
- registerSearchCommand(program2);
21158
- registerImageCommand(program2);
21159
- registerAmazonCommand(program2);
21160
- registerSwapCommand(program2);
21161
- registerBridgeCommand(program2);
21239
+ registerSearchCommand(market);
21240
+ registerImageCommand(market);
21241
+ registerAmazonCommand(market);
21242
+ registerWalletsListCommand(wallets);
21243
+ registerWalletsBalanceCommand(wallets);
21244
+ registerSwapCommand(wallets);
21245
+ registerBridgeCommand(wallets);
21162
21246
  registerConfigCommand(program2);
21163
- registerServicesCommand(program2);
21164
- registerDiscoveryCommand(program2);
21247
+ registerServicesCommand(market);
21248
+ registerDiscoveryCommand(market);
21165
21249
  registerUpdateCommand(program2);
21166
21250
  registerAccountsCommand(program2);
21167
21251
  registerTwinCommand(program2);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@heyamiko/amiko-cli",
3
- "version": "0.9.0-beta.0",
3
+ "version": "0.9.0-beta.5",
4
4
  "description": "Amiko CLI — swap tokens, manage credits, bridge cross-chain, and call marketplace agents",
5
5
  "type": "module",
6
6
  "bin": {
package/skills/SKILL.md CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: amiko-cli
3
- description: Token swaps, credits, search, image generation, audio, and MPP marketplace services
4
- homepage: https://mpp.amikomarkets.com
3
+ description: Token swaps, credits, marketplace (search/image/amazon/audio), and twin/social operations on Amiko
4
+ homepage: https://platform.heyamiko.com
5
5
  metadata: {"openclaw":{"emoji":"🤖","requires":{"bins":["node"]}}}
6
6
  ---
7
7
 
@@ -9,238 +9,195 @@ metadata: {"openclaw":{"emoji":"🤖","requires":{"bins":["node"]}}}
9
9
 
10
10
  ## How to invoke
11
11
 
12
- Run `amiko <command>` via your **shell execution tool** (e.g. `bash`). This skill is a documentation reference, not a callable tool. **Do NOT** try to call `amiko_cli`, `amiko-cli`, `amiko`, or this skill's name as a tool — no such tool exists. The only working invocation is the shell command `amiko`.
12
+ Run `amiko <command>` via your **shell execution tool** (e.g. `bash`). This skill is documentation, not a callable tool. **Do NOT** try to call `amiko_cli`, `amiko-cli`, `amiko`, or this skill's name as a tool — no such tool exists. The only working invocation is the shell command `amiko`.
13
13
 
14
- The `amiko` CLI is installed globally. Auth and payments are automatic via `.amiko.json` — never suggest `amiko login` or `amiko connect`.
14
+ The `amiko` CLI is installed globally. Auth is automatic via `.amiko.json` (walking up from cwd, falling back to `/data/.openclaw/workspace/.amiko.json`) — never suggest `amiko login` or `amiko connect`.
15
+
16
+ ## Command layout (v0.9+)
17
+
18
+ The top level has three groups:
19
+
20
+ - `amiko market <cmd>` — paid MPP services (search, image, amazon, service, discover)
21
+ - `amiko wallets <cmd>` — wallet operations (list, balance, swap, bridge)
22
+ - `amiko credits <cmd>` — credit balance and topup
23
+
24
+ Plus flat commands: `config`, `update`, `accounts`, `info`, `twin:*`, `docs*`, `voice:*`, `avatar:*`, `friends*`, `feed`, `post:*`, `composio:*`.
15
25
 
16
26
  ## Critical Rules
17
27
 
18
- 1. **Every paid / value-moving command is hard-gated on `--yes` in a non-interactive shell.** The CLI will *refuse* to run `image`, `search`, `amazon search`, `service call`, `service tts`, `service stt`, `service chat`, `credits topup`, `swap send`, or `bridge send` unless you pass `--yes`. The refusal is loud: it prints the cost and the command you should re-run with `--yes` appended. This means: **you must first quote the cost to the user, get their explicit approval, and only then append `--yes`**. If the user didn't approve, do not add `--yes`. The same applies to destructive non-paid commands (`twin:update --public`, `docs:delete`, `friends:remove`, `avatar:update`, `voice:reset`, `composio:disconnect`).
19
- 2. **After every paid command, report the remaining balance to the user.** The CLI prints a `Balance: N credits (~$X.XX)` line at the end of every paid command — include that figure in your reply so the user knows what they have left.
20
- 3. **Never retry a failed command.** If a command returns an error, report it and stop. Every paid call costs tokens even on failure.
21
- 4. **Never suggest `amiko login` or `amiko connect`.** These commands don't exist. Auth is automatic via `.amiko.json`.
22
- 5. **Check balance before expensive operations.** Run `amiko credits balance` first if unsure about funds.
23
- 6. **Payments are automatic.** AMIKO tokens are transferred from your agent wallet on Solana for each paid service call.
28
+ 1. **Every paid / value-moving command is hard-gated on `--yes` in a non-interactive shell.** The CLI *refuses* to run `market image`, `market search`, `market amazon search`, `market service call`, `market service tts`, `market service stt`, `market service chat`, `credits topup`, `wallets swap send`, or `wallets bridge send` unless `--yes` is passed. The refusal is loud: it prints the cost and the command you should re-run. **Quote the cost to the user, get explicit approval, THEN append `--yes`**. Same for destructive non-paid commands (`twin:update --public`, `docs:delete`, `friends:remove`, `avatar:update`, `voice:reset`, `composio:disconnect`).
29
+ 2. **After every paid command, report the remaining balance.** The CLI prints a `Balance: N credits` line at the end of every paid command — include that figure in your reply.
30
+ 3. **Never retry a failed command.** Report the error and stop. Every paid call costs tokens even on failure.
31
+ 4. **Never suggest `amiko login` or `amiko connect`.** These don't exist. Auth is automatic via `.amiko.json`.
32
+ 5. **Check balance before expensive operations.** Run `amiko credits balance` first if unsure.
33
+ 6. **Payments are automatic.** The platform signs and moves tokens from the twin's wallet for each paid call — the CLI never holds keys.
24
34
 
25
35
  ### Pricing cheat sheet (quote this to the user before running)
26
36
 
27
37
  | Command | Cost |
28
38
  |---------|------|
29
- | `amiko search "<query>"` | 1 AMIKO |
30
- | `amiko image "<prompt>"` | 5 AMIKO |
31
- | `amiko amazon search "<query>"` | 1 AMIKO |
32
- | `amiko amazon quote <ASIN>` | Free |
33
- | `amiko service tts <voiceId> "<text>"` | 1 AMIKO |
34
- | `amiko service call POST /v1/sfx ...` | $0.05 |
35
- | `amiko service call POST /v1/music ...` | $0.10 |
36
- | `amiko service call POST /v1/music/plan ...` | $0.02 |
37
- | `amiko swap quote ...` | Free |
38
- | `amiko swap send ...` | Solana gas only |
39
+ | `amiko market search "<query>"` | 1 AMIKO |
40
+ | `amiko market image "<prompt>"` | 5 AMIKO |
41
+ | `amiko market amazon search "<query>"` | 1 AMIKO |
42
+ | `amiko market amazon quote <ASIN>` | Free |
43
+ | `amiko market service tts <voiceId> "<text>"` | 1 AMIKO |
44
+ | `amiko market service call POST /v1/sfx ...` | $0.05 |
45
+ | `amiko market service call POST /v1/music ...` | $0.10 |
46
+ | `amiko market service call POST /v1/music/plan ...` | $0.02 |
47
+ | `amiko wallets swap quote ...` | Free |
48
+ | `amiko wallets swap send ...` | Solana gas + 10bps |
39
49
  | `amiko credits topup ...` | Whatever amount you top up |
40
50
 
41
- ## Commands
42
-
43
- ### Credits & Wallet
44
-
45
- **Credits are NOT tokens.** 10,000 credits = $1.00 USD.
46
-
47
- The `topup` command accepts **one** of three amount forms:
48
-
49
- | Form | Meaning | Example |
50
- |------|---------|---------|
51
- | `<amount>` (positional) | credits | `amiko credits topup 10000 --token AMIKO` → 10,000 credits = $1 |
52
- | `--usd <n>` | US dollars | `amiko credits topup --usd 5 --token USDC` → $5 = 50,000 credits |
53
- | `--spend <n>` | spend N of `--token` | `amiko credits topup --spend 1 --token SOL` → "1 SOL worth of credits" |
51
+ ## Credits
54
52
 
55
- **Map user intent directly to the right form** — no manual price math needed:
56
-
57
- - "top up 1 SOL of credits" → `amiko credits topup --spend 1 --token SOL`
58
- - "top up 1 USDC worth of credits" → `amiko credits topup --spend 1 --token USDC`
59
- - "top up 1 AMIKO" → `amiko credits topup --spend 1 --token AMIKO`
60
- - "top up $5 in USDC" → `amiko credits topup --usd 5 --token USDC`
61
- - "top up 10000 credits with AMIKO" → `amiko credits topup 10000 --token AMIKO`
62
-
63
- **Always confirm with the user before running.** The CLI prints a `Top-up Summary` (credits, cost in tokens, USD, wallet) and then prompts `Proceed? [y/N]`. Do NOT pass `--yes` unless the user has explicitly approved the summary.
53
+ **Display credits: 10,000 credits = $1.00 USD.**
64
54
 
65
55
  ```bash
66
- amiko credits balance # credit balance + wallet balances
67
- amiko credits topup --spend 1 --token SOL # "1 SOL worth of credits" — prompts
68
- amiko credits topup --usd 5 --token USDC # $5 paying in USDC — prompts
69
- amiko credits topup 10000 --token AMIKO --yes # skip prompt (only after user approved summary)
56
+ amiko credits balance # show balance as "N credits"
57
+ amiko credits topup --spend 1 --token SOL --yes # "1 SOL worth of credits"
58
+ amiko credits topup --usd 5 --token USDC --yes # $5 paying in USDC
59
+ amiko credits topup 10000 --token AMIKO --yes # 10,000 credits = $1
70
60
  ```
71
61
 
72
- **How topup works:**
73
- 1. You specify credits (e.g. 10000 = $1.00)
74
- 2. CLI fetches live token price via Jupiter
75
- 3. Transfers the equivalent token amount from your agent wallet to treasury
76
- 4. Verifies on-chain and credits your account
77
-
78
- Supported tokens: AMIKO, SOL, USDC, USDT. All payments come from your agent's Solana wallet.
62
+ `topup` accepts **one** of three amount forms:
79
63
 
80
- ### Search (1 AMIKO)
81
-
82
- ```bash
83
- amiko search "AI agents" # search X/Twitter
84
- amiko search "bitcoin" --raw # raw JSON output
85
- ```
64
+ | Form | Meaning | Example |
65
+ |------|---------|---------|
66
+ | `<amount>` (positional) | credits | `amiko credits topup 10000 --token AMIKO` |
67
+ | `--usd <n>` | US dollars | `amiko credits topup --usd 5 --token USDC` |
68
+ | `--spend <n>` | spend N of `--token` | `amiko credits topup --spend 1 --token SOL` |
86
69
 
87
- ### Image Generation (5 AMIKO)
70
+ Map user intent directly — no manual price math:
88
71
 
89
- ```bash
90
- amiko image "a sunset over mountains" # gpt-image-1 (default)
91
- amiko image "logo" --background transparent # transparent background
92
- amiko image "portrait" --size 1024x1792 # custom size
93
- ```
72
+ - "top up 1 SOL of credits" → `--spend 1 --token SOL`
73
+ - "top up $5 in USDC" → `--usd 5 --token USDC`
74
+ - "top up 10000 credits with AMIKO" → `10000 --token AMIKO`
94
75
 
95
- Returns a permanent Supabase Storage URL.
76
+ Supported tokens: AMIKO, SOL, USDC, USDT. The CLI fetches the live price, the platform transfers from the twin's wallet, and on-chain verification credits the account.
96
77
 
97
- ### Amazon
78
+ ## Wallets
98
79
 
99
80
  ```bash
100
- amiko amazon search "usb c cable" # product search (1 AMIKO)
101
- amiko amazon quote B01GGKYKQM # price quote (free)
81
+ amiko wallets list # all twin wallets + cached balances
82
+ amiko wallets balance <address> # force-sync one wallet; returns fresh balances
83
+ amiko wallets swap quote 1.0 SOL USDC # Jupiter quote (free)
84
+ amiko wallets swap send 1.0 SOL USDC --wallet <addr> --yes
85
+ amiko wallets swap tokens # supported tokens list
86
+ amiko wallets bridge quote 10 --from solana --to tempo
87
+ amiko wallets bridge send 10 --from solana --to tempo --yes
88
+ amiko wallets bridge status <txHash>
89
+ amiko wallets bridge routes
90
+ amiko wallets bridge limits
102
91
  ```
103
92
 
104
- ### Token Swaps
93
+ `wallets list` returns cached balances (platform doesn't auto-sync). If balances look stale, run `wallets balance <address>` to force a sync for that wallet.
105
94
 
106
- ```bash
107
- amiko swap quote 1.0 SOL USDC # get Jupiter quote
108
- amiko swap send 1.0 SOL USDC --yes # execute swap
109
- amiko swap tokens # list supported tokens
110
- ```
95
+ Swaps run via Jupiter on Solana. Supported: SOL, USDC, USDT, AMIKO, PYUSD, BONK, JUP, RAY, JitoSOL — or any mint address. Bridging goes through Across Protocol.
111
96
 
112
- Swaps execute via Jupiter on Solana. Supports: SOL, USDC, USDT, AMIKO, PYUSD, BONK, JUP, RAY, JitoSOL, mSOL, or any mint address.
113
-
114
- ### MPP Services
97
+ ## Market (paid MPP services)
115
98
 
116
99
  ```bash
117
- amiko service list # all services + prices
118
-
119
- # Sound effects ($0.05) — returns { url, format, service }
120
- amiko service call POST /v1/sfx '{"text":"thunder","duration_seconds":5}'
121
-
122
- # Music generation ($0.10) — returns { url, format, service }
123
- amiko service call POST /v1/music '{"prompt":"lo-fi beat","music_length_ms":30000}'
124
-
125
- # Text-to-speech (1 AMIKO) — returns { url, format, service }
126
- amiko service tts 21m00Tcm4TlvDq8ikWAM "Hello world"
127
-
128
- # Composition plan ($0.02)
129
- amiko service call POST /v1/music/plan '{"prompt":"epic orchestral"}'
130
-
131
- # Any endpoint
132
- amiko service call <METHOD> <path> [body]
100
+ amiko market search "AI agents" # 1 AMIKO — X/Twitter search
101
+ amiko market image "a sunset over mountains" --yes # 5 AMIKO — gpt-image-1 by default
102
+ amiko market image "logo" --background transparent # transparent bg
103
+ amiko market image "portrait" --size 1024x1792 # custom size
104
+ amiko market amazon search "usb c cable" # 1 AMIKO — product search
105
+ amiko market amazon quote B01GGKYKQM # free — price quote
106
+ amiko market service list # all services + prices
107
+ amiko market service call POST /v1/sfx '{"text":"thunder","duration_seconds":5}'
108
+ amiko market service call POST /v1/music '{"prompt":"lo-fi beat","music_length_ms":30000}'
109
+ amiko market service tts 21m00Tcm4TlvDq8ikWAM "Hello world"
110
+ amiko market service call POST /v1/music/plan '{"prompt":"epic orchestral"}'
111
+ amiko market service call <METHOD> <path> [body] # any MPP endpoint
112
+ amiko market discover # service info + pricing
133
113
  ```
134
114
 
135
- Audio and image endpoints return permanent Supabase Storage URLs.
115
+ Paid market commands require `--wallet <address>` (the Solana wallet that pays) unless one can be resolved from `.amiko.json`. Audio and image endpoints return permanent Supabase Storage URLs.
136
116
 
137
- ### Bridge
117
+ ## Account & Twin
138
118
 
139
119
  ```bash
140
- amiko bridge quote 10 # cross-chain USDC quote
141
- amiko bridge send 10 --from solana --to tempo # execute bridge
120
+ amiko accounts # resolved identity (authenticated, userId, twinId, platform)
121
+ amiko info # twin info (name, description, public, voice, avatar)
122
+ amiko twin:update --name "New Name"
123
+ amiko twin:update --description "..."
124
+ amiko twin:update --public true --yes # destructive — requires --yes in non-TTY
142
125
  ```
143
126
 
144
- ### Other
145
-
146
- ```bash
147
- amiko discovery # MPP service info + pricing
148
- amiko config show # view config
149
- amiko update # update CLI to latest (on twins: also refreshes /data, symlink, skill)
150
- amiko --help # all commands
151
- ```
152
-
153
- Agent wallet balances are surfaced by `amiko credits balance` (shows credit balance + wallet balances across all chains in one call). There is no standalone `wallet` command.
127
+ All twin-scoped commands accept `--twin <id>` to target a non-default twin.
154
128
 
155
- ### Account & Twin
129
+ ## Documents (RAG)
156
130
 
157
131
  ```bash
158
- amiko accounts # show resolved identity (mode, platform, user, active twin, wallets)
159
- amiko info # fetch twin info (name, description, is_public, voice, avatar)
160
- amiko twin:update --name "New Name" # rename the twin
161
- amiko twin:update --description "..." # update bio
162
- amiko twin:update --public true --yes # flip visibility (destructive — requires --yes in non-TTY)
132
+ amiko docs # list
133
+ amiko docs:upload ./notes.pdf # path
134
+ amiko docs:upload https://example.com/x.pdf # URL
135
+ cat file.pdf | amiko docs:upload - --stdin --name file.pdf
136
+ amiko docs:delete <docId> --yes # destructive
137
+ amiko docs:presign ./file.pdf # presigned S3 URL only
163
138
  ```
164
139
 
165
- All twin-scoped commands accept `--twin <id>` to target a non-default twin.
166
-
167
- ### Documents (RAG)
140
+ ## Voice
168
141
 
169
142
  ```bash
170
- amiko docs # list uploaded documents
171
- amiko docs:upload ./notes.pdf # upload a local file
172
- amiko docs:upload https://example.com/x.pdf # upload from URL
173
- cat file.pdf | amiko docs:upload - --stdin --name file.pdf # upload from stdin
174
- amiko docs:delete <docId> --yes # delete (destructive)
175
- amiko docs:presign ./file.pdf # get a presigned S3 URL (no upload)
143
+ amiko voice:design --description "warm, low, male, confident, measured" # min 20 chars
144
+ amiko voice:create --sample <generated_voice_id>
145
+ amiko voice:clone ./me.mp3 # path | URL | -
146
+ amiko voice:reset --yes # destructive
176
147
  ```
177
148
 
178
- ### Voice
149
+ ## Avatar
179
150
 
180
151
  ```bash
181
- amiko voice:design --description "warm, low, male, confident, measured" # min 20 chars; returns preview IDs
182
- amiko voice:create --sample <generated_voice_id> # commit a designed preview
183
- amiko voice:clone ./me.mp3 # clone from an audio file (path | URL | -)
184
- amiko voice:reset --yes # revert to default (destructive)
152
+ amiko avatar:update --file ./portrait.png --yes # max 5 MB, destructive
185
153
  ```
186
154
 
187
- ### Avatar
155
+ ## Friends
188
156
 
189
157
  ```bash
190
- amiko avatar:update --file ./portrait.png --yes # max 5 MB image/* (destructive — changes public avatar)
158
+ amiko friends # list all
159
+ amiko friends --type user # filter
160
+ amiko friends:add --id <userId>
161
+ amiko friends:accept <friendshipId>
162
+ amiko friends:remove <friendshipId> --yes # destructive
191
163
  ```
192
164
 
193
- ### Friends
165
+ ## Feed & Posts
194
166
 
195
167
  ```bash
196
- amiko friends # list all friends
197
- amiko friends --type user # filter user-to-user
198
- amiko friends:add --id <userId> # send friend request
199
- amiko friends:accept <friendshipId> # accept pending
200
- amiko friends:remove <friendshipId> --yes # remove (destructive)
168
+ amiko feed # friends feed (default)
169
+ amiko feed --type for_you --limit 20
170
+ amiko feed --hashtag ai
171
+ amiko post:create --content "hello from the CLI"
172
+ amiko post:create --content "private note" --visibility private
173
+ amiko post:create --content "look" --media https://...jpg
174
+ amiko post:comment --id <postId> --comment "great post"
175
+ amiko post:comment --id <postId> --comment "look" --media https://...jpg
176
+ amiko post:comment --id <postId> --comment "..." --twin <id>
201
177
  ```
202
178
 
203
- ### Feed & Posts
179
+ ## Composio
204
180
 
205
181
  ```bash
206
- amiko feed # friends feed (default)
207
- amiko feed --type for_you --limit 20 # public for-you feed
208
- amiko feed --hashtag ai # filter by hashtag
209
- amiko post:create --content "hello from the CLI" # public post (default)
210
- amiko post:create --content "private note" --visibility private # private post
211
- amiko post:create --content "look" --media https://...jpg # attach media URL(s)
212
- amiko post:comment --id <postId> --comment "great post" # comment as user
213
- amiko post:comment --id <postId> --comment "look" --media https://...jpg # comment with attached media
214
- amiko post:comment --id <postId> --comment "..." --twin <id> # comment as the twin
182
+ amiko composio:connect --app gmail # prints OAuth URL
183
+ amiko composio:disconnect --app gmail --yes # destructive
215
184
  ```
216
185
 
217
- ### Composio (external apps)
186
+ ## Other
218
187
 
219
188
  ```bash
220
- amiko composio:connect --app gmail # prints OAuth URL — open in a browser
221
- amiko composio:disconnect --app gmail --yes # disconnect (destructive)
189
+ amiko config show # resolved config
190
+ amiko update # self-update
191
+ amiko --help # top-level help
192
+ amiko <group> --help # e.g. `amiko wallets --help`
222
193
  ```
223
194
 
224
- ### JSON output
195
+ ## JSON output
225
196
 
226
- Every new command supports `--json` for structured output suitable for piping or parsing:
197
+ Most commands support `--json` for structured output:
227
198
 
228
199
  ```bash
200
+ amiko wallets list --json | jq '.wallets[].wallet_address'
229
201
  amiko friends --json | jq '.items[] | .friend.name'
230
202
  amiko info --json | jq -r '.name'
231
203
  ```
232
-
233
- ## Service Costs
234
-
235
- | Service | Cost | Command |
236
- |---------|------|---------|
237
- | X/Twitter search | 1 AMIKO | `amiko search "<query>"` |
238
- | Image generation | 5 AMIKO | `amiko image "<prompt>"` |
239
- | Amazon search | 1 AMIKO | `amiko amazon search "<query>"` |
240
- | Amazon quote | Free | `amiko amazon quote <ASIN>` |
241
- | Sound effects | $0.05 | `amiko service call POST /v1/sfx ...` |
242
- | Music generation | $0.10 | `amiko service call POST /v1/music ...` |
243
- | Text-to-speech | 1 AMIKO | `amiko service tts <voiceId> "<text>"` |
244
- | Swap quote | Free | `amiko swap quote ...` |
245
- | Swap execute | Gas only | `amiko swap send ...` |
246
- | Credit top-up | Amount in credits (10,000 = $1) | `amiko credits topup <credits>` |