🚀 @anna-ai/cli v0.1.23 — Local Executa Shims, Switchable Distribution Profiles & Tools-ACL Alignment

This release closes the last gap in the local bundled-executa dev loop: getting a distribution_type: local Executa to actually turn Running on an Agent under the same tool_id the app depends on.

Upgrade: npm i -g @anna-ai/cli@0.1.23 (or pnpm add -g @anna-ai/cli@0.1.23)


:sparkles: New executa install — local-dev launcher shims

A local Executa is never pushed via an install_plugin RPC, so the only way it goes live is the Agent’s Rediscover Local flow, which hunts for an executable named after the Executa’s [tool_id]. The problem is a three-way name mismatch baked into a typical project:

  • the placeholder in [executa.json] / [pyproject.toml] (e.g. tool-test-…-12345678),
  • the per-developer minted [tool_id] the server assigns at publish/push time (e.g. tool-hunter-…-4ny6cqap) — what the app’s required_executas actually references,
  • whatever shim name uv tool install happens to drop on PATH.

If the on-disk shim isn’t named with the minted [tool_id], Rediscover can’t find it (or registers it under the wrong key) and the app’s dependency never resolves.

anna-app executa install fixes this:

  • Resolves the minted [tool_id] from the [.anna/executa.json] identity cache (written by executa publish / apps push) or an explicit --tool-id.
  • Drops a small launcher shim named exactly [<tool_id>] into ~/.anna/executa/bin/.
  • The shim runs the same from-source command anna-app dev uses (uv run …, node …, go run ., or a bare binary), so a subsequent Rediscover Local spawns it and registers it under the minted id.
  • Flags: --tool-id, [–bin-dir], [–force], [–quiet], [–json].

:sparkles: apps push auto-installs local shims

When a bundled Executa’s active distribution profile is local, apps push now installs its local shim transitively and prints a one-line summary reminding you to click Rediscover Local. Shim-install failures are non-blocking — they won’t fail your push. Opt out with the new --no-install-local flag.

:sparkles: Switchable multi-profile distribution

The distribution block now accepts two shapes, so you can keep local and binary modes side by side and flip one field to choose what gets published:

"distribution": {
  "active": "binary",
  "profiles": {
    "local":  { "type": "local",  "executable_name": "…" },
    "binary": { "type": "binary", "binary_urls": { … } }
  }
}
  • Every profile is validated (a typo in an inactive profile is still caught).
  • The resolved distribution carries the active profile’s fields plus active/profiles for introspection — so all downstream publish/payload code stays profile-agnostic.
  • The historical flat single-mode form ({ "type": "binary", … }) keeps working unchanged. Setting both type and profiles is rejected.

:lady_beetle: Fixes & alignment

  • Tools ACL now matches matrix-nexus. Both the runtime host_api ACL (deriveAcl) and the validate static check now default tools.invoke / tools.list to all declared required/optional executas when host_api.tools is empty or omitted, mirroring Nexus’s _is_tool_allowed. Previously an app that declared bundled executas but left host_api.tools empty was wrongly told it couldn’t call tools.invoke.
  • Scaffold templates (go / node / python) drop the top-level manifest name. Plugin identity is now determined by the server-minted [tool_id] (taken from the on-disk shim name); server_info uses display_name instead. This removes the placeholder-vs-minted-id confusion at its source.
  • install-local-shims type fix — guarded a possibly-undefined installed[0] access surfaced under strict mode.

:gear: Under the hood

  • Pinned runtime bumped 0.2.0a6 → 0.2.0a7.
  • New unit tests for executa install, local-shim installation, and the publish primitives.

If you develop apps against local bundled executas, this is the one to grab — executa install plus the apps push auto-shim finally make Rediscover Local resolve dependencies on the first try.