Yuque Lakebook Export Convert one or more Yuque files into local Markdown folders, with images and internal document links prepared for Obsidian. When to Use Use this skill when the user asks for: - Exporting one or more Yuque files - Converting a Yuque knowledge base into Markdown - Migrating Yuque content into Obsidian - Fixing Yuque export issues around images, cropped images, internal links, hierarchy, or tables Do not use Do not use this skill for: - Generic Markdown editing that does not involve Yuque or - Website scraping tasks - Export tasks that already come from a non-Yuque format I…

)\nTABLE_ROW_RE = re.compile(r'^\\s*\\|.*\\|\\s*

Yuque Lakebook Export Convert one or more Yuque files into local Markdown folders, with images and internal document links prepared for Obsidian. When to Use Use this skill when the user asks for: - Exporting one or more Yuque files - Converting a Yuque knowledge base into Markdown - Migrating Yuque content into Obsidian - Fixing Yuque export issues around images, cropped images, internal links, hierarchy, or tables Do not use Do not use this skill for: - Generic Markdown editing that does not involve Yuque or - Website scraping tasks - Export tasks that already come from a non-Yuque format I…

)\nLIST_RE = re.compile(r'^\\s*(?:[-+*]|\\d+\\.)\\s+')\nLAKE_DOCTYPE_RE = re.compile(r'^\\ufeff?(?:\u003c!doctype\\s+lake>\\s*)?', re.IGNORECASE)\n\n\ndef strip_lake_prefix_artifact(text):\n normalized = text.lstrip(\"\\ufeff\")\n normalized = LAKE_DOCTYPE_RE.sub(\"\", normalized, count=1)\n if not normalized[:4].lower() == \"lake\":\n return normalized\n\n remainder = normalized[4:]\n stripped_remainder = remainder.lstrip()\n if not stripped_remainder:\n return \"\"\n\n marker = stripped_remainder[0]\n if (\n marker.isupper()\n or not marker.isascii()\n or marker in {\"!\", \"#\", \"*\", \"-\", \"_\", \"`\", \"~\", \">\", \"[\", \"(\", \"{\", \"|\", \":\"}\n ):\n return stripped_remainder\n\n return normalized\n\n\ndef normalize_markdown(text):\n \"\"\"\n 统一整理块级元素之间的空行,提升 Obsidian 等 Markdown 渲染兼容性。\n \"\"\"\n text = strip_lake_prefix_artifact(text)\n lines = text.splitlines()\n if not lines:\n return text\n\n normalized = []\n in_fence = False\n\n def is_blank(value):\n return value.strip() == \"\"\n\n def is_fence(value):\n stripped = value.strip()\n return stripped.startswith(\"```\") or stripped.startswith(\"~~~\")\n\n def is_heading(value):\n return bool(HEADING_RE.match(value))\n\n def is_hr(value):\n return bool(HR_RE.match(value))\n\n def is_table_row(value):\n return bool(TABLE_ROW_RE.match(value))\n\n def previous_nonblank():\n for item in reversed(normalized):\n if not is_blank(item):\n return item\n return None\n\n for index, line in enumerate(lines):\n stripped = line.rstrip()\n next_line = lines[index + 1] if index + 1 \u003c len(lines) else \"\"\n prev = previous_nonblank()\n current_is_fence = is_fence(stripped)\n current_is_heading = is_heading(stripped)\n current_is_hr = is_hr(stripped)\n current_is_table = is_table_row(stripped)\n next_is_table = is_table_row(next_line)\n\n if not in_fence:\n should_prepend_blank = False\n if current_is_heading or current_is_hr or current_is_fence:\n should_prepend_blank = prev is not None\n elif current_is_table and prev is not None and not is_table_row(prev):\n should_prepend_blank = True\n\n if should_prepend_blank and normalized and not is_blank(normalized[-1]):\n normalized.append(\"\")\n\n normalized.append(stripped)\n\n if current_is_fence:\n in_fence = not in_fence\n if not in_fence and next_line and next_line.strip() and not is_blank(next_line):\n if not is_blank(normalized[-1]):\n normalized.append(\"\")\n continue\n\n if in_fence:\n continue\n\n if current_is_table and not next_is_table:\n if next_line and next_line.strip():\n normalized.append(\"\")\n elif (current_is_heading or current_is_hr) and next_line and next_line.strip():\n normalized.append(\"\")\n\n collapsed = []\n blank_count = 0\n for line in normalized:\n if is_blank(line):\n blank_count += 1\n if blank_count > 1:\n continue\n else:\n blank_count = 0\n collapsed.append(line)\n\n result = \"\\n\".join(collapsed).strip() + \"\\n\"\n return result\n\n\n# from lxml import etree\ndef load_meta_json(global_context: GlobalContext):\n \"\"\"\n 解析meta.json中标注的文件关系\n :return:\n \"\"\"\n full_path = \"/\".join([global_context.root_path, \"$meta.json\"])\n fp = open(full_path, 'r', encoding='utf-8')\n json_obj = json.load(fp)\n meta = json_obj['meta']\n # print(meta)\n meta_obj = json.loads(meta)\n book_yml = meta_obj['book']['tocYml']\n # print(book_yml)\n # with open('meta_book_yml.yaml', 'w+', encoding='utf-8') as yaml_fp:\n # yaml_fp.write(book_yml)\n # yaml_fp.flush()\n books = yaml.load(book_yml, yaml.Loader)\n for book in books:\n if book.get('uuid'):\n global_context.id_and_book[book['uuid']] = book\n if book['type'] == 'META':\n continue\n if book['parent_uuid'] == '':\n global_context.root_books.append(book)\n continue\n parent_uuid = book['parent_uuid']\n if global_context.parent_id_and_child.get(parent_uuid):\n global_context.parent_id_and_child[parent_uuid].append(book)\n else:\n global_context.parent_id_and_child[parent_uuid] = []\n global_context.parent_id_and_child[parent_uuid].append(book)\n # print(books)\n global_context.file_total = len(global_context.id_and_book)\n global_context.total = len(global_context.id_and_book)\n\n\ndef create_tree_dir(global_context, parent_dir, book):\n \"\"\"\n 根据解析出的关系创建文档的目录树\n :param parent_dir: 当前文档所在的父目录\n :param book: 当前book对象\n :param global_context 上下文\n :return:\n \"\"\"\n if book is None:\n return\n uuid = book['uuid']\n name = sanitize_path_segment(book['title'])\n file_url = book['url']\n book_children = global_context.parent_id_and_child.get(uuid)\n has_children = bool(book_children)\n current_dir = parent_dir\n\n if has_children or file_url == '':\n current_dir = remove_invalid_characters(os.path.join(parent_dir, name))\n if not os.path.exists(current_dir):\n os.makedirs(current_dir, exist_ok=True)\n\n global_context.all_file_count += 1\n if file_url != '':\n ltm = LakeToMd(\n os.path.join(global_context.root_path, \"{}.json\".format(file_url)),\n target=os.path.join(current_dir if has_children else parent_dir, name)\n )\n ltm.to_md(global_context)\n global_context.failure_image_download_list += ltm.image_download_failure\n global_context.file_count += 1\n # print(\"\\r\", end=\"\")\n # i = (file_count // file_total) * 100\n print(\"\\rprocess progress: {}/{}/{}. \".format(global_context.file_count, global_context.all_file_count,\n global_context.file_total), end=\"\")\n # sys.stdout.flush()\n # time.sleep(0.05)\n if not book_children:\n return\n for child in book_children:\n create_tree_dir(global_context, current_dir, child)\n\n\ndef register_doc_paths(global_context, parent_dir, book):\n \"\"\"\n 预先计算所有导出 markdown 路径,供内部文档链接转相对路径使用。\n \"\"\"\n if book is None:\n return\n uuid = book['uuid']\n name = sanitize_path_segment(book['title'])\n file_url = book['url']\n book_children = global_context.parent_id_and_child.get(uuid)\n has_children = bool(book_children)\n current_dir = parent_dir\n\n if has_children or file_url == '':\n current_dir = remove_invalid_characters(os.path.join(parent_dir, name))\n\n if file_url != '':\n target_base = os.path.join(current_dir if has_children else parent_dir, name)\n target_md_path = remove_invalid_characters(target_base) + \".md\"\n global_context.doc_path_map[uuid] = target_md_path\n global_context.doc_path_map[file_url] = target_md_path\n if book.get('doc_id') is not None:\n global_context.doc_path_map[str(book['doc_id'])] = target_md_path\n\n if not book_children:\n return\n for child in book_children:\n register_doc_paths(global_context, current_dir, child)\n\n\nclass LakeToMd:\n body_html = None\n image_download_failure = []\n\n def __init__(self, filename, target):\n self.filename = filename\n self.target = target\n self.__body_html()\n\n def __body_html(self):\n fp = open(file=self.filename, mode='r', encoding='utf-8')\n file_json = json.load(fp)\n fp.close()\n self.body_html = self._extract_body(file_json)\n\n @staticmethod\n def _extract_body(file_json):\n doc_json = file_json.get(\"doc\") or {}\n body_fields = (\n \"body_draft_asl\",\n \"body_asl\",\n \"body_draft\",\n \"body\",\n )\n for field in body_fields:\n body = doc_json.get(field)\n if isinstance(body, str) and body.strip():\n return LakeToMd._normalize_body(body)\n return \"\"\n\n @staticmethod\n def _normalize_body(body):\n \"\"\"\n Some lakebook documents retain a Yuque Lake format marker at the beginning,\n for example `lake\u003ch2>...`. Strip the accidental prefix so it does not render\n as `lake##` in the exported Markdown.\n \"\"\"\n return strip_lake_prefix_artifact(body)\n\n def to_md(self, global_context):\n mp = MyParser(self.body_html)\n name = os.path.basename(self.target)\n short_target = os.path.dirname(self.target)\n current_file_path = remove_invalid_characters(self.target) + \".md\"\n if short_target and not os.path.exists(short_target):\n os.makedirs(short_target, exist_ok=True)\n context = MyContext(\n filename=name,\n image_target=short_target,\n download_image=global_context.download_image,\n skip_existing=global_context.skip_existing,\n current_file_path=current_file_path,\n doc_path_map=global_context.doc_path_map\n )\n res = mp.handle_descent(mp.soup, context)\n res = normalize_markdown(res)\n self.image_download_failure += context.failure_images\n self.target = remove_invalid_characters(self.target)\n if not res.strip():\n print(f\"\\n警告: 文档导出结果为空 -> {self.filename}\")\n with open(self.target + \".md\", 'w+', encoding='utf-8') as fp:\n fp.writelines(res)\n fp.flush()\n\n\ndef convert_to_md(global_context, file_path, open_output=False):\n output_path = file_path\n if not os.path.exists(output_path):\n os.makedirs(output_path, exist_ok=True)\n global_context.doc_path_map = {}\n for root_book in global_context.root_books:\n register_doc_paths(global_context, output_path, root_book)\n for root_book in global_context.root_books:\n create_tree_dir(global_context, output_path, root_book)\n print(\"\\n>>> markdown 转换完成\")\n if open_output:\n # 根据操作系统选择合适的命令打开文件夹\n import platform\n system = platform.system()\n if system == 'Windows':\n os.system(\"explorer \" + output_path)\n elif system == 'Darwin': # macOS\n os.system(\"open \" + output_path)\n elif system == 'Linux':\n os.system(\"xdg-open \" + output_path)\n else:\n print(\"未识别的操作系统,无法自动打开输出文件夹\")\n\n\ndef start_convert(meta, lake_book, output, download_image_of_in, skip_existing=False, open_output=False):\n global_context = GlobalContext()\n temp_dir = tempfile.mkdtemp(prefix=\"yuque_export_\")\n result = {\n \"success\": False,\n \"file_count\": 0,\n \"output\": os.path.abspath(output) if output else output,\n \"error\": None,\n \"failure_images\": []\n }\n if lake_book:\n global_context.root_path = unpack_lake_book_file(lake_book, temp_dir)\n print(\">>> lake文件抽取完成\")\n else:\n global_context.root_path = meta\n if not global_context.root_path:\n print(\"参数校验失败!-i或者-l二者必须有一个\")\n result[\"error\"] = \"参数校验失败!-i或者-l二者必须有一个\"\n return result\n try:\n load_meta_json(global_context)\n print(\">>> meta json解析完成\")\n global_context.download_image = download_image_of_in\n global_context.skip_existing = skip_existing\n abspath = os.path.abspath(output)\n print(\">>> 开始进行markdown转换\")\n convert_to_md(global_context, abspath, open_output=open_output)\n print(\"共导出%s个文件\" % global_context.file_count)\n\n print(\"图片下载错误列表:\")\n print(' list: ', global_context.failure_image_download_list)\n print(' count:', len(global_context.failure_image_download_list))\n result[\"success\"] = True\n result[\"file_count\"] = global_context.file_count\n result[\"failure_images\"] = list(global_context.failure_image_download_list)\n if os.path.exists(temp_dir):\n shutil.rmtree(temp_dir)\n except Exception as e:\n if os.path.exists(temp_dir):\n shutil.rmtree(temp_dir)\n print(e)\n result[\"error\"] = str(e)\n result[\"traceback\"] = traceback.format_exc()\n return result\n# \"\"\"\n# 已经完成到根据meta生成目录了\n# \"\"\"\n# if __name__ == '__main__':\n# load_meta_json('data/$.meta.json')\n# file_total = len(id_and_book)\n# total = len(id_and_book)\n# abspath = os.path.abspath(\"test\")\n# convert_to_md(abspath)\n# print(\"共导出%s个文件\" % file_count)\n#\n# print(\"图片下载错误列表:\")\n# print(failure_image_download_list)\n# parse_failure_result(failure_image_download_list)\n","content_type":"text/x-python; charset=utf-8","language":"python","size":14036,"content_sha256":"f88e22cba480011c027bf993e0eb45f18c16e23129150f1446632b37fa10d9ab"}],"content_json":{"type":"doc","content":[{"type":"heading","attrs":{"level":1},"content":[{"text":"Yuque Lakebook Export","type":"text"}]},{"type":"paragraph","content":[{"text":"Convert one or more Yuque ","type":"text"},{"text":".lakebook","type":"text","marks":[{"type":"code_inline"}]},{"text":" files into local Markdown folders, with images and internal document links prepared for Obsidian.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"When to Use","type":"text"}]},{"type":"paragraph","content":[{"text":"Use this skill when the user asks for:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Exporting one or more Yuque ","type":"text"},{"text":".lakebook","type":"text","marks":[{"type":"code_inline"}]},{"text":" files","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Converting a Yuque knowledge base into Markdown","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Migrating Yuque content into Obsidian","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Fixing Yuque export issues around images, cropped images, internal links, hierarchy, or tables","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Do not use","type":"text"}]},{"type":"paragraph","content":[{"text":"Do not use this skill for:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Generic Markdown editing that does not involve Yuque or ","type":"text"},{"text":".lakebook","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Website scraping tasks","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Export tasks that already come from a non-Yuque format","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Instructions","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Prefer non-interactive execution so the agent can run deterministically.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Before any non-interactive export, the agent must confirm the output root directory with the user. Do not choose an output directory on the user's behalf.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"If the user has not provided an output directory, ask a concise question and wait for the user's answer before running the export command.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Prefer ","type":"text"},{"text":"uv","type":"text","marks":[{"type":"code_inline"}]},{"text":" consistently. Do not create temporary ","type":"text"},{"text":".venv","type":"text","marks":[{"type":"code_inline"}]},{"text":" or similar task-local environments in the working directory.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Before running any ","type":"text"},{"text":"uv","type":"text","marks":[{"type":"code_inline"}]},{"text":" command, first check whether ","type":"text"},{"text":"uv","type":"text","marks":[{"type":"code_inline"}]},{"text":" is available in the environment.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"If ","type":"text"},{"text":"uv","type":"text","marks":[{"type":"code_inline"}]},{"text":" is not installed or not available in ","type":"text"},{"text":"PATH","type":"text","marks":[{"type":"code_inline"}]},{"text":", the agent must ask the user for confirmation before installing ","type":"text"},{"text":"uv","type":"text","marks":[{"type":"code_inline"}]},{"text":". Do not install it silently.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Before running ","type":"text"},{"text":"uv sync","type":"text","marks":[{"type":"code_inline"}]},{"text":" or ","type":"text"},{"text":"uv run python scripts/cli.py ...","type":"text","marks":[{"type":"code_inline"}]},{"text":", the agent must first switch into the installed skill tool directory, meaning the directory that contains this ","type":"text"},{"text":"SKILL.md","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"pyproject.toml","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"uv.lock","type":"text","marks":[{"type":"code_inline"}]},{"text":", and ","type":"text"},{"text":"scripts/","type":"text","marks":[{"type":"code_inline"}]},{"text":". Do not run these commands directly from the ","type":"text"},{"text":".lakebook","type":"text","marks":[{"type":"code_inline"}]},{"text":" source directory, the output directory, or the user's current workspace root.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Use this entrypoint for agent execution:","type":"text"}]}]}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"uv run python scripts/cli.py","type":"text"}]},{"type":"ordered_list","attrs":{"order":9,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Sync dependencies before first use:","type":"text"}]}]}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"uv sync","type":"text"}]},{"type":"ordered_list","attrs":{"order":10,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Recommended command order:","type":"text"}]}]}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"cd /path/to/installed-skill-root\nuv sync\nuv run python scripts/cli.py ...","type":"text"}]},{"type":"ordered_list","attrs":{"order":11,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Standard single-file execution:","type":"text"}]}]}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"uv run python scripts/cli.py -l \"/path/to/your_file.lakebook\" -o \"/target/root\"","type":"text"}]},{"type":"ordered_list","attrs":{"order":12,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Standard batch execution:","type":"text"}]}]}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"uv run python scripts/cli.py -l \"/path/to/your_file_1.lakebook\" \"/path/to/your_file_2.lakebook\" -o \"/target/root\"","type":"text"}]},{"type":"ordered_list","attrs":{"order":13,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Although ","type":"text"},{"text":"scripts/cli.py","type":"text","marks":[{"type":"code_inline"}]},{"text":" still supports interactive terminal selection for manual human use, agents must not rely on interactive mode because they cannot reliably capture terminal interaction state. Always pass explicit ","type":"text"},{"text":"-l","type":"text","marks":[{"type":"code_inline"}]},{"text":" and ","type":"text"},{"text":"-o","type":"text","marks":[{"type":"code_inline"}]},{"text":" arguments.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Do not manually create temporary virtual environments in the current working directory, the user's download directory, or any task directory; dependencies should be managed by ","type":"text"},{"text":"uv","type":"text","marks":[{"type":"code_inline"}]},{"text":" from the skill tool directory.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Some Yuque exports include ","type":"text"},{"text":"\u003c!doctype lake>","type":"text","marks":[{"type":"code_inline"}]},{"text":" at the start of the document body; older implementations could render this as a stray ","type":"text"},{"text":"lake##","type":"text","marks":[{"type":"code_inline"}]},{"text":" prefix in Markdown. The current skill implementation already handles this case.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"After export, verify:","type":"text"}]}]}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":".md","type":"text","marks":[{"type":"code_inline"}]},{"text":" files exist","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"sibling ","type":"text"},{"text":".assets","type":"text","marks":[{"type":"code_inline"}]},{"text":" folders exist","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"internal links are relative Markdown paths","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"images render in Obsidian","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"exported documents do not start with an erroneous ","type":"text"},{"text":"lake##","type":"text","marks":[{"type":"code_inline"}]},{"text":" prefix","type":"text"}]}]}]},{"type":"ordered_list","attrs":{"order":17,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"If export fails, inspect the batch log written next to the input ","type":"text"},{"text":".lakebook","type":"text","marks":[{"type":"code_inline"}]},{"text":" files.","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"For detailed behavior, troubleshooting, and output rules, read ","type":"text"},{"text":"references/usage.md","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]}]},"metadata":{"date":"2026-06-05","name":"yuque-lakebook-export","author":"@skillopedia","source":{"stars":9,"repo_name":"awesome-agent-skills","origin_url":"https://github.com/yangsonhung/awesome-agent-skills/blob/HEAD/skills/en/yuque-lakebook-export/SKILL.md","repo_owner":"yangsonhung","body_sha256":"2d04d5a2ff0d2b122f08a54e23b869a6f2181600f9bdaa68101cff62108194c7","cluster_key":"b1e63b4f337469c5c724792940c339291f9e28807fd3b4d72ea49013643ef7f5","clean_bundle":{"format":"clean-skill-bundle-v1","source":"yangsonhung/awesome-agent-skills/skills/en/yuque-lakebook-export/SKILL.md","attachments":[{"id":"3a70ced4-d620-5d04-affc-48d8d03a4066","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/3a70ced4-d620-5d04-affc-48d8d03a4066/attachment.toml","path":"pyproject.toml","size":244,"sha256":"8dc898b7574e26073a703e00538d3e7ecfe936368f01b2c69d70bcb47bc60cea","contentType":"text/plain; charset=utf-8"},{"id":"eacf1728-0609-5c3f-aea8-5c2a163c65ac","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/eacf1728-0609-5c3f-aea8-5c2a163c65ac/attachment.md","path":"references/usage.md","size":1559,"sha256":"a62ad1f5899a608b34007d41959c9c0fc676a2d56107dbbdb404b5cdd238bb60","contentType":"text/markdown; charset=utf-8"},{"id":"292bed04-d47c-534d-af56-2761e36e5af7","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/292bed04-d47c-534d-af56-2761e36e5af7/attachment.py","path":"scripts/cli.py","size":15250,"sha256":"7687ddc6748c1d359b146100de5cbf1934a5d8e3f3e52b58099985a04c155508","contentType":"text/x-python; charset=utf-8"},{"id":"c727468b-5ff5-5d26-9b44-af33fd971184","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/c727468b-5ff5-5d26-9b44-af33fd971184/attachment.py","path":"scripts/yuque_lakebook_export/__init__.py","size":66,"sha256":"44f870e87b5edda8f3bfd8c2a03bddf034ae45e6aeaaecbde0f602bf9bfdc155","contentType":"text/x-python; charset=utf-8"},{"id":"03bef3a2-d319-58c7-be55-94a98ef52bc6","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/03bef3a2-d319-58c7-be55-94a98ef52bc6/attachment.py","path":"scripts/yuque_lakebook_export/lake_handle.py","size":21789,"sha256":"9c2ca1f6b285754215104286c192947fb6af3caf660d5ed3767947f21da571c2","contentType":"text/x-python; charset=utf-8"},{"id":"c4d7b863-e749-5386-aadd-12e082bc66fe","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/c4d7b863-e749-5386-aadd-12e082bc66fe/attachment.py","path":"scripts/yuque_lakebook_export/lake_reader.py","size":1139,"sha256":"66958bf86b0832bfa3def86706fd9ef29b0dd285ec0b7fc2a37a9e94118c8055","contentType":"text/x-python; charset=utf-8"},{"id":"d6b3a8e1-b764-5326-a88d-bfe1a1cb2c28","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/d6b3a8e1-b764-5326-a88d-bfe1a1cb2c28/attachment.py","path":"scripts/yuque_lakebook_export/lake_setup.py","size":14036,"sha256":"f88e22cba480011c027bf993e0eb45f18c16e23129150f1446632b37fa10d9ab","contentType":"text/x-python; charset=utf-8"},{"id":"b14038f3-9b11-5f80-ac53-42c461ee3038","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/b14038f3-9b11-5f80-ac53-42c461ee3038/attachment.lock","path":"uv.lock","size":22045,"sha256":"206d940f5189a3f37c1ccf74fb59803256914e1724ce350fcd4092360f756229","contentType":"text/plain; charset=utf-8"}],"bundle_sha256":"5edbe5460705006848aa0a0a4ab02164b0787f2d12e7f5b6df5144b31058feba","attachment_count":8,"text_attachments":8,"attachment_storage":"skillopedia-attachments-v1","binary_attachments":0,"excluded_attachments":[]},"cluster_size":1,"skill_md_path":"skills/en/yuque-lakebook-export/SKILL.md","import_metadata":{"date":"2026-06-05","author":"@skillopedia","version":"v1","category":"documents-office","category_label":"Documents"},"exact_dupes_collapsed_into_this":0},"license":"MIT","version":"v1","category":"documents-office","import_tag":"clean-skills-v1","description":"Export Yuque knowledge bases, Yuque documents, or .lakebook files into local Markdown folders for Obsidian. Use when users want to export Yuque, convert lakebook to Markdown, migrate a Yuque knowledge base to Obsidian, batch-convert multiple .lakebook files, or fix Yuque export issues such as missing images, cropped image mismatches, broken internal links, wrong folder hierarchy, and Markdown table rendering problems."}},"renderedAt":1782981333102}

Yuque Lakebook Export Convert one or more Yuque files into local Markdown folders, with images and internal document links prepared for Obsidian. When to Use Use this skill when the user asks for: - Exporting one or more Yuque files - Converting a Yuque knowledge base into Markdown - Migrating Yuque content into Obsidian - Fixing Yuque export issues around images, cropped images, internal links, hierarchy, or tables Do not use Do not use this skill for: - Generic Markdown editing that does not involve Yuque or - Website scraping tasks - Export tasks that already come from a non-Yuque format I…