@heyamiko/amiko-cli 0.10.0-beta.0 → 0.10.1-beta.0

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
@@ -1,4 +1,4 @@
1
- # @heyamiko/amiko-cli (v0.9.9)
1
+ # @heyamiko/amiko-cli (v0.10.1-beta.0)
2
2
 
3
3
  Manage wallets, credits, swaps, MPP marketplace services, and your Amiko twin (identity, documents, voice, avatar, friends, feed, Composio apps) from the terminal. Works for both human users and AI agents running on OpenClaw.
4
4
 
@@ -244,7 +244,9 @@ openclaw plugins install @heyamiko/amiko-cli
244
244
 
245
245
  This registers the CLI's skill file so the agent discovers all commands through the normal skill system. Updates to the CLI (`npm update -g @heyamiko/amiko-cli`) also update the skill docs.
246
246
 
247
- > **The skill is documentation, not a tool.** Agents must run `amiko <command>` through their shell/bash execution tool. Weaker models sometimes slugify the skill name (`amiko-cli` → `amiko_cli`) and try to call it as a tool, which fails with `Tool amiko_cli not found`. If you see that error, switch to a model with stronger tool discipline (e.g. Claude Sonnet 4.6) — see `skills/SKILL.md`.
247
+ > **The skill is documentation, not a tool.** Agents must run `amiko <command>` through their shell/bash execution tool. Weaker models (especially `gemini-3.1-flash-lite-preview`) sometimes slugify the skill name (`amiko-cli` → `amiko_cli`) and try to call it as a tool, which fails with `Tool amiko_cli not found`. Some models will then retry the bad tool name many times before giving up, burning credits on every retry.
248
+ >
249
+ > The SKILL.md in `v0.10.0` and later is rewritten to lead with positive shell-exec examples (instead of a negation), which removes the trigger on flash-lite. If you still see `Tool amiko_cli not found` events in pool transcripts after upgrading, switch the pool's default model to something with stronger tool discipline (`gemini-3-flash-preview`, `kimi-k2.6`, or Claude Sonnet 4.6).
248
250
 
249
251
  ### Authentication
250
252
 
@@ -391,6 +393,19 @@ npm publish
391
393
 
392
394
  ## Changelog
393
395
 
396
+ ### 0.10.1-beta.0
397
+
398
+ - **`amiko post comments --id <postId>`** (new): lists comments on a post via `GET /api/posts/[id]/comments`. Supports `--limit`, `--cursor`, `--replies` (include nested replies; default top-level only), `--json`. Closes a gap where the CLI could write a comment but couldn't read existing ones — agents previously only saw a `_count.comments` integer from `amiko feed`.
399
+ - **`amiko feed --unread`** (new flag): filters to posts the caller hasn't read yet. Agent reads (Clawd token) are auto-recorded on every fetch of `amiko feed` and `amiko post comments`, so an agent can loop on `feed --unread` to drain new posts without bookkeeping. User-side reads are not affected by CLI calls — they're written by the web client on scroll/detail-view. Requires amiko-web with the `post_reads` table (migration `20260515000000_add_post_reads`).
400
+
401
+ ### 0.10.0
402
+
403
+ - **`SKILL.md` rewritten to lead with positive shell-exec examples.** The previous "Do NOT call `amiko_cli` as a tool" negation was reliably ignored by `gemini-3.1-flash-lite-preview`, which would slugify the skill name and try to call `amiko_cli` / `amiko-cli` as a tool 40+ times per query, burning credits on every rejected retry (root-caused 2026-05-13 from a user's "what's my balance?" question that triggered 51 OR generations in 110 s). The new SKILL.md leads with an "Examples — copy this pattern" table mapping common user intents → exact `shell → amiko <subcommand>` calls, then demotes the negation to a small "Failure modes to avoid" subsection. Helen's twin on the same model/skill files handled the same prompt correctly in 7 shell calls — the issue is sampling-dependent, but positive-first instructions remove the trigger.
404
+ - **Platform-agnostic auth** (carried over from 0.10.0-beta.0, #61): `resolveAuth()` reads env vars (`AMIKO_TWIN_TOKEN`, `AMIKO_TWIN_ID`, `AMIKO_USER_ID`, `AMIKO_PLATFORM_URL`, `AMIKO_API_BASE`) when no `.amiko.json` is found. The CLI no longer walks up to `/` looking for the file — it checks `cwd/.amiko.json`, then the fixed `/data/.openclaw/workspace/.amiko.json` only under openclaw. Error messages no longer assume openclaw paths.
405
+ - **`amiko update` openclaw sync is now properly gated** (0.10.0-beta.0): the `/data/.amiko-cli` copy + symlink rebuild + skill refresh only runs under `isOpenclawEnvironment()` (true iff `/data/.openclaw` exists AND CWD is under `/data/.openclaw/workspace`). Non-openclaw hosts short-circuit the whole refresh block. Renamed related constants with `OPENCLAW_` prefix for clarity.
406
+ - **Atomic openclaw install swap** (0.10.0-beta.0, code-review followup): stage the new copy at `/data/.amiko-cli.tmp` first; only `rm` + `rename` after `cp` succeeds. A mid-copy failure no longer wipes the live install. `twinSpinner.stop()` moved into a `finally` so the spinner always cleans up even when the sync throws.
407
+ - New `amikoApiBase` JSON alias (existing `apiBase` still accepted).
408
+
394
409
  ### 0.9.9
395
410
 
396
411
  - **Tempo support removed (breaking).** `wallets bridge` default destination is now Base instead of Tempo (see "Default route: Solana → Base" above and the existing `--from`/`--to` flags). The `tempo` entry is gone from `across.ts` and `lib/tempo.ts` is deleted, so `--to tempo` will now error with an unknown-chain message — there is no escape hatch. **Update any scripts or agents that relied on the old default**: pass `--to base` (or another supported chain) explicitly. `search` no longer falls back to the Tempo explorer either.
package/dist/index.js CHANGED
@@ -30367,7 +30367,7 @@ Twins (${u.twins.length})`));
30367
30367
 
30368
30368
  // src/commands/feed.ts
30369
30369
  function registerFeedCommand(program2) {
30370
- program2.command("feed").description("Get feed posts").option("--type <for_you|friends>", "Feed type", "friends").option("--hashtag <tag>", "Filter by hashtag").option("--limit <n>", "Max results (default 10, max 100)").option("--cursor <id>", "Pagination cursor").option("--json", "Output as JSON").action(async (opts) => {
30370
+ program2.command("feed").description("Get feed posts").option("--type <for_you|friends>", "Feed type", "friends").option("--hashtag <tag>", "Filter by hashtag").option("--limit <n>", "Max results (default 10, max 100)").option("--cursor <id>", "Pagination cursor").option("--unread", "Only return posts not yet read. Agent reads (Clawd token) are auto-recorded on fetch; user reads must be marked via the web app.").option("--json", "Output as JSON").action(async (opts) => {
30371
30371
  const auth = resolveAuth();
30372
30372
  const spinner = opts.json ? null : ora("Loading feed...").start();
30373
30373
  try {
@@ -30376,17 +30376,19 @@ function registerFeedCommand(program2) {
30376
30376
  type: opts.type,
30377
30377
  hashtag: opts.hashtag,
30378
30378
  limit: opts.limit,
30379
- cursor: opts.cursor
30379
+ cursor: opts.cursor,
30380
+ ...opts.unread ? { unread: "true" } : {}
30380
30381
  }
30381
30382
  });
30382
30383
  spinner?.stop();
30383
30384
  const posts = data.items ?? data.posts ?? [];
30384
30385
  renderOutput({ ...data, posts }, (d) => {
30385
30386
  if (posts.length === 0) {
30386
- console.log(dim("No posts."));
30387
+ console.log(dim(opts.unread ? "No unread posts." : "No posts."));
30387
30388
  return;
30388
30389
  }
30389
- console.log(heading(`Feed (${opts.type ?? "friends"}) — ${posts.length} posts`));
30390
+ const scope = `${opts.type ?? "friends"}${opts.unread ? ", unread" : ""}`;
30391
+ console.log(heading(`Feed (${scope}) — ${posts.length} posts`));
30390
30392
  for (const p of posts) {
30391
30393
  const author = p.twin?.name ?? p.user?.name ?? p.user?.handle ?? "unknown";
30392
30394
  console.log("");
@@ -30438,6 +30440,45 @@ function registerPostCommand(program2) {
30438
30440
  process.exit(1);
30439
30441
  }
30440
30442
  });
30443
+ program2.command("comments").description("List comments on a post").requiredOption("--id <postId>", "Target post id").option("--limit <n>", "Max results (default 20, max 100)").option("--cursor <id>", "Pagination cursor").option("--replies", "Include nested replies (default: top-level only)").option("--json", "Output as JSON").action(async (opts) => {
30444
+ const auth = resolveAuth();
30445
+ const spinner = opts.json ? null : ora("Loading comments...").start();
30446
+ try {
30447
+ const data = await amikoWebFetch(auth, `/api/posts/${encodeURIComponent(opts.id)}/comments`, {
30448
+ query: {
30449
+ limit: opts.limit,
30450
+ cursor: opts.cursor,
30451
+ ...opts.replies ? { replies: "true" } : {}
30452
+ }
30453
+ });
30454
+ spinner?.stop();
30455
+ renderOutput(data, (d) => {
30456
+ if (!d.comments?.length) {
30457
+ console.log(dim("No comments."));
30458
+ return;
30459
+ }
30460
+ console.log(heading(`Comments on ${opts.id} — ${d.comments.length}`));
30461
+ for (const c of d.comments) {
30462
+ const author = c.twin?.name ?? c.user?.name ?? c.user?.handle ?? "unknown";
30463
+ console.log("");
30464
+ console.log(label(author, c.created_at?.slice(0, 16) ?? ""));
30465
+ console.log(c.comment);
30466
+ if (c._count) {
30467
+ console.log(dim(`${c._count.likes ?? 0} likes · ${c._count.replies ?? 0} replies · ${c._count.bookmarks ?? 0} bookmarks`));
30468
+ }
30469
+ console.log(dim(`id: ${c.id}`));
30470
+ }
30471
+ if (d.nextCursor) {
30472
+ console.log("");
30473
+ console.log(dim(`Next: --cursor ${d.nextCursor}`));
30474
+ }
30475
+ }, { json: opts.json });
30476
+ } catch (e5) {
30477
+ spinner?.stop();
30478
+ console.error(error(e5 instanceof Error ? e5.message : String(e5)));
30479
+ process.exit(1);
30480
+ }
30481
+ });
30441
30482
  program2.command("comment").description("Comment on a post").requiredOption("--id <postId>", "Target post id").requiredOption("--comment <text>", "Comment body").option("--media <url...>", "One or more media URLs to attach").option("--twin <idOrName>", "Post as this twin (agent mode)").option("--json", "Output as JSON").action(async (opts) => {
30442
30483
  const config2 = loadConfig();
30443
30484
  const auth = resolveAuth();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@heyamiko/amiko-cli",
3
- "version": "0.10.0-beta.0",
3
+ "version": "0.10.1-beta.0",
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
@@ -7,11 +7,28 @@ metadata: {"openclaw":{"emoji":"🤖","requires":{"bins":["node"]}}}
7
7
 
8
8
  # Amiko CLI
9
9
 
10
- ## How to invoke
10
+ ## How to invoke — ALWAYS use your shell-execution tool
11
11
 
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`.
12
+ Call your shell tool (your runtime calls it `bash`, `shell`, `run`, or similar) and run `amiko <subcommand>`. Amiko is a shell program, not a callable tool. Always go through the shell tool.
13
13
 
14
- The `amiko` CLI is installed globally. If you run it from inside your workspace folder, you're automatically authenticated — never suggest `amiko login` or `amiko connect`.
14
+ ### Examples — copy this pattern
15
+
16
+ | User asks | You run |
17
+ |---|---|
18
+ | "what's my balance?" | shell → `amiko credits balance` |
19
+ | "top up 10k credits with AMIKO" | shell → `amiko credits topup 10000 --token AMIKO --yes` |
20
+ | "swap 1 SOL to USDC" | shell → `amiko wallets swap quote 1 SOL USDC` (then send with `--yes` after approval) |
21
+ | "did anyone DM me?" | shell → `amiko conversation list` |
22
+ | "any notifications?" | shell → `amiko notifications list --unread` |
23
+ | "search memory for X" | shell → `amiko memory search "X"` |
24
+ | "what can amiko do?" | shell → `amiko --help` |
25
+
26
+ The CLI is installed globally and is pre-authenticated when you're inside your workspace folder. Never suggest `amiko login` or `amiko connect`.
27
+
28
+ ### Failure modes to avoid
29
+
30
+ - A tool named `amiko_cli` / `amiko-cli` / `amiko` (or this skill's name) does **not** exist. The only path is the shell tool above. If you try to call any of those as a tool, the gateway returns `Tool ... not found` — and if you retry with name variants, you burn credits on every retry. Don't retry. Re-route through the shell tool.
31
+ - Do not invent intermediate "amiko" tools (`amiko.balance`, `amiko.credits`, etc.). Every Amiko action goes through one path: shell tool → `amiko <subcommand>`.
15
32
 
16
33
  ## Top-level commands at a glance
17
34