npx quack "my async fn returns undefined" __ quack.
<(o )___ What exactly is undefined โ the variable, the property,
( ._> / or the thing you expected it to hold?
`---'
The duck never answers your bug. It only asks the questions that make you find it.
That's the whole product. Rubber-duck debugging works because explaining a problem forces you to confront your assumptions โ quack automates the duck, not the thinking. It is deliberately not an AI that solves your bug: no network, no API key, no account, no telemetry. Offline, instant, seedable.
Demo GIF (asciinema) goes here before launch.
| You do | The duck does |
|---|---|
quack |
Interactive session. Type your reasoning; get the next probing question. Exit with :q. |
quack "my test is flaky" |
One-shot: 1โ3 escalating questions about exactly that. |
cat error.log | quack |
Reads your logs, asks targeted questions. |
git diff | quack |
Explain your change to the duck before you commit it. |
Useful flags: --mode savage (see below), --json (machine-readable), --seed 42
(reproducible), --quiet (no duck, you monster), --help (in-character). The duck
always exits 0 โ it will never break your pipeline, only your confidence.
| Mode | Voice |
|---|---|
socratic (default) |
Patient, genuinely probing. |
senior |
"Have you read the docs? Okay. Have you actually read them?" |
savage |
"Have you reproduced it, or are you debugging a rumor?" |
zen |
"Describe the bug without blaming the code. What remains? ๐ฆ" |
chaos |
"What would this function do if it were a duck?" |
The quack-vscode extension puts a ๐ฆ in your status bar. It reads your selection and
the actual errors under your cursor, and asks about those. Same engine, same
questions, still no answers. (Marketplace + OpenVSX.)
The dataset is the product. Adding a question is a one-file PR to
packages/data/packs/ โ see CONTRIBUTING.md. CI enforces the one
sacred rule: every entry must be a question. Advice is rejected by a linter,
automatically, forever.
The engine is small on purpose: a documented contract
(specs/001-rubber-duck-debugger/contracts/core-api.md), a seeded PRNG (mulberry32),
and JSON packs. Reimplement it in anything.
| Language | Status |
|---|---|
| TypeScript (this repo) | โ reference |
| Python / Go / Rust / Emacs | yours? |
One question before every commit:
cp scripts/hooks/prepare-commit-msg .git/hooks/ && chmod +x .git/hooks/prepare-commit-msgTwo actions, everything else is automated by .github/workflows/release.yml:
# 1. bump the version in packages/cli/package.json (and any libs that changed)
# 2. tag and push
git tag v0.1.0 && git push origin v0.1.0The release workflow re-runs the full quality bar (build, types, lint, tests, and
the dataset never-answers guardrail), verifies the tag matches the CLI version,
publishes every public package whose version is new (pnpm -r publish skips
already-published versions and the private extension), creates a GitHub Release with
generated notes, and writes a per-package outcome summary. A safe rehearsal is one
click: Actions โ Release โ Run workflow โ dry-run: true.
Trust model: no npm token is stored anywhere in this repository. Publishing uses
npm trusted publishing (OIDC) โ register
each package once on npmjs.com (package โ Settings โ Trusted Publisher โ GitHub
Actions โ this repo + release.yml). Every published version carries a provenance
attestation; verify with npm audit signatures. If your org cannot use OIDC, the
fallback is an NPM_TOKEN repository secret plus NODE_AUTH_TOKEN on the publish
step โ still never a token in code.
quack is taken on npm. Available
fallbacks checked 2026-06-12: quackd, rubberduck-cli (and @quack/* scope
ownership must be confirmed). Update name in packages/cli/package.json and the
repository.url/homepage placeholders (OWNER) in all three public manifests โ
provenance requires the repository URL to match the publishing repo.
pnpm install && pnpm build && pnpm test # Node โฅ 18.17Monorepo: packages/core (pure engine) ยท packages/data (question packs) ยท
packages/cli ยท packages/vscode. One runtime dependency in the whole product
(picocolors). MIT.
The name
quackis a placeholder pending an npm availability check (fallbacks:quackd,ducksay,rubberduck-cli).