Install
openclaw skills install @cpsean/yuque-docs-skillUse this skill when a user wants to create, update, delete, or list documents in a Yuque knowledge base, or manage Yuque repository table of contents. Use it for pushing local content to Yuque, syncing document changes, or inspecting what exists in a Yuque repo. Do not use it when the user wants general knowledge-base management unrelated to Yuque, or when they need to manage Yuque team members, permissions, or repository settings.
openclaw skills install @cpsean/yuque-docs-skillManage documents in a Yuque knowledge base through the OpenAPI. Owns create, read, update, delete of documents and TOC inspection.
This skill does NOT own:
requests and python-dotenv installed..env file in the project root (created via the setup flow below).If the user has not configured this skill yet (no .env file, or list returns a config error), follow this flow:
Ask for the knowledge base URL. Tell the user:
Please paste your Yuque knowledge base URL, for example:
https://xxx.yuque.com/group/bookYou can find it by opening your knowledge base in the browser and copying the address bar URL.
Ask for the API token. Tell the user:
Please paste your Yuque API token.
To create one: open Yuque -> click your avatar (top right) -> "Account Settings" -> "Tokens" -> "Create new token". Grant it read/write access to your target knowledge base.
Token page: https://www.yuque.com/settings/tokens
Run the setup command. The script auto-parses the URL and validates the connection:
python scripts/yuque_cli.py setup --url "<user_url>" --token "<user_token>"
.env is written, connection is verified, .gitignore is checked.--force to overwrite an existing .env.Confirm by running python scripts/yuque_cli.py list.
.env to git. The setup script checks .gitignore and warns if .env is not excluded..env.python scripts/yuque_cli.py list to confirm token and repo are valid.scripts/yuque_cli.py with the matching subcommand.list, get, or toc to confirm the operation succeeded.| Action | Command | Key flags |
|---|---|---|
| Setup | python scripts/yuque_cli.py setup --url URL --token TOKEN | --force, --env-path |
| List | python scripts/yuque_cli.py list | --offset, --limit |
| Get | python scripts/yuque_cli.py get <id_or_slug> | |
| Create | python scripts/yuque_cli.py create -t "Title" -b "Body" | -f FILE, --no-toc, --format, --slug |
| Update | python scripts/yuque_cli.py update <id_or_slug> -t "T" | -b, -f FILE, --format |
| Delete | python scripts/yuque_cli.py delete <id_or_slug> --confirm | --confirm required (not optional) |
| TOC | python scripts/yuque_cli.py toc | |
| Sync | python scripts/yuque_cli.py sync | --check, --root, --layout, --on-missing |
| Pull | python scripts/yuque_cli.py pull --slug <slug> | --all, --overwrite, --root, --layout |
| Status | python scripts/yuque_cli.py status | --root, --layout |
Global flags available on all commands: --json (machine-readable output), --dry-run (preview without executing).
Dry-run mode always outputs JSON regardless of the
--jsonflag. Use it to inspect the payload before committing.
Use sync for "push only what actually changed" instead of blind update. The script maintains .yuque-sync.json (auto-added to .gitignore) tracking each doc's local content hash and remote latest_version_id, so unchanged docs are skipped without any GET-detail call.
When the user runs sync/pull/status and no state file exists, the script auto-detects the local layout from .md files under --root (default cwd):
.md files at top level. Slug = file stem..md files under subdirectories. Slug = file stem (subdirs are organizational only; they do not create TOC groups).--- slug: xxx --- frontmatter at the top. Slug = frontmatter value..md files yet; suggest pull --all to seed locally.If layouts are mixed or partially-frontmatter, the script errors and asks the user to pass --layout flat|nested|frontmatter or normalize the directory.
In frontmatter layout, each .md file begins with a YAML block. Supported fields:
slug (required) — the Yuque document slug (URL identifier). Usually English kebab-case, e.g. create-draft-task.title (optional) — the document title pushed to Yuque. Useful when the file name or H1 should not be used as the title.Example:
---
slug: create-draft-task
title: 创建起草任务
---
# 创建起草任务
正文内容。
The YAML frontmatter is stripped before pushing to Yuque — it never appears in the rendered document body.
When sync pushes a document, the title sent to Yuque is resolved in this order:
title field (if present)# Heading) in the body.md extension)When the title falls back to the file name or slug (steps 3–4), sync --check / status lists these docs under a "Title fallback" section so you know to add an H1 or frontmatter title.
Use sync --force-title to always use the file name stem as the title, ignoring H1 and frontmatter title. This is useful when upstream-generated titles are unreliable.
During sync push, the following transformations are applied to the body before sending it to Yuque:
[text](file.md) links are converted to [text](slug) using the local slug map, so they resolve correctly on Yuque. External URLs (http://...), anchors (#section), and non-.md links are left untouched. Unresolved links are kept as-is and reported as warnings.**标签:**值 (bold-close marker directly followed by a non-space character) is rewritten to **标签:** 值, because Yuque's renderer requires a trailing space to recognize the bold-close marker. Already-correct **标签:** 值 is not affected.On pull, the reverse transformation is applied: slug links are converted back to local file-name links when a matching local file is known.
optional_properties=latest_version_id) — no per-doc GET.latest_version_id to the values stored in .yuque-sync.json.create for local files with no remote counterpart (auto-adds to TOC).update for local files whose body changed and remote did not.sync exits 2 when local files that were previously synced are now missing. This is not an error — it means the script needs an explicit choice from the user. The stdout block describes three options, each with the exact flag to re-run with:
--on-missing delete — delete on Yuque too--on-missing pull — restore locally from Yuque--on-missing forget — keep on Yuque, drop from local stateWhen you see exit code 2, show the printed block to the user (translated to their query language; see Language section), then re-invoke sync --on-missing <choice> once they pick.
If a doc was changed both locally and remotely (or remote moved while local stayed), sync lists it under "Conflicts" and skips it. Resolve manually:
pull --slug <slug> --overwrite — accept remote version locally.update <slug> -f path/to/file.md — overwrite remote with local version.After resolution, the next sync run will reconcile the state file.
The CLI emits English in fixed-format blocks for stability. When relaying CLI output to the user — especially the sync confirmation block, status sections, and error messages — translate the human-readable text into the user's query language. Keep the following literal and untranslated:
--on-missing delete, --layout flat)..env.setup with the correct URL..env is protected.--title, --body, --body-file, --slug, --format, --public must be given.--confirm.sync exit code 2: Not an error. Confirmation required for missing-local files. Show the block to the user, get their choice, re-run with --on-missing <choice>.--layout for them — ask which structure they intend.Do NOT guess doc IDs or slugs. If unknown, run list, toc, or status first to find the target.
scripts/yuque_cli.py — the CLI tool. Run it; do not read it unless debugging.scripts/yuque_cli.py --help and scripts/yuque_cli.py <cmd> --help for full flag details..env file holds credentials (never commit it).append_doc_to_toc. Use --no-toc only if you explicitly want an unlisted document.id parameter in get/update/delete can be either an integer doc ID or a string slug. Both work, but slugs are more readable.--body-file instead of --body for any non-trivial content to avoid shell quoting issues.--format markdown (the default) unless the user specifically needs Lake format.sync ignores remote drafts (body_draft). Change detection is based on latest_version_id (the last published version). If a teammate is editing in the Yuque web editor without publishing, that draft will be overwritten by sync update. If you suspect this, use pull --slug <slug> --overwrite to inspect remote first.sync will only delete remotely when the user explicitly passes --on-missing delete after seeing the confirmation block. Do not pass delete on the user's behalf without an unambiguous yes.