@heyamiko/amiko-cli 0.12.0-beta.1 → 0.12.0-beta.3

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
@@ -182,9 +182,19 @@ Modes: `image`, `video`, `tts`, `music`, `sfx` (mirrors the platform Create Stud
182
182
 
183
183
  ### How it works (and getting the result)
184
184
 
185
- The CLI **submits the job, then blocks and polls until it finishes** (video can take several minutes), printing the asset URL, whether you were charged, and the charge tx on success. In non-TTY environments it prints a `…still generating (Ns elapsed)` tick to stderr. `--raw` prints the full job result as JSON.
185
+ **By default the command returns immediately** with a **job id** and `status: PENDING` — it does **not** block for the whole generation. It prints how to check the result and a rough ETA. This keeps agents/scripts from being held for 60s–9min.
186
186
 
187
- If the poll window elapses (10 min for video, 5 min otherwise) the CLI does **not** treat it as failure — the generation may still complete server-side. It prints the **job id**; retrieve the finished asset with either:
187
+ ```
188
+ $ amiko create image "a whale in space" --yes
189
+ Submitted — job aX9k…
190
+ Status: PENDING — generating in the background
191
+ Check result: amiko create status aX9k…
192
+ Usually ready in ~15–60s — charged only on success.
193
+ ```
194
+
195
+ Rough ETAs: image ~15–60s, video ~2–9 min, music ~30–120s, tts/sfx ~5–20s.
196
+
197
+ Retrieve the finished asset with:
188
198
 
189
199
  ```bash
190
200
  amiko create status <jobId> # re-query that job (queryable ~24h)
@@ -192,10 +202,12 @@ amiko create media # list your recent generations (permanent)
192
202
  amiko create media --service video --limit 5
193
203
  ```
194
204
 
195
- - **`amiko create status <jobId>`** — re-polls the job once and prints its status / asset. Jobs stay queryable for ~24h.
205
+ - **`amiko create status <jobId>`** — re-polls the job once; prints `PROCESSING`, or the asset + charge when done. Jobs stay queryable for ~24h.
196
206
  - **`amiko create media`** — lists your recent Create Studio generations (URL, type, model, prompt, date). `--service <type>` filters, `--limit <n>` caps (max 50), `--raw` for JSON. Use this once a job id has expired, or just to browse.
197
207
  - **Web:** `https://platform.heyamiko.com/media`
198
208
 
209
+ **`--wait`** — if you'd rather block until it finishes and print the asset inline (e.g. an interactive terminal), pass `--wait`. It polls (10 min cap for video, 5 min otherwise) with a `…still generating (Ns)` tick; on timeout it falls back to the job-id + retrieval hint above. `--raw` prints the full job result as JSON either way.
210
+
199
211
  > `amiko markets image` still exists and is unchanged — it's the direct MPP pay-per-call path (pre-pay in AMIKO). Use `amiko create` for the Create Studio experience (async, charge-on-success); use `amiko markets` for raw MPP endpoints.
200
212
 
201
213
  ## Amazon
package/dist/index.js CHANGED
@@ -28590,6 +28590,13 @@ function registerImageCommand(program2) {
28590
28590
 
28591
28591
  // src/commands/create.ts
28592
28592
  var POLL_INTERVAL_MS = 3000;
28593
+ var ETA = {
28594
+ IMAGE: "~15–60s",
28595
+ VIDEO: "~2–9 min",
28596
+ MUSIC: "~30–120s",
28597
+ TTS: "~5–20s",
28598
+ SFX: "~5–20s"
28599
+ };
28593
28600
  function statusOf(err) {
28594
28601
  return err?.status;
28595
28602
  }
@@ -28679,6 +28686,23 @@ async function submitAndPoll(opts) {
28679
28686
  console.error(error(e5 instanceof Error ? e5.message : "Submit failed"));
28680
28687
  process.exit(1);
28681
28688
  }
28689
+ if (!opts.wait) {
28690
+ stop();
28691
+ if (opts.raw) {
28692
+ console.log(JSON.stringify({
28693
+ jobId,
28694
+ status: "PENDING",
28695
+ check: `amiko create status ${jobId}`,
28696
+ eta: ETA[opts.mode]
28697
+ }, null, 2));
28698
+ return;
28699
+ }
28700
+ console.log(success(`Submitted — job ${jobId}`));
28701
+ console.log(label("Status", "PENDING — generating in the background"));
28702
+ console.log(label("Check result", `amiko create status ${jobId}`));
28703
+ console.log(dim(`Usually ready in ${ETA[opts.mode]} — charged only on success. (Also: amiko create media)`));
28704
+ return;
28705
+ }
28682
28706
  setStatus("Generating…");
28683
28707
  startTicker();
28684
28708
  const maxMs = opts.mode === "VIDEO" ? 600000 : 300000;
@@ -28717,12 +28741,13 @@ async function submitAndPoll(opts) {
28717
28741
  printCompleted(final, `${opts.mode[0]}${opts.mode.slice(1).toLowerCase()} created`);
28718
28742
  }
28719
28743
  function registerCreateCommand(create2) {
28720
- create2.command("image <prompt>").description("Generate an image (Create Studio)").option("--model <model>", "Image model", "gpt-image-2").option("--aspect <ratio>", "Aspect ratio: 1:1, 16:9, 9:16, 4:3, 3:4", "1:1").option("--token <symbol>", "Preferred charge token: AMIKO, USDC, USDT, SOL").option("--raw", "Output raw JSON").option("--yes", "Skip the pre-spend confirmation (required in non-interactive shells)").action(async (prompt, opts) => {
28744
+ create2.command("image <prompt>").description("Generate an image (Create Studio)").option("--model <model>", "Image model", "gpt-image-2").option("--aspect <ratio>", "Aspect ratio: 1:1, 16:9, 9:16, 4:3, 3:4", "1:1").option("--token <symbol>", "Preferred charge token: AMIKO, USDC, USDT, SOL").option("--raw", "Output raw JSON").option("--yes", "Skip the pre-spend confirmation (required in non-interactive shells)").option("--wait", "Block until generation finishes and print the asset (default: return a job id immediately)").action(async (prompt, opts) => {
28721
28745
  await submitAndPoll({
28722
28746
  mode: "IMAGE",
28723
28747
  summary: `Create image: ${prompt.slice(0, 80)}${prompt.length > 80 ? "…" : ""}`,
28724
28748
  raw: opts.raw,
28725
28749
  yes: opts.yes,
28750
+ wait: opts.wait,
28726
28751
  quoteBody: { mode: "IMAGE", model: opts.model, size: opts.aspect },
28727
28752
  jobBody: {
28728
28753
  mode: "IMAGE",
@@ -28733,7 +28758,7 @@ function registerCreateCommand(create2) {
28733
28758
  }
28734
28759
  });
28735
28760
  });
28736
- create2.command("video <prompt>").description("Generate a video (Create Studio)").option("--model <model>", "Video model", "MiniMax-Hailuo-2.3-Fast").option("--resolution <res>", "512P, 720P, 768P, 1080P", "768P").option("--seconds <n>", "Clip length: 6 or 10", "6").option("--aspect <ratio>", "Aspect ratio (provider-dependent)").option("--first-frame <url>", "Image-to-video: first frame URL/data URI").option("--token <symbol>", "Preferred charge token: AMIKO, USDC, USDT, SOL").option("--raw", "Output raw JSON").option("--yes", "Skip the pre-spend confirmation (required in non-interactive shells)").action(async (prompt, opts) => {
28761
+ create2.command("video <prompt>").description("Generate a video (Create Studio)").option("--model <model>", "Video model", "MiniMax-Hailuo-2.3-Fast").option("--resolution <res>", "512P, 720P, 768P, 1080P", "768P").option("--seconds <n>", "Clip length: 6 or 10", "6").option("--aspect <ratio>", "Aspect ratio (provider-dependent)").option("--first-frame <url>", "Image-to-video: first frame URL/data URI").option("--token <symbol>", "Preferred charge token: AMIKO, USDC, USDT, SOL").option("--raw", "Output raw JSON").option("--yes", "Skip the pre-spend confirmation (required in non-interactive shells)").option("--wait", "Block until generation finishes and print the asset (default: return a job id immediately)").action(async (prompt, opts) => {
28737
28762
  const seconds = Number(opts.seconds);
28738
28763
  if (seconds !== 6 && seconds !== 10) {
28739
28764
  console.error(error("--seconds must be 6 or 10."));
@@ -28744,6 +28769,7 @@ function registerCreateCommand(create2) {
28744
28769
  summary: `Create video: ${prompt.slice(0, 80)}${prompt.length > 80 ? "…" : ""}`,
28745
28770
  raw: opts.raw,
28746
28771
  yes: opts.yes,
28772
+ wait: opts.wait,
28747
28773
  quoteBody: {
28748
28774
  mode: "VIDEO",
28749
28775
  model: opts.model,
@@ -28762,12 +28788,13 @@ function registerCreateCommand(create2) {
28762
28788
  }
28763
28789
  });
28764
28790
  });
28765
- create2.command("tts <text>").description("Generate speech from text (Create Studio)").option("--model <model>", "TTS model id", "eleven_multilingual_v2").option("--voice <voiceId>", "Voice id", "21m00Tcm4TlvDq8ikWAM").option("--token <symbol>", "Preferred charge token: AMIKO, USDC, USDT, SOL").option("--raw", "Output raw JSON").option("--yes", "Skip the pre-spend confirmation (required in non-interactive shells)").action(async (text, opts) => {
28791
+ create2.command("tts <text>").description("Generate speech from text (Create Studio)").option("--model <model>", "TTS model id", "eleven_multilingual_v2").option("--voice <voiceId>", "Voice id", "21m00Tcm4TlvDq8ikWAM").option("--token <symbol>", "Preferred charge token: AMIKO, USDC, USDT, SOL").option("--raw", "Output raw JSON").option("--yes", "Skip the pre-spend confirmation (required in non-interactive shells)").option("--wait", "Block until generation finishes and print the asset (default: return a job id immediately)").action(async (text, opts) => {
28766
28792
  await submitAndPoll({
28767
28793
  mode: "TTS",
28768
28794
  summary: `Create speech: ${text.slice(0, 80)}${text.length > 80 ? "…" : ""}`,
28769
28795
  raw: opts.raw,
28770
28796
  yes: opts.yes,
28797
+ wait: opts.wait,
28771
28798
  quoteBody: { mode: "TTS", model: opts.model, prompt: text },
28772
28799
  jobBody: {
28773
28800
  mode: "TTS",
@@ -28778,7 +28805,7 @@ function registerCreateCommand(create2) {
28778
28805
  }
28779
28806
  });
28780
28807
  });
28781
- create2.command("music [prompt]").description("Generate music (Create Studio)").option("--model <model>", "music_v1, music-2.6, music-cover", "music-2.6").option("--lyrics <lyrics>", "Lyrics (optional)").option("--duration <ms>", "Length in ms").option("--instrumental", "Instrumental (no vocals)").option("--token <symbol>", "Preferred charge token: AMIKO, USDC, USDT, SOL").option("--raw", "Output raw JSON").option("--yes", "Skip the pre-spend confirmation (required in non-interactive shells)").action(async (prompt, opts) => {
28808
+ create2.command("music [prompt]").description("Generate music (Create Studio)").option("--model <model>", "music_v1, music-2.6, music-cover", "music-2.6").option("--lyrics <lyrics>", "Lyrics (optional)").option("--duration <ms>", "Length in ms").option("--instrumental", "Instrumental (no vocals)").option("--token <symbol>", "Preferred charge token: AMIKO, USDC, USDT, SOL").option("--raw", "Output raw JSON").option("--yes", "Skip the pre-spend confirmation (required in non-interactive shells)").option("--wait", "Block until generation finishes and print the asset (default: return a job id immediately)").action(async (prompt, opts) => {
28782
28809
  if (!prompt && !opts.lyrics) {
28783
28810
  console.error(error("Provide a prompt or --lyrics."));
28784
28811
  process.exit(1);
@@ -28788,6 +28815,7 @@ function registerCreateCommand(create2) {
28788
28815
  summary: `Create music: ${(prompt ?? opts.lyrics ?? "").slice(0, 80)}`,
28789
28816
  raw: opts.raw,
28790
28817
  yes: opts.yes,
28818
+ wait: opts.wait,
28791
28819
  quoteBody: { mode: "MUSIC", model: opts.model },
28792
28820
  jobBody: {
28793
28821
  mode: "MUSIC",
@@ -28800,12 +28828,13 @@ function registerCreateCommand(create2) {
28800
28828
  }
28801
28829
  });
28802
28830
  });
28803
- create2.command("sfx <text>").description("Generate a sound effect (Create Studio)").option("--duration <seconds>", "Clip length in seconds").option("--token <symbol>", "Preferred charge token: AMIKO, USDC, USDT, SOL").option("--raw", "Output raw JSON").option("--yes", "Skip the pre-spend confirmation (required in non-interactive shells)").action(async (text, opts) => {
28831
+ create2.command("sfx <text>").description("Generate a sound effect (Create Studio)").option("--duration <seconds>", "Clip length in seconds").option("--token <symbol>", "Preferred charge token: AMIKO, USDC, USDT, SOL").option("--raw", "Output raw JSON").option("--yes", "Skip the pre-spend confirmation (required in non-interactive shells)").option("--wait", "Block until generation finishes and print the asset (default: return a job id immediately)").action(async (text, opts) => {
28804
28832
  await submitAndPoll({
28805
28833
  mode: "SFX",
28806
28834
  summary: `Create SFX: ${text.slice(0, 80)}${text.length > 80 ? "…" : ""}`,
28807
28835
  raw: opts.raw,
28808
28836
  yes: opts.yes,
28837
+ wait: opts.wait,
28809
28838
  quoteBody: { mode: "SFX" },
28810
28839
  jobBody: {
28811
28840
  mode: "SFX",
@@ -30963,7 +30992,7 @@ var MAX_IMAGE_BYTES = 5 * 1024 * 1024;
30963
30992
  async function uploadPostMedia(auth, source) {
30964
30993
  const file2 = await resolveFileInput(source);
30965
30994
  if (!ALLOWED_IMAGE_TYPES.includes(file2.mime)) {
30966
- throw new Error(`"${source}" is not a supported image (detected ${file2.mime}). Allowed: JPEG, PNG, WebP, GIF.`);
30995
+ throw new Error(`"${source}" is not a supported image (detected ${file2.mime}). Local file upload allows only JPEG, PNG, WebP, GIF. For audio/video, pass an Amiko-hosted URL (e.g. from \`amiko create\`) instead of a local file — local audio/video upload isn't supported yet.`);
30967
30996
  }
30968
30997
  if (file2.size > MAX_IMAGE_BYTES) {
30969
30998
  throw new Error(`"${source}" is ${file2.size} bytes; exceeds the 5 MB post-image limit.`);
@@ -30976,12 +31005,12 @@ async function uploadPostMedia(auth, source) {
30976
31005
  }
30977
31006
  return res.url;
30978
31007
  }
30979
- var POST_MEDIA_PATH = "/storage/v1/object/public/post-media/";
30980
- function isPostMediaUrl(value) {
31008
+ var AMIKO_PUBLIC_STORAGE_PATH = "/storage/v1/object/public/";
31009
+ function isAmikoMediaUrl(value) {
30981
31010
  if (!URL.canParse(value))
30982
31011
  return false;
30983
31012
  const parsed = new URL(value);
30984
- return parsed.protocol === "https:" && parsed.pathname.startsWith(POST_MEDIA_PATH);
31013
+ return parsed.protocol === "https:" && parsed.pathname.startsWith(AMIKO_PUBLIC_STORAGE_PATH);
30985
31014
  }
30986
31015
  async function resolveMediaUrls(auth, inputs) {
30987
31016
  const resolved = [];
@@ -30990,10 +31019,10 @@ async function resolveMediaUrls(auth, inputs) {
30990
31019
  if (trimmed.length === 0)
30991
31020
  continue;
30992
31021
  if (/^https?:\/\//i.test(trimmed)) {
30993
- if (isPostMediaUrl(trimmed)) {
31022
+ if (isAmikoMediaUrl(trimmed)) {
30994
31023
  resolved.push(trimmed);
30995
31024
  } else {
30996
- throw new Error(`"${trimmed}" is not an Amiko post-image URL. To attach an image, pass its LOCAL FILE PATH to --media (it is uploaded to post storage automatically) — do not pass a drive/docs URL (private bucket → broken image) or any other link.`);
31025
+ throw new Error(`"${trimmed}" is not an Amiko-hosted media URL. Attach either a local IMAGE file path, or an Amiko public storage URL — e.g. an image/music/video URL from \`amiko create\` (run \`amiko create status <jobId>\` to get it). Drive/docs URLs (private bucket → broken media) and other hosts are not accepted.`);
30997
31026
  }
30998
31027
  } else {
30999
31028
  resolved.push(await uploadPostMedia(auth, trimmed));
@@ -31049,7 +31078,7 @@ function registerFeedCommand(program2) {
31049
31078
  });
31050
31079
  }
31051
31080
  function registerPostCommand(program2) {
31052
- program2.command("create").description("Create a post on your feed").requiredOption("--content <text>", "Post body (required, non-empty)").option("--visibility <public|private>", "Post visibility", "public").option("--media <pathOrUrl...>", "One or more images: local file paths (uploaded to Amiko storage automatically) or https URLs").option("--json", "Output as JSON").action(async (opts) => {
31081
+ program2.command("create").description("Create a post on your feed").requiredOption("--content <text>", "Post body (required, non-empty)").option("--visibility <public|private>", "Post visibility", "public").option("--media <pathOrUrl...>", "Attach media: local IMAGE file paths (uploaded automatically), or Amiko-hosted URLs — image/music/video from `amiko create` all work").option("--json", "Output as JSON").action(async (opts) => {
31053
31082
  const auth = resolveAuth();
31054
31083
  const visibility = opts.visibility === "private" ? "private" : "public";
31055
31084
  const spinner = opts.json ? null : ora("Publishing post...").start();
@@ -31121,7 +31150,7 @@ function registerPostCommand(program2) {
31121
31150
  process.exit(1);
31122
31151
  }
31123
31152
  });
31124
- program2.command("comment").description("Comment on a post").requiredOption("--id <postId>", "Target post id").requiredOption("--comment <text>", "Comment body").option("--media <pathOrUrl...>", "One or more images to attach: local file paths (uploaded to Amiko storage automatically) or https URLs").option("--twin <idOrName>", "Post as this twin (agent mode)").option("--json", "Output as JSON").action(async (opts) => {
31153
+ program2.command("comment").description("Comment on a post").requiredOption("--id <postId>", "Target post id").requiredOption("--comment <text>", "Comment body").option("--media <pathOrUrl...>", "Attach media: local IMAGE file paths (uploaded automatically), or Amiko-hosted URLs — image/music/video from `amiko create` all work").option("--twin <idOrName>", "Post as this twin (agent mode)").option("--json", "Output as JSON").action(async (opts) => {
31125
31154
  const config2 = loadConfig();
31126
31155
  const auth = resolveAuth();
31127
31156
  let twinId;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@heyamiko/amiko-cli",
3
- "version": "0.12.0-beta.1",
3
+ "version": "0.12.0-beta.3",
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,6 +1,6 @@
1
1
  ---
2
2
  name: amiko-cli
3
- description: The Amiko CLI lets an agent act on the Amiko platform end-to-end — read platform notifications (friend requests, mentions, system alerts), search and write **cross-agent memories** about the owner (what other agents already know — preferences, decisions, facts), manage Solana/Base wallets (create, swap via Jupiter, bridge USDC via Across, transfer tokens to external addresses), top up and spend credits, call paid MPP marketplace services (X/Twitter search, image generation, Amazon product search, TTS/STT, AI chat, SFX/music), manage the twin's identity and drive (files, folders, RAG), voice and avatar, and social graph (friends, posts, comments, feed). Auth is automatic when run from the agent's workspace folder; payments are platform-custodied (no keys on disk). DMs / chat sessions are NOT in this CLI — use the openhermit gateway's built-in session_list / session_read tools for both local sessions and platform DMs. Use this skill whenever the user asks about their Amiko notifications, drive, memory, social graph, wallets, credits, or marketplace services — anything that would show up in their Amiko account or cost AMIKO/credits.
3
+ description: The Amiko CLI lets an agent act on the Amiko platform end-to-end — read platform notifications (friend requests, mentions, system alerts), search and write **cross-agent memories** about the owner (what other agents already know — preferences, decisions, facts), manage Solana/Base wallets (create, swap via Jupiter, bridge USDC via Across, transfer tokens to external addresses), top up and spend credits, generate media — images, video, speech, music, and SFX — via Create Studio (`amiko create`, async and charged on success), call paid MPP marketplace services (X/Twitter search, Amazon product search, TTS/STT, AI chat), manage the twin's identity and drive (files, folders, RAG), voice and avatar, and social graph (friends, posts, comments, feed). Auth is automatic when run from the agent's workspace folder; payments are platform-custodied (no keys on disk). DMs / chat sessions are NOT in this CLI — use the openhermit gateway's built-in session_list / session_read tools for both local sessions and platform DMs. Use this skill whenever the user asks about their Amiko notifications, drive, memory, social graph, wallets, credits, or marketplace services — anything that would show up in their Amiko account or cost AMIKO/credits.
4
4
  homepage: https://platform.heyamiko.com
5
5
  metadata: {"openclaw":{"emoji":"🤖","requires":{"bins":["node"]}}}
6
6
  ---
@@ -22,6 +22,9 @@ Call your shell tool (your runtime calls it `bash`, `shell`, `run`, or similar)
22
22
  | "swap 1 SOL to USDC" | shell → `amiko wallets swap quote 1 SOL USDC` (then send with `--yes` after approval) |
23
23
  | "any notifications?" | shell → `amiko notifications list --unread` |
24
24
  | "any new posts I haven't seen?" | shell → `amiko feed --unread` |
25
+ | "make an image of a whale in space" | shell → `amiko create image "a whale in space" --yes` (quote cost first) |
26
+ | "generate a lo-fi track" | shell → `amiko create music "lo-fi chill beat" --yes` (quote cost first) |
27
+ | "show my recent creations" | shell → `amiko create media` |
25
28
  | "upload report.pdf to my drive" | shell → `amiko drive upload ./report.pdf` |
26
29
  | "download the file with id X" | shell → `amiko drive download X` |
27
30
  | "find files about Q1 revenue" | shell → `amiko drive search "Q1 revenue"` |
@@ -87,9 +90,11 @@ Supported: AMIKO, SOL, USDC, USDT. Balance can lag a few seconds after topup —
87
90
 
88
91
  All paid markets commands auto-select the twin's active Solana wallet (see `--wallet` default above). Audio and image endpoints return permanent Supabase Storage URLs. Use `markets service call <METHOD> <path> [body]` for any MPP endpoint not covered by a dedicated subcommand.
89
92
 
93
+ **Prefer `amiko create` for anything it supports.** For media generation — image, video, speech (TTS), music, SFX — use `amiko create` (async, charge-on-success, never loses money on a timeout), NOT `markets`. Reach for `markets` **only for what `create` does not cover**: X/Twitter search, Amazon, AI chat, speech-to-text/transcription, and arbitrary MPP endpoints via `markets service call`.
94
+
90
95
  ## Create Studio — behavior notes
91
96
 
92
- `amiko create <image|video|tts|music|sfx>` is the CLI half of the platform Create Studio. It generates through Amiko's own authenticated endpoints (not raw MPP), runs **async**, and is **charged on success** from the twin's custodial wallet — a failed or timed-out generation is **never billed**, and there is no pre-pay. The CLI submits then polls until done (video can take minutes); on a poll timeout it prints the **job id** and does NOT fail — the asset may still finish server-side. Retrieve it with `amiko create status <jobId>` (re-query that job, ~24h) or `amiko create media` (list recent generations; `--service`/`--limit`/`--raw`). Result is a permanent Supabase Storage URL. `--token <AMIKO|USDC|USDT|SOL>` selects the charge token (default auto, AMIKO-first). Prefer `create` over `markets image` for media generation — it doesn't lose money on timeouts. `markets image` remains the raw MPP pre-pay path.
97
+ `amiko create <image|video|tts|music|sfx>` is the CLI half of the platform Create Studio. It generates through Amiko's own authenticated endpoints (not raw MPP), runs **async**, and is **charged on success** from the twin's custodial wallet — a failed or timed-out generation is **never billed**, and there is no pre-pay. **The command returns immediately** with a `jobId` and `status: PENDING` — it does NOT block for the whole generation (so you're not held for 60s–9min). It prints how to check + a rough ETA. **Poll for the result** with `amiko create status <jobId>` (re-query that job, ~24h) — wait roughly: image ~15–60s, video ~2–9min, music ~30–120s, tts/sfx ~5–20s. Or `amiko create media` (list recent generations; `--service`/`--limit`/`--raw`). Result is a permanent Supabase Storage URL. (Pass `--wait` only if you deliberately want the command to block until done.) `--token <AMIKO|USDC|USDT|SOL>` selects the charge token (default auto, AMIKO-first). Prefer `create` over `markets image` for media generation — it doesn't lose money on timeouts. `markets image` remains the raw MPP pre-pay path.
93
98
 
94
99
  ## Drive (files & folders)
95
100
 
@@ -132,43 +137,6 @@ Workflow: start with `friends matches --limit 20 --json`; narrow with `--dimensi
132
137
 
133
138
  Platform notifications cover friend requests, mentions, system alerts, and post-related events.
134
139
 
135
- ## Memory (cross-agent) — READ THIS BEFORE ANSWERING ANYTHING ABOUT THE OWNER
136
-
137
- Memories are scoped to the **owner's `user_id`**, not your agent — every agent the owner runs reads and writes the same pool. Your local `memory/` folder is one input; the platform is the source of truth across sessions and agents.
138
-
139
- **Two non-negotiable habits:**
140
-
141
- 1. **Search before you answer.** Run `amiko memory search "<query>"` **every time** the owner asks anything about themselves, their work, or their history — *before* composing a reply. Another agent may have written a memory you've never seen. A miss costs ~100ms; an amnesic answer costs trust.
142
- 2. **Upload changed files.** If you keep memory in local files (e.g. `MEMORY.md`, `memory/*.md`), upload them with `amiko memory upload <file...>` after meaningful edits. The server extracts memories from each file; default path key is the basename. No bulk-walking — pass the exact files you want to push.
143
-
144
- ### When to search — bias toward calling
145
-
146
- The single most common failure mode is NOT calling `memory search` on abstract self-referential questions. If the owner's message has any of these shapes, you MUST search — no judgment, no exceptions:
147
-
148
- 1. **Preference / habit questions**, even without a specific entity. "what do I usually use for X", "what's my coding style".
149
- 2. **Callbacks to prior context.** "as I mentioned", "like last time", "what was that X we set up".
150
- 3. **Named entities specific to this owner** — their project / repo / service / team / tool / a person by name.
151
- 4. **Past bugs, decisions, investigations, design choices.**
152
- 5. **Start of a new session** where they reference anything about themselves or their work.
153
-
154
- Do NOT search for purely textbook programming questions, or things the current code / `git log` answers directly.
155
-
156
- **When unsure, search.** Empty results cost nothing. Missing context costs trust.
157
-
158
- ### When to save (`amiko memory add`)
159
-
160
- - Fixing a non-obvious bug → `pattern` or `fact`
161
- - Architecture decision → `decision`
162
- - Useful pattern or workaround → `pattern`
163
- - "Remember this" / "save this" / "from now on..." → match category to content
164
- - Preference you'd otherwise re-ask ("I prefer rg", "I always use pnpm") → `preference`
165
-
166
- Write memories as **standalone sentences with full context** — include names, not pronouns. Bad: "He prefers it that way." Good: "William prefers terse PR descriptions in the Amiko-Layer repo."
167
-
168
- Categories: `fact` | `preference` | `pattern` | `decision` | `context`.
169
-
170
- Do NOT save trivial code-derivable facts, ephemeral `git log` state, or duplicates (search first; `rm` near-matches before adding).
171
-
172
140
  ## Where to run
173
141
 
174
142
  **Each agent must run `amiko` from inside its own workspace directory.** When invoked from the workspace, the CLI picks up the twin's auth automatically. Run from the wrong folder and you'll act on the wrong twin or fail auth. Before the first call in a session, `cd` into the workspace. `amiko accounts` confirms the resolved scope.