Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Youdao Notes Export

A portable Hermes skill + script package for exporting Youdao Cloud Notes into local files, metadata, ledgers, progress records, and audit reports.

This package focuses on Youdao Cloud Notes → local export artifacts. It does not write to gbrain or any downstream knowledge base by itself.

What it does

  • Inventory Youdao Cloud Notes without reading note bodies or mutating cloud state.
  • Read normal notes through the verified youdaonote CLI.
  • Upgrade legacy normal .note items through the verified visible Playwright workflow.
  • Handle readable-empty notes correctly.
  • Classify sensitive, attachment, media, and source-corrupt notes.
  • Reconcile old/new fileIds after legacy note upgrade.
  • Delete only verified old originals/duplicate copies to the Youdao recycle bin.
  • Clean converted suffixes such as X(1).note when safe.
  • Run in fixed groups with durable ledgers, progress.json, stdout heartbeat, resumable execution, and final audit.

Dependency model

This skill is designed to be easy for an AI agent or operator to install and verify, but it does not automatically install dependencies.

The skill package provides scripts, templates, and checks. The calling agent/operator is responsible for explicitly installing and configuring runtime dependencies after user approval.

The runner/checker must not silently:

  • install Python packages;
  • install browser binaries;
  • install CLIs;
  • modify shell startup files;
  • log in to Youdao automatically;
  • print credentials, cookies, tokens, or sensitive note bodies.

Requirements

Required runtime capabilities:

  • Python 3.9+.
  • Playwright installed in the selected Python interpreter.
  • Playwright Chromium installed for that same interpreter.
  • A configured youdaonote CLI.
  • Network access to Youdao Cloud Notes.
  • A writable local output directory.
  • For legacy .note upgrade: a visible persistent browser profile logged in to Youdao Cloud Notes.

Configuration precedence:

defaults < local config file < YOUDAO_EXPORT_* environment variables

Supported portable environment variables:

Setting Config key Environment variable Default
Python interpreter for runner/browser automation python_bin YOUDAO_EXPORT_PYTHON_BIN python3
Youdao CLI command/path cli_path YOUDAO_EXPORT_CLI youdaonote
Local run output root output_root YOUDAO_EXPORT_OUTPUT_ROOT ~/.youdao-notes-export/runs
Persistent browser profile directory browser_profile_dir YOUDAO_EXPORT_BROWSER_PROFILE_DIR ~/.youdao-notes-export/browser-profile
Group size batch_size YOUDAO_EXPORT_BATCH_SIZE 10
Inventory retry attempts inventory_max_attempts YOUDAO_EXPORT_INVENTORY_MAX_ATTEMPTS 3
Inventory retry delay seconds inventory_retry_delay_seconds YOUDAO_EXPORT_INVENTORY_RETRY_DELAY_SECONDS 30
Inventory heartbeat seconds inventory_heartbeat_seconds YOUDAO_EXPORT_INVENTORY_HEARTBEAT_SECONDS 600

Install dependencies explicitly

Choose one Python interpreter and use it consistently as python_bin / YOUDAO_EXPORT_PYTHON_BIN.

1. Install Python 3.9+

macOS with Homebrew:

brew install python
python3 --version

Ubuntu/Debian/WSL:

sudo apt-get update
sudo apt-get install -y python3 python3-pip python3-venv
python3 --version

If you use a virtual environment:

python3 -m venv .venv
. .venv/bin/activate
python --version

Then set python_bin to that interpreter, for example python, .venv/bin/python, or an absolute path.

2. Install Playwright and Chromium into the selected Python

Use the same interpreter that will be configured as python_bin:

<python_bin> -m pip install playwright
<python_bin> -m playwright install chromium

Examples:

python3 -m pip install playwright
python3 -m playwright install chromium

or, inside a venv:

. .venv/bin/activate
python -m pip install playwright
python -m playwright install chromium

3. Install and configure youdaonote CLI

Install the verified youdaonote CLI using its official/project-specific installation instructions. This README intentionally does not guess a package manager command because the CLI distribution source must be verified by the operator.

After installing it, make sure either:

  • youdaonote is available on PATH; or
  • cli_path in export_config.yaml points to the installed command; or
  • YOUDAO_EXPORT_CLI=/absolute/path/to/youdaonote is set for the current run.

Verify:

youdaonote check

If the command is not on PATH, use the explicit path:

/path/to/youdaonote check
export YOUDAO_EXPORT_CLI=/path/to/youdaonote

Do not print CLI config files, auth tokens, cookies, or credentials in logs.

Configure

Create a local config from the template. Keep local configuration outside the skill package:

mkdir -p ~/.config/youdao-notes-export
cp templates/export_config.example.yaml ~/.config/youdao-notes-export/export_config.yaml
export YOUDAO_EXPORT_CONFIG="$HOME/.config/youdao-notes-export/export_config.yaml"

Minimal example:

python_bin: python3
cli_path: youdaonote
output_root: ~/.youdao-notes-export/runs
browser_profile_dir: ~/.youdao-notes-export/browser-profile
batch_size: 10
allow_cloud_mutation: false
inventory_max_attempts: 3
inventory_retry_delay_seconds: 30
inventory_heartbeat_seconds: 600

Equivalent temporary environment override example:

export YOUDAO_EXPORT_PYTHON_BIN=python3
export YOUDAO_EXPORT_CLI=/path/to/youdaonote
export YOUDAO_EXPORT_OUTPUT_ROOT="$HOME/.youdao-notes-export/runs"
export YOUDAO_EXPORT_BROWSER_PROFILE_DIR="$HOME/.youdao-notes-export/browser-profile"
export YOUDAO_EXPORT_BATCH_SIZE=10

Prefer command-level temporary env/config for portability. Writing to shell startup files is a persistent local change and should require explicit user approval.

Check environment

Run the portable checker first:

python3 scripts/check_env.py --config "$YOUDAO_EXPORT_CONFIG"

The checker outputs JSON and only reports status/hints. It does not install anything.

Expected success shape:

{
  "dependency_model": "check_only_no_auto_install",
  "ok": true
}

Optional remote CLI check:

python3 scripts/check_env.py --config "$YOUDAO_EXPORT_CONFIG" --remote

Run the runner health check:

python3 scripts/youdao_export_all.py health --config "$YOUDAO_EXPORT_CONFIG" --dry-run
python3 scripts/youdao_export_all.py health --config "$YOUDAO_EXPORT_CONFIG"

--dry-run skips Playwright browser launch. Non-dry-run verifies that Playwright imports and Chromium launches in the configured python_bin interpreter.

Browser login

Legacy .note upgrade uses a visible persistent Playwright profile. The user must log in once:

python3 scripts/youdao_export_all.py browser-login --config "$YOUDAO_EXPORT_CONFIG"

A browser window opens. The user scans/finishes Youdao login. The profile is stored under browser_profile_dir and reused by later runs.

If a later run reaches a login page, the runner pauses the whole mutation phase as browser_login_required instead of failing every item.

Basic flow

Read-only discovery and planning:

python3 scripts/youdao_export_all.py inventory --config "$YOUDAO_EXPORT_CONFIG" --run-id <run_id>
python3 scripts/youdao_export_all.py plan-groups --config "$YOUDAO_EXPORT_CONFIG" --run-dir ~/.youdao-notes-export/runs/<run_id> --batch-size 10

Run groups through the heartbeat consumer wrapper. AI agents should not run long run-groups jobs directly unless they implement an equivalent stdout/progress consumer and real user-visible delivery sink. Printing to stdout is only local observation and must not be counted as user delivery for chat/agent platforms.

Read-only mode first when possible:

python3 scripts/agent_heartbeat_consumer_example.py \
  --sink-command '<host-agent-deliver-command>' \
  --delivery-log ~/.youdao-notes-export/runs/<run_id>/agent_delivery_log.jsonl \
  -- \
  python3 scripts/youdao_export_all.py run-groups \
    --config "$YOUDAO_EXPORT_CONFIG" \
    --run-dir ~/.youdao-notes-export/runs/<run_id>

Cloud mutation only after explicit user approval:

python3 scripts/agent_heartbeat_consumer_example.py \
  --sink-command '<host-agent-deliver-command>' \
  --delivery-log ~/.youdao-notes-export/runs/<run_id>/agent_delivery_log.jsonl \
  -- \
  python3 scripts/youdao_export_all.py run-groups \
    --config "$YOUDAO_EXPORT_CONFIG" \
    --run-dir ~/.youdao-notes-export/runs/<run_id> \
    --allow-cloud-mutation

Optional local progress inspection:

python3 scripts/youdao_progress_watch.py --run-dir ~/.youdao-notes-export/runs/<run_id>

Release/user-visible sync is not satisfied by log heartbeat alone. The calling agent must prove that heartbeat summaries reached the user channel, or record a delivery failure and fallback path.

Cleanup and audit:

python3 scripts/youdao_export_all.py cleanup-renames --config "$YOUDAO_EXPORT_CONFIG" --run-dir ~/.youdao-notes-export/runs/<run_id> --allow-cloud-mutation
python3 scripts/youdao_export_all.py audit --config "$YOUDAO_EXPORT_CONFIG" --run-dir ~/.youdao-notes-export/runs/<run_id>

Cloud mutation is disabled unless --allow-cloud-mutation is provided.

Agent setup guide

When an AI agent installs or uses this skill for a user, follow this sequence.

Agent responsibilities

  1. Read SKILL.md, this README.md, templates/export_config.example.yaml, and relevant scripts before running commands.
  2. Explain the dependency model to the user: the skill checks dependencies but does not auto-install them.
  3. Before any installation or persistent configuration change, ask for explicit approval and state:
    • what will be installed/changed;
    • why it is needed;
    • scope of the change;
    • risks/impact;
    • rollback/removal path;
    • verification command.
  4. Do not invent the youdaonote CLI installation source. If unknown, ask the user/operator for the official CLI source or an already installed path.
  5. Do not print credentials, cookies, token files, CLI config contents, or note bodies.
  6. For long exports, run run-groups through scripts/agent_heartbeat_consumer_example.py or an equivalent consumer implemented by the host agent. Record run_dir, process/session id, log path, progress.json, and agent_delivery_log.jsonl; relay compact heartbeat updates at the agreed cadence and verify user-visible delivery.

Agent setup recipe

Use this as the default machine-executable checklist:

# 1. Create local config
mkdir -p ~/.config/youdao-notes-export
cp templates/export_config.example.yaml ~/.config/youdao-notes-export/export_config.yaml
export YOUDAO_EXPORT_CONFIG="$HOME/.config/youdao-notes-export/export_config.yaml"

# 2. Check current dependency state; no installation is performed
python3 scripts/check_env.py --config "$YOUDAO_EXPORT_CONFIG"

# 3. If Playwright is missing, ask user approval, then install explicitly
<python_bin> -m pip install playwright
<python_bin> -m playwright install chromium

# 4. If youdaonote is missing, do NOT guess installation.
#    Ask for official install instructions or an installed command path, then configure one of:
#    - cli_path in export_config.yaml
#    - YOUDAO_EXPORT_CLI=/absolute/path/to/youdaonote

# 5. Verify after dependencies/config are ready
python3 scripts/check_env.py --config "$YOUDAO_EXPORT_CONFIG"
python3 scripts/youdao_export_all.py health --config "$YOUDAO_EXPORT_CONFIG" --dry-run
python3 scripts/youdao_export_all.py health --config "$YOUDAO_EXPORT_CONFIG"

# 6. Ask user to log in through visible browser profile if legacy upgrade is needed
python3 scripts/youdao_export_all.py browser-login --config "$YOUDAO_EXPORT_CONFIG"

# 7. Run read-only inventory and planning
python3 scripts/youdao_export_all.py inventory --config "$YOUDAO_EXPORT_CONFIG" --run-id <run_id>
python3 scripts/youdao_export_all.py plan-groups --config "$YOUDAO_EXPORT_CONFIG" --run-dir ~/.youdao-notes-export/runs/<run_id> --batch-size <N>

# 8. Run mutation only with explicit user approval, through the heartbeat consumer wrapper
python3 scripts/agent_heartbeat_consumer_example.py \
  --sink-command '<host-agent-deliver-command>' \
  --delivery-log ~/.youdao-notes-export/runs/<run_id>/agent_delivery_log.jsonl \
  -- \
  python3 scripts/youdao_export_all.py run-groups \
    --config "$YOUDAO_EXPORT_CONFIG" \
    --run-dir ~/.youdao-notes-export/runs/<run_id> \
    --allow-cloud-mutation

# 9. Verify user-visible heartbeat delivery, not only runner logs
python3 - <<'PY'
from pathlib import Path
log = Path('~/.youdao-notes-export/runs/<run_id>/agent_delivery_log.jsonl').expanduser()
if not log.exists() or log.stat().st_size == 0:
    raise SystemExit('missing agent-visible delivery log')
print(log.read_text(encoding='utf-8').splitlines()[-1])
PY

# 10. Final cleanup/audit
python3 scripts/youdao_export_all.py cleanup-renames --config "$YOUDAO_EXPORT_CONFIG" --run-dir ~/.youdao-notes-export/runs/<run_id> --allow-cloud-mutation
python3 scripts/youdao_export_all.py audit --config "$YOUDAO_EXPORT_CONFIG" --run-dir ~/.youdao-notes-export/runs/<run_id>

Agent heartbeat handling

The runner emits channel-neutral JSONL heartbeat lines such as:

{"type":"heartbeat","event":"item-complete","items_done":3,"items_total":11,"groups_done":1,"groups_total":4,"paused":false}

A calling agent should forward compact summaries to the current user channel. The provided wrapper already prints group/phase summaries and writes agent_delivery_log.jsonl:

python3 scripts/agent_heartbeat_consumer_example.py \
  --sink-command '<host-agent-deliver-command>' \
  --delivery-log ~/.youdao-notes-export/runs/<run_id>/agent_delivery_log.jsonl \
  -- \
  python3 scripts/youdao_export_all.py run-groups \
    --config "$YOUDAO_EXPORT_CONFIG" \
    --run-dir ~/.youdao-notes-export/runs/<run_id> \
    --allow-cloud-mutation

Example user-visible summary:

Youdao export <run_id>: group-complete, phase=run-groups, items=3/21, groups=1/7, counts={'upgrade_success': 3}

Forward immediately on:

  • login required;
  • service outage;
  • retry exhaustion;
  • unsafe/unknown mutation state;
  • process exit;
  • final completion.

A release or third-party-agent validation is incomplete unless agent_delivery_log.jsonl contains delivered=true entries from a real host delivery sink for at least inventory/plan completion when applicable, every group-complete, run-groups-complete, and audit-complete; or contains explicit delivered=false failure records plus a documented fallback action. Default stdout output records delivered=false unless --stdout-is-delivery is explicitly used for a local CLI user who is directly watching the terminal.

Do not hold the active chat turn open with long blocking waits just to watch progress. Prefer background process + short polls/watcher/cron/gateway delivery.

Browser workflow

The verified workflow is visible Playwright with a persistent profile. The user scans the Youdao QR login once, then the export runner reuses the profile.

For old-note upgrade, the runner first opens the standard note URL and verifies that the current page is the exact target old note. Only if target verification fails due to Youdao Web SPA redirect/jump does it retry with search/folder fallback. Upgrade is clicked only after target verification.

If converted copies such as X(1).note appear, they are not automatically treated as junk. The runner/audit must verify which copy is the readable converted note before rename/delete cleanup.

Output

A run writes to ~/.youdao-notes-export/runs/<run_id>/ with inventory, immutable groups, result ledgers, failure ledgers, progress, journals, screenshots when applicable, and final audit.

Typical layout:

~/.youdao-notes-export/runs/<run_id>/
  inventory.jsonl
  inventory_attempts.jsonl
  groups/group_001.json
  group_results/group_001.results.jsonl
  group_summaries/group_001.summary.json
  failures/
  actions/
  progress.json
  final_audit.json

Do not publish or share local run-output directories without reviewing them. They may contain fileIds, local paths, screenshots, metadata, and redacted-but-still-private operational context.

Safety

  • Default mode is read-only.
  • Any cloud mutation requires explicit --allow-cloud-mutation.
  • Never clear the Youdao recycle bin.
  • Delete/rename only after verification.
  • Do not print credentials or sensitive note bodies.
  • Pause on login loss, global service outage, retry exhaustion, or unknown post-mutation state.
  • Continue on ordinary item-level failures by recording them in failure/manual-review ledgers.
  • Treat local configs, browser profiles, ledgers, screenshots, and run outputs as private operational artifacts.

Agent supervisor contract

Host delivery sink discovery

The supervisor can discover a host delivery sink without hard-coding any platform. Discovery order:

  1. CLI: --sink-command <host-agent-deliver-command>
  2. Environment variables: YOUDAO_EXPORT_DELIVERY_COMMAND, AGENT_DELIVERY_COMMAND, HERMES_DELIVERY_COMMAND
  3. Config file: delivery_command: <host-agent-deliver-command>

Preflight before a notification-sensitive long run:

python3 scripts/agent_heartbeat_consumer_example.py \
  --config "$YOUDAO_EXPORT_CONFIG" \
  --check-delivery

For tests that claim user-visible notification, fail closed when no sink is available:

python3 scripts/agent_heartbeat_consumer_example.py \
  --config "$YOUDAO_EXPORT_CONFIG" \
  --delivery-required \
  --check-delivery

Equivalent config/env controls:

delivery_command: my-agent-deliver-current-user
delivery_required: true
export AGENT_DELIVERY_COMMAND='my-agent-deliver-current-user'
export AGENT_DELIVERY_REQUIRED=true

Host command contract:

  • stdin: one compact progress summary;
  • exit 0: the host platform/agent accepted/sent the user-visible message;
  • non-zero: delivery failed;
  • stderr/stdout: concise failure reason.

The public package only verifies this contract with fake/local sinks. Real platform delivery must be supplied and tested by the host agent.

Long runs require a host/calling-agent supervisor. This package is channel-neutral: it produces progress signals, but the host agent must actively observe and deliver them. Do not hard-code WeChat/Telegram/Slack/etc. into this skill.

Supported supervisor patterns:

  1. Foreground child stdout consumer

    The wrapper launches the runner and consumes JSONL heartbeat directly:

    python3 scripts/agent_heartbeat_consumer_example.py \
      --sink-command '<host-agent-deliver-command>' \
      --delivery-log ~/.youdao-notes-export/runs/<run_id>/agent_delivery_log.jsonl \
      -- \
      python3 scripts/youdao_export_all.py run-groups \
        --config "$YOUDAO_EXPORT_CONFIG" \
        --run-dir ~/.youdao-notes-export/runs/<run_id> \
        --allow-cloud-mutation
  2. Background process + progress polling

    If the host agent starts the runner in its own background-process system, stdout may not remain attached to the active chat turn. In that case, a supervisor must poll progress.json:

    python3 scripts/agent_heartbeat_consumer_example.py \
      --poll-progress ~/.youdao-notes-export/runs/<run_id>/progress.json \
      --poll-interval 30 \
      --sink-command '<host-agent-deliver-command>' \
      --delivery-log ~/.youdao-notes-export/runs/<run_id>/agent_delivery_log.jsonl
  3. External scheduler / watcher

    A cron job, gateway worker, or platform-native agent watcher may read progress.json, group result files, and audit output, then write equivalent delivery records. It must preserve the same semantics: delivered=true only for real host delivery; stdout/log observation is delivered=false.

Delivery log requirements:

  • delivered=true: the host sink accepted/sent the user-visible message.
  • delivered=false: stdout-only observation or host delivery failure.
  • delivery failures must include the error and fallback action.

This is the core release gate for agent-visible progress. Runner heartbeat and local logs are necessary, but not sufficient.

Local outbox sink for integration tests

For local/CI validation, this package includes a channel-neutral host sink example:

python3 scripts/local_outbox_delivery_sink.py --outbox /tmp/youdao-delivery-outbox.jsonl

Use it through discovery or --sink-command:

export AGENT_DELIVERY_COMMAND="python3 scripts/local_outbox_delivery_sink.py --outbox /tmp/youdao-delivery-outbox.jsonl"
python3 scripts/agent_heartbeat_consumer_example.py \
  --check-delivery

Then run a heartbeat/supervisor command normally. Successful records will have delivered=true, and the outbox file will contain the accepted summaries. This proves the skill can discover and call a host sink end-to-end. It does not prove delivery to WeChat/Telegram/Slack/etc.; real platform delivery still belongs to the host agent's own sink command.

Publishing hygiene

Do not publish this working directory directly if it contains local runtime artifacts.

A clean public package should include only source/docs/templates, for example:

SKILL.md
README.md
scripts/
templates/
references/
LICENSE
.gitignore
RELEASE_NOTES.md

Exclude:

runs/
**/__pycache__/
*.pyc
*.bak*
config.resolved.*
*.log
screenshots/
.browser-profile/

About

This SKILL can be utilized by the AI Agent to export the content from Youdao Cloud Notes to the local storage for the Agent's memory layer to incorporate.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages