Skip to content

Releases: rokbenko/quackd

v0.4.0 "adapters" — a brain for any small robot

Choose a tag to compare

@rokbenko rokbenko released this 02 Sep 17:49

quackd now drives four robots, and each one decides for itself what quackd may ask of it. Every robot is an adapter that hands over a manifest — this is what I am, this is what I can do — and the verbs the model is offered are built from that manifest and nothing else. The thesis does not change: the LLM picks verbs, the robot's own controllers move, quackd enforces the contract.

A Reachy Mini head on the wall spots the ball and judges the kick while a Microduck walks in and kicks it

A head that cannot walk and a duck that cannot judge its own kick, finishing one task under one contract. Simulator, scripted pilots, zero planner LLM calls.

Highlights

  • A verb that is not in the manifest does not exist — not in the registry, not in the MCP tool list, not in .duck validation, not in the prompt. Every robot is a RobotAdapter that returns a RobotManifest from connect(), and default_registry() is now just the Microduck's manifest compiled into verbs. Eight core verbs (observe, report_state, stop, say, move, go_to, search_scan, approach_and) exist only on a body whose manifest meets their requirements — a camera for observe, the twist intent and mobility for move — and declaring one the body cannot support makes the manifest refuse to build. get_frame, walk_to and walk are permanent aliases in one table, so every 0.3 .duck file still runs unchanged (ADR-0017, ADR-0018). Write one in a day: docs/adapters.md, docs/manifest-spec.md.
  • Four adapters, eleven backends, one flag. --robot <adapter>:<backend> on run, validate, serve-mcp, doctor and list-verbs: microduck (sim2d, mock, jsonrpc, websocket), reachy_mini (sim2d, mock, sdk), lerobot (mock, real), rosbridge (mock, ws) — one of the eleven is still a stub that raises with a link. Because the manifest decides the vocabulary, it is fifteen verbs on a Microduck, nine on a Reachy Mini head, seven on an SO-101 class arm with a camera and a pick policy, seven on a wheeled base with a camera topic: a head is never offered kick, an arm is never offered move, and move/go_to clamp to the speed limits the manifest names. --transport X still works as --robot microduck:X, warns once per process, and is gone in 0.5. Per-backend honesty table: docs/adapter-status.md.
  • A head and a duck finish one task together. reachy-spots-duck-kicks: a stationary Reachy Mini spots the ball and judges the kick from its own fresh frames, a Microduck approaches and kicks with its own legs, and the actor never gets to claim success — only the spotter's VERDICT, with the simulator's ground truth as a veto on top. Members are adapters sharing one arena and one lockstep clock, bids carry a capability term so a robot only bids for a role its manifest can fill, and a single auction fills every role. 10 of 10 seeds with the scripted pilots, zero planner LLM calls, every message in flock.jsonl. Simulator only, and the frame-of-reference limitation is written down rather than papered over (ADR-0020): docs/flock.md.
  • .duck v1 makes "wrong robot" a validation error instead of a runtime failure. requires, robots and flock.roles; v0 files parse unchanged and the bundled starters stay at duck: 0. quackd validate find-and-kick --robot reachy_mini:sim2d prints requires kick, but reachy-01 (reachy-mini) does not provide it and exits 1 before anything connects (ADR-0019): docs/duck-spec.md.
  • MCP fronts a fleet. serve-mcp --robots duck=microduck:sim2d,reachy=reachy_mini:mock exposes six robot_* tools (robot_list, robot_list_verbs, robot_run_verb, robot_observe, robot_say, robot_load_duckfile), each robot with its own executor, budget, heartbeat and contract, and robot_load_duckfile checks a contract's requires against that robot's manifest before adopting it. The eight duck_* tools remain as deprecated aliases of the default robot — 14 tools in all — and go away in 0.5. Every simulated robot over MCP gets its own world; a shared arena over MCP is future work: docs/mcp.md.
  • Also in 0.4: LAN discovery (quackd discover / quackd announce over zeroconf, an identity-only TXT record checked under 200 bytes per pair) and an MQTT flock bus behind the same two-method Bus protocol, both behind quackd[lan], both imported lazily, both library-only (ADR-0021, docs/lan.md); ADRs 0017 to 0023 and a page per adapter; goldens recorded from 0.3 that prove the seeded worlds, the starter ducks and the flock-kick conversation did not move; 360 tests, no network, no keys, and four seeded sweeps that CI holds at 10 of 10.

Nothing here has run on hardware, on any of the four bodies. What the demos and the sweeps use is microduck:sim2d, reachy_mini:sim2d and the mocks. The four SDK backends — microduck:jsonrpc, reachy_mini:sdk, lerobot:real, rosbridge:ws — are experimental in the strict sense: every upstream method, topic, socket and message name is read from pinned upstream source and marked VERIFIED or UNVERIFIED in one file per adapter, a test proves UNVERIFIED names are reachable only from those backends, and each has been exercised against fakes and nothing else. microduck:websocket is a stub that raises with links until upstream ships it. The Microduck arrives Christmas 2026; Reachy Mini hardware exists today and we do not have one. The LAN pieces are thinner still: zeroconf was exercised once for real between two processes on one machine, the MQTT bus once against a local amqtt broker on that same machine, and never between two machines — a flock across machines also needs a clock across machines, which does not exist yet, which is why there is no --bus flag.

uvx quackd run reachy-spots-duck-kicks --provider fake        # two bodies, one contract, no API key
uvx quackd run reachy-spotter --provider fake                 # a Reachy Mini head, no legs, same loop
uvx quackd list-adapters                                      # four adapters, eleven backends
uvx quackd validate find-and-kick --robot reachy_mini:sim2d   # "requires kick, but reachy-01 (reachy-mini) does not provide it"
claude mcp add quackd -- uvx quackd serve-mcp --robots duck=microduck:sim2d,reachy=reachy_mini:mock

quackd is an independent community project, not affiliated with or endorsed by Pollen Robotics, Hugging Face or Open Robotics.

Full changelog: v0.3.0...v0.4.0

v0.3.0 "flock" — ducks that cooperate (in the simulator)

Choose a tag to compare

@rokbenko rokbenko released this 31 Aug 10:46

Multiple simulated Microducks can now talk to each other and divide up a job, limited only by the skills each duck already has. The first choreography ships in this release: split the search, hold an auction, the closest duck kicks, and every message is on the record.

Highlights

  • Flock mode: add a flock: block to a .duck file or pass --flock N to put multiple ducks in one shared arena. They coordinate over an in-process message bus with typed messages (TASK, BID, CLAIM, ROLE, HB, RESULT), acting only through the verbs each duck already has, so the machinery is task-agnostic and the kick is simply the first choreography built on it (the target label is configurable). A deterministic Contract Net auction awards the claim from each duck's own camera distance estimate (20 % hysteresis, 6 s claim lease, one claimant lock, sim-time watchdog), and every message, bid, claim and role change lands in flock.jsonl. Guide: docs/flock.md, ADR-0015.
  • Multi-duck simulator: World(n_ducks=…) with per-duck noise streams, duck-duck collisions and the four Microduck colorways. A lockstep clock freezes the world while any pilot thinks, so single-duck runs stay bit-identical per seed (ADR-0016).
  • One LLM call at most: the planner may tune task parameters through a single forced tool call, clamped per field with a deterministic fallback. --provider fake computes the plan as a pure function. summary.json records llm_calls as proof.
  • Ground truth everywhere: the outcome is judged from sim telemetry, not a model claim, and duck-duck separation is watched from world ground truth while a claim is live.
  • Before release the flock diff went through an adversarial review (69 agents, 24 confirmed findings, all fixed): deadlock guards on the shared clock, per-duck budget enforcement, watchdog floors, cooldown gating at bid time and more. Details in the CHANGELOG.

Sim only, honestly labelled: one choreography ships today, and nothing multi-duck has run on hardware (Microducks ship Christmas 2026). More choreographies over the same bus and roles are the roadmap, not the release.

uvx quackd run flock-kick --provider fake --seed 3

Full changelog: v0.2.0...v0.3.0

quackd v0.2.0 — local and open-source LLMs can pilot the duck

Choose a tag to compare

@rokbenko rokbenko released this 30 Aug 10:41

Local and open source LLMs can now pilot the duck. Ollama, vLLM, llama.cpp, LM Studio, or any OpenAI compatible server. No API key.

uvx --from "quackd[openai]" quackd run find-and-kick --provider ollama --model qwen3:8b
uvx --from "quackd[openai]" quackd run find-and-kick --provider vllm --model Qwen/Qwen3-8B
uvx --from "quackd[openai]" quackd run find-and-kick --provider local --base-url http://gpu-box:8000/v1
uvx quackd run --goal "find the ball and kick it" --provider fake        # still no key, scripted pilot

Added

  • Local providers ollama, vllm, llamacpp, lmstudio, local (--base-url). Model discovery from /v1/models when --model is omitted, tool_choice=auto and no parallel_tool_calls field for picky servers (QUACKD_TOOL_CHOICE to override), vision opt-in with --vision, and a JSON text fallback that understands a tool call a small model wrote as plain text (marked text_fallback in the transcript). quackd doctor probes the four default local addresses. Guide: docs/local-llms.md. (ADR-0014)
  • quackd run --goal "...": a plain language goal instead of a .duck file. The scripted fake pilot picks a strategy from the goal's keywords.
  • --base-url, --api-key, --vision/--no-vision, --gif-size.
  • New README written for first time readers, a Microduck-like logo and a social preview card.

Changed

  • Providers are named by company, not model family ("OpenAI"). Hero GIF re-recorded at 320 px panes.

Fixed

  • Rich markup ate quackd[extra] in CLI error hints. mypy on Python 3.12 (numpy stubs).

Known limitations

  • Local model quality is unmeasured and we have not run a live local server ourselves yet. If you do, please share the transcript in Discussions.
  • The simulator is a cartoon and nothing has run on a real Microduck. The hero GIF is the scripted pilot.

Full changelog: CHANGELOG.md. quackd is an independent community project, not affiliated with or endorsed by Pollen Robotics or Hugging Face.

quackd v0.1.0 — Give your Microduck a brain

Choose a tag to compare

@rokbenko rokbenko released this 28 Aug 14:26

Give a small robot a brain. Tell the Microduck what you want in plain language; an LLM uses the robot's existing skills to do it. First release: sim-first, honest about hardware.

find-and-kick in the built-in simulator

uvx quackd run --goal "find the ball and kick it" --provider fake            # no key, built-in simulator
uvx --from "quackd[anthropic]" quackd run find-and-kick --provider anthropic  # with Claude
claude mcp add quackd -- uvx quackd serve-mcp --transport sim2d               # drive it from Claude Code

What's in 0.1.0

  • .duck task files — strict, validated frontmatter (allowlist, budgets, confirm gates, abort rules) + a Markdown body the model reads; five starters bundled; quackd run --goal "…" for ad-hoc goals.
  • 13 verbs — ten built-in (walk sit stand kick grab stand_up stop quack gaze get_frame) mapping 1:1 to the robot's shipped behaviours, three composite (search_scan walk_to approach_and), and a reserved interface for learned verbs.
  • Safety executor — allowlist, confirm gates, budgets, dry-run, machine-enforced abort_when, heartbeat, kill switch. Same layer for .duck runs and MCP sessions.
  • Built-in 2D simulator — deterministic under --seed, upstream-style deadman, top-down + duck-cam renders, GIF + transcript per run; find-and-kick succeeds on 10/10 seeds.
  • Providers — Claude (claude-opus-5), OpenAI, Gemini, Grok, and a scripted fake; vendor SDKs are optional extras.
  • MCP serverquackd serve-mcp for Claude Code / Claude Desktop, verified client config in docs/mcp.md.
  • Real robot — experimental jsonrpc transport with method names verified against upstream duck-ipc-proto v16; never run on hardware yet. WebSocket transport is a stub tracking upstream's draft.
  • quackd doctor, quackd validate, quackd list-verbs, quackd record; 124 tests, no network, no keys.

Known limitations

  • The simulator is a cartoon (it tests the agent loop, not physics); nothing has run on a real Microduck.
  • The hero GIF is the scripted pilot — a real-model recording is one command away once a key is available.
  • Default model IDs for OpenAI / Gemini / Grok are unverified; override with QUACKD_MODEL.

Full changelog: CHANGELOG.md. quackd is an independent community project, not affiliated with or endorsed by Pollen Robotics or Hugging Face.