Yinxiang / Evernote China → Markdown
Overview
This skill performs a fully client-free export of a Yinxiang Biji (印象笔记, China region) or Evernote account to clean standard Markdown. The pipeline is three stages:
印象笔记云端 ──(evernote-backup)──▶ 本地 .enex ──(Yarle)──▶ 纯 Markdown (.md)
Why these tools: Yarle only converts local .enex files — it cannot log into the cloud. evernote-backup is the only mature CLI that can authenticate to the China backend (--backend china) and pull notes down without the desktop client. Chaining them is the only no-client path to Markdown.
Run the bundled script scripts/run_export.sh to drive the whole pipeline. It checks/installs dependencies, runs each stage, and prints progress. Read the steps below so you understand what each stage does and can intervene when the user needs something non-default (e.g. login fails, partial export, custom output dir).
When NOT to use
- The user already has
.enexfiles on disk and only wants a format conversion — skip straight to Yarle (Stage 4); there's no cloud, no login, noevernote-backupneeded. - The notes live in a different app (Notion, 语雀, flomo, Apple Notes) — this pipeline is Evernote/印象笔记-specific.
- The user wants Obsidian-flavored output with wikilinks/Zettelkasten — this skill deliberately produces plain StandardMD; that's a different Yarle config than the one bundled here.
Credential handling (non-negotiable)
This skill logs into the user's personal note account, so credentials are the one thing you must get right:
- Never ask the user to paste their password into the chat. The password is typed directly into the terminal during
evernote-backup init-db, which prompts for it. - Never put the password in a command argument, a file, an env var, or a log line.
evernote-backupsupports--password, but using it would expose the password in shell history and process listings — do not use it. Let the interactive prompt collect it. - Don't echo or repeat any credential the user happens to mention. Refer to "your 印象笔记 password", never the value.
The bundled script follows all three: it calls init-db with no --password and never captures the prompt.
Key facts before you start
- China region uses
--backend china. A normal Evernote (international) account uses the default backend — ask the user which one they have if it's unclear. The yinxiang.com login = China backend. - Credentials are entered interactively during
init-db(see "Credential handling" above for the rules). syncis resumable. Large accounts take a while; if it's interrupted, re-runningevernote-backup synccontinues where it left off. The database file (en_backup.db) holds sync state — don't delete it between runs.- Output is plain Markdown by design. Yarle is configured with
outputFormat: StandardMDandisZettelkastenNeeded: false— no Obsidian double-links, no Zettelkasten naming. Tags become#tag, metadata goes into YAML frontmatter, attachments/images land in a_res/folder.
Default locations
Unless the user specifies otherwise, run everything inside a working directory and produce:
en_backup.db— evernote-backup sync database (sync state, keep it)enex_out/— exported.enexfiles (one per notebook)md_out/— final Markdown, mirroring the notebook structuremd_out/_res/— images and attachments
These are intentionally created under the current working directory rather than written straight into the user's Obsidian vault — the skill doesn't assume a library layout. After conversion, tell the user where md_out/ is and offer to move it into their vault.
Workflow
Drive the pipeline with the bundled script. It is idempotent and safe to re-run.
bash <skill-dir>/scripts/run_export.sh [WORK_DIR]
WORK_DIR defaults to the current directory. The script walks these stages and stops with a clear message if a stage needs your input:
Preflight (optional but recommended for non-technical users)
Before the real run, you can do a no-op environment check that touches nothing in the cloud and creates no files:
bash <skill-dir>/scripts/run_export.sh --check
It reports, in friendly Chinese, whether evernote-backup, Node/npm, and Yarle are ready, whether 印象笔记 is reachable, and how to install anything missing — exiting 0 if ready, 1 if a required tool is absent. Run this first when the user seems unsure about their setup or when a real run failed at Stage 0, so they get a clear picture before committing to a login + sync.
Stage 0 — Dependencies
- evernote-backup (Python): prefers
pipx install evernote-backupfor an isolated install. Ifpipxis missing, it installs into the active Python env withpip install evernote-backup. Verify withevernote-backup --version. - Yarle (Node): installed with
npm install -g yarle-evernote-to-md --ignore-scripts. The--ignore-scriptsmatters: Yarle bundles a native module (utimes) that needs Xcode Command Line Tools to compile and will fail the install otherwise — but that module only stamps file mtimes, so skipping it is harmless. Additionally, the installedyarlecommand has a shebang (env node --max-old-space-size=1024) that macOS can't execute, so the script invokes Yarle by calling its entry script directly:node <pkg>/dist/dropTheRope.js.
The script reports which tools were already present vs. freshly installed. Don't reinstall what's already there.
Stage 1 — Login (interactive)
evernote-backup init-db --backend china # omit --backend for international Evernote
This is interactive: the user types their yinxiang.com email/password and 2FA code directly into the terminal. It creates en_backup.db. If the DB already exists, this stage is skipped (re-running would error with "Database already exists"). To re-auth (e.g. token expired), the user runs evernote-backup reauth --backend china.
> The script pauses here and hands the terminal to the user for credential entry. It does not capture or echo the password.
Stage 2 — Sync from cloud
evernote-backup sync
Pulls all notes into en_backup.db. Progress (notes downloaded / total) prints to the terminal. Resumable — re-run if interrupted.
Stage 3 — Export to .enex
evernote-backup export ./enex_out/
Writes one .enex per notebook into enex_out/. This is equivalent to a client-side export.
Stage 4 — Convert to Markdown (Yarle)
The script generates yarle.config.json from assets/yarle.config.template.json, setting outputDir to md_out/ and enexSources to the export directory (enex_out/). The directory matters: Yarle 6.x treats a single .enex entry as one file, but anything else as a directory it scans (non-recursively) for *.enex — it does not expand glob patterns, and passing a multi-file list makes it readdir() the first entry. Since evernote-backup export writes .enex files flat into the export dir, handing Yarle that directory is exactly right. The script then runs:
node <yarle-pkg>/dist/dropTheRope.js --configFile <abs path to yarle.config.json>
Note the flag is --configFile (not --config), and Yarle is invoked via node rather than the broken yarle command. Result: clean .md files under md_out/notes/<notebook>/, attachments in a _res/ folder.
Stage 5 — Report
Print a summary: number of notebooks, .enex files, resulting .md files, total size, and the absolute path of md_out/. Offer to move/copy md_out/ into the user's target directory (e.g. their Obsidian vault).
Handling problems
- Login fails / "Two-factor required": 印象笔记中国区 often requires the 2FA SMS code. Re-run
init-dband have the user enter the code when prompted. If the account uses a phone number rather than email, that's the login identifier. Database already exists: expected on re-run — skipinit-db, go straight tosync.- Token expired between runs:
evernote-backup reauth --backend china, thensync. - Yarle produces Obsidian-style links: confirm the config has
isZettelkastenNeeded: falseandoutputFormat: "StandardMD". Regenerate the config from the template if it drifted. - Empty
md_out/: check thatenex_out/actually contains.enexfiles; if not,synclikely hasn't completed.
Resources
scripts/run_export.sh— orchestrates the full pipeline (dependency check/install → init-db → sync → export → Yarle → report) with progress output.assets/yarle.config.template.json— the canonical plain-Markdown Yarle config (StandardMD, no Zettelkasten). The script copies and path-fills this; edit the template if the user wants different conversion behavior.
Quick Reference
| 场景 | 命令 |
|---|---|
| 环境预检(不碰云端) | bash <skill-dir>/scripts/run_export.sh --check |
| 完整导出(中国区) | bash <skill-dir>/scripts/run_export.sh ~/导出目录 |
| 国际版 Evernote | BACKEND=international bash <skill-dir>/scripts/run_export.sh ~/导出目录 |
| 登录失效后重新授权 | evernote-backup reauth --backend china |
| 已有 .enex 只转格式 | 跳到 Stage 4:node <yarle-pkg>/dist/dropTheRope.js --configFile <config> |
- 唯一需要用户动手的是 Stage 1 登录(输账号密码+验证码);其余全自动。
- 中断可直接重跑同一命令——sync 断点续传、
en_backup.db已存在则跳过登录。 - 产出在
<WORK_DIR>/md_out/notes/<笔记本>/,附件在_res/。