Duoduo Admin
Use this skill as the host-mode entrypoint for users who do not yet have a clear
mental model of duoduo.
Start With Discovery
- Confirm the daemon is up with
duoduo daemon status.
- Read
duoduo daemon config before making persistent changes. Treat that
output as the source of truth for paths and active settings.
- If the daemon is down, start there. If the machine is not onboarded yet,
explain that the user must finish
duoduo onboarding first.
- If the user says something is broken, first decide whether it is local
misconfiguration, operator error, channel/plugin setup error, or a likely
duoduo product bug.
Explain Duoduo In Host-Mode Terms
Keep the explanation concrete and filesystem-first.
stdio is the default direct operator surface after onboarding.
duoduo daemon ... manages the long-lived runtime process.
duoduo channel ... manages installable external channel plugins.
~/.config/duoduo/.env is the persistent host-mode settings file.
kernel/config/<kind>.md stores per-channel-kind defaults and kind prompts.
var/channels/<channel_id>/descriptor.md stores per-channel-instance
overrides and instance prompts.
- The host daemon is a detached background process. Updating package files alone
does not replace the running process.
- Re-opening
duoduo from the same real workspace path re-attaches the same
stdio session key instead of creating a brand-new conversation surface.
Read references/host-mode-map.md when the user
needs a fuller explanation of how these surfaces fit together.
Upgrade And Restart
"Is there an update?" → check both:
duoduo --version
npm view @openduo/duoduo version
Standard upgrade path (works for minor bumps within the same major):
npm install -g @openduo/duoduo@latest
duoduo daemon restart -r "upgraded @openduo/duoduo to <version>"
Newer builds collapse both steps into one command that also installs
into the prefix owning the running binary (which a bare
npm install -g may not), supplies the restart reason itself, and
health-checks the new daemon:
duoduo upgrade [version] [--wake <session-or-alias>]
Check availability from the CLI itself rather than from a version
number — duoduo --help lists --wake on the upgrade line exactly
when this behavior is present. Older builds have a duoduo upgrade
that takes only a version and does none of the above; on those, use
the two-command form.
The restart matters because the daemon is a detached background
process — installing a newer CLI package does not hot-swap it.
These skills are not part of the upgrade. They ship from the GitHub
repo, not the npm package, so both upgrade paths leave them untouched
and you are left operating a new CLI from old instructions. Whenever the
version changes, offer to refresh them:
npx -y skills add https://github.com/openduo/duoduo --global --all
Offer — do not do it silently. See
references/upgrade-playbook.md for the
non-interactive/SSH caveats.
The -r reason is delivered to every session woken after the restart.
Without it, a session whose turn the restart cut off has no way to know
why its conversation stopped mid-sentence, and will typically conclude a
person interrupted it. If a session was waiting on an answer, add
--wake <session-or-alias> (repeatable) — it will not resume on its own.
This holds even when the caller is a session inside the daemon being
restarted: the wake is carried by the restart itself, so it survives
the caller's own process dying with the old daemon.
Crossing major boundaries (including v0.5)
When the upgrade crosses a behavioral boundary (v0.5 added Feishu
main-session semantics and a new trust model for DMs), follow the
full playbook instead of the one-liner above:
Read references/upgrade-playbook.md.
To collect the facts the playbook branches on, run the preflight:
bash scripts/v05-upgrade-preflight.sh
The script outputs markdown listing the installed version, daemon
status, channel inventory, Feishu env keys, and descriptor shapes,
then recommends one of Branch B / C / D. It is an accelerator,
not a required path: if the script fails to run or the environment
is unusual, the playbook's Step 1 fallback enumerates every probe
the script performs as an individual command so the agent can
reproduce it by hand.
Automation surfaces you should know about
These surfaces matter when agents and automation talk to duoduo;
bare duoduo interactive use works without any of them.
duoduo onboard: dedicated subcommand that runs the wizard
and exits (never drops into the chat REPL). This is the correct
entrypoint for any automation or agent call. In non-TTY contexts
it reads its answers from env vars (at minimum
ALADUO_RUNTIME_MODE, ALADUO_CLAUDE_AUTH_SOURCE) instead of
prompting. If those are missing, it exits with code 2 and prints
the full env-var recipe on stderr — forward that recipe to the
caller rather than guessing.
DUODUO_NODE_BIN env: when set, the duoduo bash wrapper
uses that absolute path instead of resolving node via PATH.
Use this when a caller environment resets PATH (bash -lc in
agent spawn, GUI managers shipping a private Node runtime, etc.).
See openduo/duoduo#50 for the full rationale.
- User-visible drain errors: when the daemon's internal SDK
turn fails (most commonly: third-party compatible endpoints that
don't accept Claude Code's current wire schema), the user
sees a text reply prefixed with
[duoduo:drain-error] instead
of silence. The message carries the original error and suggests
DISABLE_ADAPTIVE=1 DISABLE_THINKING=1 DISABLE_INTERLEAVED_THINKING=1 MAX_THINKING_TOKENS=0
in ~/.config/duoduo/.env as the common workaround.
duoduo session archive <session_key>: archives every
durable artifact of one session in one call
(session dir, ingress snapshots, outbox records, channel
descriptor). "Archive" literally — nothing is deleted, everything
moves to var/<kind>-archive/ where the operator can mv it
back. Refuses when the target has a live actor; cancel it first
via /cancel. This is the right tool when the dashboard shows a
session that should no longer exist (e.g. after a channel reset)
or when you want a clean slate for one specific session without
touching the rest of the runtime. The
reset-feishu-session.sh script in duoduo-channel-admin drives
this CLI; read that script as a worked example if you need to
batch-archive per channel.
- Runtime selection: Claude, Codex, Grok, and Pi are peer
runtimes. Claude remains the default fallback, while
runtime: codex
can be selected per channel/job where Codex is available. Grok
(runtime: grok, ALADUO_DEFAULT_RUNTIME=grok) has no silent
Claude fallback — install grok, restart the daemon, run
grok login (login needs no restart). Pi ships inside duoduo (nothing to
install, always available) with the same no-silent-fallback posture:
every pi session needs a model pointer (provider/modelId via job
frontmatter, /model, or partition frontmatter) and fails actionably
without one. Use ALADUO_DEFAULT_RUNTIME=codex, =grok, or =pi
only for an intentional global default change.
- Stdio output buffering: the terminal UI buffers assistant text
more cleanly so status/tool rendering does not interleave as visibly
with assistant prose. Treat this as a UX fix, not a protocol change.
Find Problems And Escalate
When the user is reporting a bug or unexpected behavior:
- Reproduce or at least restate the exact symptom.
- Inspect the live state with the smallest useful commands, usually
duoduo daemon status, duoduo daemon config, duoduo daemon logs, and
any relevant duoduo channel ... status/logs.
- Separate local setup mistakes from probable product defects.
- If it looks like a duoduo bug or docs gap, prepare a public-safe issue
summary for
openduo/duoduo.
Read references/issue-reporting.md when the
user wants to file an issue or asks you to prepare one.
Route The Request
- Channel installation, channel lifecycle, Feishu setup, WeChat packaging, or
channel prompt/workspace changes:
read ../duoduo-channel-admin/SKILL.md
and let that workflow own the implementation.
- Runtime flags such as Codex, debug logs, telemetry, cadence, or daemon
diagnostics:
read ../duoduo-runtime-admin/SKILL.md
and let that workflow own the implementation.
- Confirmed bug report or docs gap that should be escalated publicly:
use references/issue-reporting.md.
- Mixed or vague requests:
explain the mechanism first, then move into the smallest concrete change.
Operating Rules
- Prefer live inspection over defaults. Use the actual daemon config, actual
files, and actual channel list before claiming how the system is set up.
- After editing
~/.config/duoduo/.env, tell the user to run
duoduo daemon restart -r "changed <setting>" unless they explicitly asked
for an edit-only change. Never suggest a bare restart — the reason is what
tells the interrupted sessions what happened to them.
- When the user asks to "understand duoduo", answer in terms of files,
commands, and lifecycle rather than abstract architecture jargon.
- Do not pretend a raw Git repository can be installed as a channel plugin.
Duoduo's channel installer accepts npm package specs (no flag) or local
.tgz tarballs (which require the explicit --from-path flag).
1---2name: duoduo-admin3description: Explain and manage a host-mode duoduo installation after onboarding. Use when the user asks how duoduo works, how stdio/daemon/channel/session fit together, where duoduo stores config and state, how to inspect current setup, how to upgrade duoduo itself, where something lives on disk (kernel_dir, runtime_dir, .env, descriptor.md), how to archive or recover a specific session (`duoduo session archive`, sessions-archive directory, restoring an archived session), or for broad 'configure duoduo' / 'fix my duoduo' requests that haven't narrowed to a specific channel or runtime setting yet. Also trigger for Chinese: 帮我理解 duoduo, duoduo 是怎么工作的, 看看我现在的 duoduo 配置, 帮我管理 duoduo, 升级 duoduo, 升级要注意什么, duoduo 哪个路径存什么, 归档 session, 删掉 session, 恢复归档 session.4---56# Duoduo Admin78Use this skill as the host-mode entrypoint for users who do not yet have a clear9mental model of duoduo.1011## Start With Discovery12131. Confirm the daemon is up with `duoduo daemon status`.142. Read `duoduo daemon config` before making persistent changes. Treat that15 output as the source of truth for paths and active settings.163. If the daemon is down, start there. If the machine is not onboarded yet,17 explain that the user must finish `duoduo` onboarding first.184. If the user says something is broken, first decide whether it is local19 misconfiguration, operator error, channel/plugin setup error, or a likely20 duoduo product bug.2122## Explain Duoduo In Host-Mode Terms2324Keep the explanation concrete and filesystem-first.2526- `stdio` is the default direct operator surface after onboarding.27- `duoduo daemon ...` manages the long-lived runtime process.28- `duoduo channel ...` manages installable external channel plugins.29- `~/.config/duoduo/.env` is the persistent host-mode settings file.30- `kernel/config/<kind>.md` stores per-channel-kind defaults and kind prompts.31- `var/channels/<channel_id>/descriptor.md` stores per-channel-instance32 overrides and instance prompts.33- The host daemon is a detached background process. Updating package files alone34 does not replace the running process.35- Re-opening `duoduo` from the same real workspace path re-attaches the same36 stdio session key instead of creating a brand-new conversation surface.3738Read [references/host-mode-map.md](references/host-mode-map.md) when the user39needs a fuller explanation of how these surfaces fit together.4041## Upgrade And Restart4243"Is there an update?" → check both:4445```bash46duoduo --version47npm view @openduo/duoduo version48```4950Standard upgrade path (works for minor bumps within the same major):5152```bash53npm install -g @openduo/duoduo@latest54duoduo daemon restart -r "upgraded @openduo/duoduo to <version>"55```5657Newer builds collapse both steps into one command that also installs58into the prefix owning the running binary (which a bare59`npm install -g` may not), supplies the restart reason itself, and60health-checks the new daemon:6162```bash63duoduo upgrade [version] [--wake <session-or-alias>]64```6566Check availability from the CLI itself rather than from a version67number — `duoduo --help` lists `--wake` on the upgrade line exactly68when this behavior is present. Older builds have a `duoduo upgrade`69that takes only a version and does none of the above; on those, use70the two-command form.7172The restart matters because the daemon is a detached background73process — installing a newer CLI package does not hot-swap it.7475**These skills are not part of the upgrade.** They ship from the GitHub76repo, not the npm package, so both upgrade paths leave them untouched77and you are left operating a new CLI from old instructions. Whenever the78version changes, offer to refresh them:7980```bash81npx -y skills add https://github.com/openduo/duoduo --global --all82```8384Offer — do not do it silently. See85[references/upgrade-playbook.md](references/upgrade-playbook.md) for the86non-interactive/SSH caveats.8788The `-r` reason is delivered to every session woken after the restart.89Without it, a session whose turn the restart cut off has no way to know90why its conversation stopped mid-sentence, and will typically conclude a91person interrupted it. If a session was waiting on an answer, add92`--wake <session-or-alias>` (repeatable) — it will not resume on its own.93This holds even when the caller is a session inside the daemon being94restarted: the wake is carried by the restart itself, so it survives95the caller's own process dying with the old daemon.9697### Crossing major boundaries (including v0.5)9899When the upgrade crosses a behavioral boundary (v0.5 added Feishu100main-session semantics and a new trust model for DMs), follow the101full playbook instead of the one-liner above:102103Read [references/upgrade-playbook.md](references/upgrade-playbook.md).104105To collect the facts the playbook branches on, run the preflight:106107```bash108bash scripts/v05-upgrade-preflight.sh109```110111The script outputs markdown listing the installed version, daemon112status, channel inventory, Feishu env keys, and descriptor shapes,113then recommends one of Branch B / C / D. It is an **accelerator,114not a required path**: if the script fails to run or the environment115is unusual, the playbook's Step 1 fallback enumerates every probe116the script performs as an individual command so the agent can117reproduce it by hand.118119## Automation surfaces you should know about120121These surfaces matter when agents and automation talk to duoduo;122bare `duoduo` interactive use works without any of them.123124- **`duoduo onboard`**: dedicated subcommand that runs the wizard125 and exits (never drops into the chat REPL). This is the correct126 entrypoint for any automation or agent call. In non-TTY contexts127 it reads its answers from env vars (at minimum128 `ALADUO_RUNTIME_MODE`, `ALADUO_CLAUDE_AUTH_SOURCE`) instead of129 prompting. If those are missing, it exits with code 2 and prints130 the full env-var recipe on stderr — forward that recipe to the131 caller rather than guessing.132- **`DUODUO_NODE_BIN` env**: when set, the `duoduo` bash wrapper133 uses that absolute path instead of resolving `node` via PATH.134 Use this when a caller environment resets PATH (`bash -lc` in135 agent spawn, GUI managers shipping a private Node runtime, etc.).136 See openduo/duoduo#50 for the full rationale.137- **User-visible drain errors**: when the daemon's internal SDK138 turn fails (most commonly: third-party compatible endpoints that139 don't accept Claude Code's current wire schema), the user140 sees a text reply prefixed with `[duoduo:drain-error]` instead141 of silence. The message carries the original error and suggests142 `DISABLE_ADAPTIVE=1 DISABLE_THINKING=1 DISABLE_INTERLEAVED_THINKING=1 MAX_THINKING_TOKENS=0`143 in `~/.config/duoduo/.env` as the common workaround.144- **`duoduo session archive <session_key>`**: archives every145 durable artifact of one session in one call146 (session dir, ingress snapshots, outbox records, channel147 descriptor). "Archive" literally — nothing is deleted, everything148 moves to `var/<kind>-archive/` where the operator can `mv` it149 back. Refuses when the target has a live actor; cancel it first150 via `/cancel`. This is the right tool when the dashboard shows a151 session that should no longer exist (e.g. after a channel reset)152 or when you want a clean slate for one specific session without153 touching the rest of the runtime. The154 `reset-feishu-session.sh` script in `duoduo-channel-admin` drives155 this CLI; read that script as a worked example if you need to156 batch-archive per channel.157- **Runtime selection**: Claude, Codex, Grok, and Pi are peer158 runtimes. Claude remains the default fallback, while `runtime: codex`159 can be selected per channel/job where Codex is available. Grok160 (`runtime: grok`, `ALADUO_DEFAULT_RUNTIME=grok`) has **no silent161 Claude fallback** — install `grok`, restart the daemon, run162 `grok login` (login needs no restart). Pi ships inside duoduo (nothing to163 install, always available) with the same no-silent-fallback posture:164 every pi session needs a model pointer (`provider/modelId` via job165 frontmatter, `/model`, or partition frontmatter) and fails actionably166 without one. Use `ALADUO_DEFAULT_RUNTIME=codex`, `=grok`, or `=pi`167 only for an intentional global default change.168- **Stdio output buffering**: the terminal UI buffers assistant text169 more cleanly so status/tool rendering does not interleave as visibly170 with assistant prose. Treat this as a UX fix, not a protocol change.171172## Find Problems And Escalate173174When the user is reporting a bug or unexpected behavior:1751761. Reproduce or at least restate the exact symptom.1772. Inspect the live state with the smallest useful commands, usually178 `duoduo daemon status`, `duoduo daemon config`, `duoduo daemon logs`, and179 any relevant `duoduo channel ... status/logs`.1803. Separate local setup mistakes from probable product defects.1814. If it looks like a duoduo bug or docs gap, prepare a public-safe issue182 summary for `openduo/duoduo`.183184Read [references/issue-reporting.md](references/issue-reporting.md) when the185user wants to file an issue or asks you to prepare one.186187## Route The Request188189- Channel installation, channel lifecycle, Feishu setup, WeChat packaging, or190 channel prompt/workspace changes:191 read [../duoduo-channel-admin/SKILL.md](../duoduo-channel-admin/SKILL.md)192 and let that workflow own the implementation.193- Runtime flags such as Codex, debug logs, telemetry, cadence, or daemon194 diagnostics:195 read [../duoduo-runtime-admin/SKILL.md](../duoduo-runtime-admin/SKILL.md)196 and let that workflow own the implementation.197- Confirmed bug report or docs gap that should be escalated publicly:198 use [references/issue-reporting.md](references/issue-reporting.md).199- Mixed or vague requests:200 explain the mechanism first, then move into the smallest concrete change.201202## Operating Rules203204- Prefer live inspection over defaults. Use the actual daemon config, actual205 files, and actual channel list before claiming how the system is set up.206- After editing `~/.config/duoduo/.env`, tell the user to run207 `duoduo daemon restart -r "changed <setting>"` unless they explicitly asked208 for an edit-only change. Never suggest a bare `restart` — the reason is what209 tells the interrupted sessions what happened to them.210- When the user asks to "understand duoduo", answer in terms of files,211 commands, and lifecycle rather than abstract architecture jargon.212- Do not pretend a raw Git repository can be installed as a channel plugin.213 Duoduo's channel installer accepts npm package specs (no flag) or local214 `.tgz` tarballs (which require the explicit `--from-path` flag).