mcpField
L
lark-hirono

lark-hirono

github.com/charles1614Documents037 installsUpdated 27w ago
Repository

About lark-hirono

lark-hirono is a skill and CLI toolkit for creating and maintaining Feishu documents from Markdown. It supports uploads, document retrieval, analysis, optimization, highlighting, and quality checks through a workflow that uses LLM judgment alongside CLI operations.

Key features

  1. 01Upload styled Feishu documents
  2. 02Fetch and analyze documents
  3. 03Optimize existing wiki pages
  4. 04Extract and apply keyword highlights
  5. 05Verify document quality

Use cases

  1. 01Publishing local Markdown to Feishu
  2. 02Lightly improving a Feishu wiki page
  3. 03Reviewing document structure and quality

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/charles1614/lark-hirono --skill lark-hirono

After installing, type/lark-hironoin Claude Code to confirm it loaded.

Bundled filesreferences/mermaid-guide.mdreferences/optimization-guide.md

Details

From the project README

Lark Hirono — Feishu Document Toolkit

Upload markdown as styled Feishu documents, optimize existing pages, fetch/analyze/highlight/verify.

Skill Files Location

This skill's supporting files are located relative to this SKILL.md:

  • references/optimization-guide.md — Quality standards and reference patterns for document transformation
  • references/mermaid-guide.md — When and how to generate mermaid diagrams; examples for common patterns

Running the CLI

Determine the correct invocation once at the start of each session, trying each step in order:

  1. Global install — check if lark-hirono is on PATH:

    command -v lark-hirono
    

    If found, use lark-hirono <action> [options] for all commands. If not found, install with npm install -g lark-hirono; and update to latest via npm update -g lark-hirono

  2. Local dev repo — only if working inside a cloned lark-hirono repo (the directory containing package.json with "name": "lark-hirono"), ensure deps are installed (npm install) and run:

    npx tsx bin/lark-hirono.ts <action> [options]
    

All examples below use lark-hirono as shorthand — substitute the resolved command.

First-Time Setup

Run these steps once before first use. Each step is a prerequisite for the next.

1. Install lark-hirono
npm install -g lark-hirono
2. Install lark-cli

lark-hirono calls the lark-cli binary (>= 1.0.9) as a subprocess for all Feishu API operations. If it's not already installed:

mkdir -p /tmp/larkcli && cd /tmp/larkcli
npm init -y && npm install @larksuite/cli
node node_modules/@larksuite/cli/scripts/install.js

Or set the LARK_CLI environment variable to point to an existing lark-cli binary.

Verify installation:

lark-cli --version   # should print >= 1.0.9
3. Configure lark-cli

Initialize the app credentials that lark-cli uses to call Feishu APIs:

lark-cli config init

This is an interactive setup — follow the prompts to provide your Feishu app ID and secret. For details on app setup and scopes, see the lark-shared skill (lark-cli config init / lark-cli auth login).

4. Authenticate
lark-hirono auth login --domain docs
# or equivalently: lark-cli auth login --domain docs

This opens a browser for Feishu OAuth. After login, the token is cached by lark-cli (typically in ~/.config/lark/).

Verify auth:

lark-hirono auth status

If the token has expired, re-run auth login.

5. Optional config file

Create lark-hirono.json in your project directory for defaults (wiki space, node, background mode). This file is optional — all values can be passed as CLI flags instead.

Prerequisites Summary
  • Node.js 20+
  • lark-cli >= 1.0.9 (installed and authenticated)
  • lark-hirono.json config file (optional, for wiki-space/wiki-node defaults)

Data Locations

  • Config file: lark-hirono.json in current directory or ancestors
  • Token cache: Managed by lark-cli (typically ~/.config/lark/)
  • Keyword batches: <input.md>.keywords_batch_N.json (generated by highlight extract)
  • Selected keywords: <input.md>.selected_keywords.json (LLM output, used by pipeline)

Arguments

$ARGUMENTS should be: ACTION [ARGS...]

Determine the action from user intent:

User intentAction
Upload local markdown to Feishuupload <input.md>
Optimize existing Feishu docSkill workflow (fetch → edit → upload)
Update Feishu doc from local fileoptimize --doc <id> --input <file>
Fetch Feishu doc as markdownfetch --doc <id>
Analyze document structureanalyze <input.md>
Extract table titles for LLMhighlight extract <input.md>
Apply keyword highlightshighlight apply <input.md> <keywords.json>
Verify Feishu doc qualityverify --doc <id>
Authentication managementauth <subcommand>

Action: upload

Upload local markdown file as styled Feishu document.

lark-hirono upload <input.md> [title] [options]

Options:

  • --title <title> — Document title (default: first H1)
  • --wiki-space <id> — Wiki space ID
  • --wiki-node <id> — Parent node ID
  • --bg-mode <mode> — Heading background: light | dark
  • --image-dir <dir> — Directory for downloaded images
  • --strip-title — Remove first H1 heading
  • --no-highlight — Skip keyword highlighting
  • --frontmatter-as-callout — Convert YAML frontmatter into a Meta callout (blockquote → Feishu callout). Without the flag, frontmatter passes through unchanged.
  • --mention-map <path> — JSON map keyed by doc URL: { "<url>": { "obj_token": "…", "obj_type"?: 22, "title"?: "…" } }. After upload, any text_run link matching a key is rewritten to a native mention_doc element so Feishu's backlinks panel and graph view populate.
  • --verify — Fetch and verify after upload
  • --dry-run — Preprocess only, print markdown to stdout
  • -v, --verbose — Verbose logging

Input format notes:

  • [^name] inline footnote refs + [^name]: body definitions are auto-detected and rewritten to unicode superscripts (⁽¹⁾…) plus a trailing ## Footnotes section. Idempotent and a no-op on inputs without footnote defs. Content inside fenced code blocks is left alone.

For catalog_table docs (tables with Code/Title columns):

  1. Run highlight extract input.md first
  2. Send JSON to LLM, save as .selected_keywords.json
  3. Upload will auto-apply keywords if file exists

Example:

lark-hirono upload my-doc.md "My Document" --wiki-space 123456

Action: optimize

Light-touch optimization of a Feishu wiki document: fix errors, repair corruption, improve formatting — while preserving the author's tone, style, and intent.

Core principle: The original document is the authority. The reference document only guides formatting structure. Never rewrite or restructure aggressively.

Output: A new wiki sub-page under the reference document containing the optimized version.

How it works: The skill uses CLI commands (fetch, upload, analyze) as tools while applying LLM judgment for corruption detection, emphasis decisions, and quality audits.

Arguments
  • SOURCE_URL: The Feishu wiki URL to optimize, e.g. https://my.feishu.cn/wiki/Abc123
  • DEST_URL (optional): A well-formatted reference doc URL; new page is created under its parent node

Extracting IDs from URLs:

  • Wiki URL https://my.feishu.cn/wiki/Abc123XYZ → doc/node ID is Abc123XYZ (the path segment after /wiki/)
  • Use this ID for --doc, --wiki-node CLI flags
Workflow

Follow these tasks in order:

  1. Read Source — Fetch and understand the source document
  2. Read Reference — Fetch and analyze the reference document's format
  3. Format Analysis — Compare structures and identify format gaps
  4. Content Review — Identify factual errors, incomplete descriptions, minor issues
  5. Generate Optimized Version — Apply light-touch improvements 5.5. Content Preservation Audit — Verify no content was dropped or shortened 5.6. Emphasis Audit — Verify color/bold density is appropriate 5.7. Rendered-Layout Regression Check — Verify no visual regressions
  6. Write to Feishu — Create new sub-page with optimized content
Task 1: Read Source Document
lark-hirono fetch --doc <source-doc-id>

Save the full output. This is the document to optimize.

Analyze carefully: topic, purpose, writing style/tone, heading structure, content flow, formatting patterns, and technical payload that must survive (numbers, formulas, systems, deployment facts, experiment settings, citations, caveats). Record observations for Task 5.

Task 2: Read Reference Document
lark-hirono fetch --doc <reference-doc-id>

Save the full output. This is the format reference only — not a content source.

Analyze the FORMAT only: heading hierarchy, section organization, formatting conventions (bold, lists), content density, structural elements (dividers, quotes, code blocks).

Task 3: Format Analysis

Read [references/optimization-guide.md](/references/optimization-guide.md) for the detailed comparison framework and known format conventions.

Reference Discipline:

  • The optimization guide is a style reference, not a license to restyle the document wholesale
  • Preserve the source document's macro-structure unless there is a clear formatting defect
  • Do not renumber or deepen the heading hierarchy just to match the reference pattern if the source already has a stable hierarchy
  • If an opening block, metadata block, or summary layout already works, prefer light cleanup over redesign

Check the source document against these specific format conventions:

ConventionExpected Pattern
Opening callout[!callout] with description + paper/repo links
Numbered headings## 1 标题 / ### 1.1 子标题
Heading groupsContinuous numbering across whole doc
Level conflictsGroup/chapter titles at correct level vs. sub-items
Callouts/quotes|> / [!callout] / > 📌 freely throughout
Code block tagsLanguage tag on every code block
Bold key termsFirst mention of important technical terms bolded
Inline emphasis{red:...} for key points; {green:...} for key terms

Hard Constraints:

  • Do not assume numbered headings are mandatory when the source already has a coherent hierarchy
  • Exception — Chinese ordinal headings are always a defect: ## 一、, ## 二、, ## 三、… use Chinese characters that do NOT trigger the tool's blue-number coloring. Always convert to ## 1 Title, ## 2 Title… format. This is not optional.
  • Do not force extra subsection levels simply because the reference is more granular
  • All siblings at the same heading level must be consistently numbered or consistently unnumbered. A lone unnumbered heading (e.g., ## Cheatsheet) among numbered siblings must be assigned the next sequential number.
  • Treat opening layout, metadata layout, and top-of-document summary layout as high-risk areas where over-editing is likely to regress the page

Important: Only note FORMAT differences. Do not compare content topics.

Task 4: Content Review (Light Touch)

Review the source document for issues that should be fixed regardless of format:

Fix These:

  • Factual errors: Incorrect technical information, wrong version numbers, broken links
  • Incomplete descriptions: Sentences that trail off, missing explanations, TODO/placeholder text
  • Obvious typos: Spelling errors, grammar mistakes that change meaning
  • Broken formatting: Unclosed markdown, inconsistent list indentation
  • Feishu export corruption: Paragraphs that became headings, broken heading hierarchy, merged content

Do NOT Change:

  • Author's tone: If they write casually, keep it casual
  • Content focus: If they emphasize certain topics, respect that emphasis
  • Technical opinions: If they recommend a tool or approach, keep it
  • Original structure: Only adjust structure if it clearly conflicts with the reference format
  • Level of detail: If the author was brief on a topic, they may have had a reason
Task 4.5: Mermaid Diagram (Best-Effort)

Read [references/mermaid-guide.md](/references/mermaid-guide.md) for patterns, rules, and placement examples.

Decision: does this document benefit from a diagram? Generate one mermaid block (placed after the opening callout, before the first heading) if the document describes a multi-stage pipeline, system architecture, branching algorithm, or process flow. Skip for reference tables, FAQs, catalogs, or docs with no flow structure. When in doubt, skip — a bad diagram is worse than no diagram.

The pipeline handles all visual styling automatically. You only write the structure.


Task 5: Generate Optimized Version

CRITICAL: Read this section carefully before writing.

The 80/20 Rule

The optimized document should be 80%+ identical to the original. Changes should be subtle improvements, not rewrites.

What to change:
  1. Opening callout — REQUIRED for narrative documents (text-heavy, few tables). Skip for catalog_table or data_table documents.

    • Write it as the very first block, before any heading.
    • Format: <callout emoji="ICON" background-color="light-blue" border-color="light-blue"> — choose an icon (e.g. gift, bulb, bookmark, pushpin, rocket, star)
    • Put the document's intro/summary description inside, closed with </callout>
    • If the source already has an intro paragraph, blockquote, or summary section that describes the document, reuse or lightly optimize that content as the callout body — do not invent new summary text
    • If no such content exists, synthesize a 1–3 sentence summary from the document's main topic and scope
    • Pipeline safety net: Pipeline auto-injects from first paragraph as fallback — always write explicitly for control over content and emoji.
  2. Heading restructuring — Fix numbering AND hierarchy when needed:

    • Apply continuous sequential numbering: ## 1, ## 2… for top-level; ### 1.1, ### 1.2… for second-level
    • Input format: Write ## 1 Title (number then space then title — no period in the markdown you write). The pipeline adds a period automatically for single-level numbers: ## 1 Title → rendered as 1. Title with blue prefix. Multi-level numbers (### 1.1 Sub) do NOT get a period added.
    • Fix Chinese ordinals: ## 一、标题 → ## 1 标题
    • Fix corruption: Paragraphs that became headings → convert back to paragraphs
    • Preserve hierarchy: Do not add or remove heading levels unless structure is broken
  3. Add emphasis — Apply {red:...} and {green:...} markers:

    • Red emphasis: Key conclusions, results, important claims (10-20 instances in a long doc)
      • Bold phrase: {red:**important conclusion**} → renders bold + red
      • Plain text: {red:term} → renders red
      • Inline code: {red:`cmd`} → renders red code
    • Green emphasis: First mention of key technical terms (5-10 instances)
      • Plain text: {green:term} → renders green
      • Inline code: {green:`code`} → renders green code
    • CRITICAL — convert raw <text color> tags from fetched docs: Raw <text color="green">BF16</text> HTML from fetched documents does NOT render in uploaded docs — it appears as plain text. During optimization, convert every <text color="COLOR">CONTENT</text> to its shorthand form: {green:CONTENT}, {red:CONTENT}, etc. If the content has bold, place bold inside: {green:**CONTENT**}. Never preserve the raw <text color> form in the optimized output.
    • Preserve all existing emphasis: Every {red:...}, {green:...}, and **bold** in the source document MUST be carried over to the optimized version. Add new emphasis on top; never remove original emphasis.
    • CRITICAL rendering rules: Bold INSIDE color tags ({red:**text**}, never **{red:text}**). No $formula$ in headings. No ** wrapping $formula$ boundaries. See optimization-guide § "Rendering Pitfalls" for full patterns.
  4. Add in-line callouts — Insert markdown blockquotes for key insights throughout the document body:

    • Use > 📌 **标题**: ... for key insights
    • Use > 📚 **背景**: ... for background knowledge
    • Target: 5-15 such blockquotes throughout a long document
    • Pipeline auto-conversion: Blockquotes matching TL;DR, 核心思想, 关键结论, 一句话总结, 核心区别 etc. are auto-converted to <callout> XML. Do not manually write <callout> XML for these — write > TL;DR: ... and let the pipeline convert.
    • CRITICAL — no emoji prefix inside <callout> XML body: When writing a <callout> XML block directly, do NOT start the body text with an emoji (📌, 💡, 📚, etc.). The emoji= attribute on the opening tag already provides the icon — adding an emoji in the body text creates a redundant double-icon display. Only the > 📌 **Title**: ... blockquote syntax (auto-converted by pipeline) needs the emoji prefix.
    • CRITICAL — no nested <callout> XML: Lark does not render a <callout> XML block nested inside another <callout> XML block. If the source document contains this pattern, convert the inner <callout> block to plain paragraphs (strip the opening/closing XML tags, keep the text). Markdown blockquotes (> ...) inside a <callout> body are fine and are NOT nested callouts.
  5. Fix code blocks — Add language tags if missing.

  6. Fix factual errors — Correct typos, broken links, wrong information

  7. Preserve images, tables, equations verbatim — Copy <image token>, <lark-table>, <equation> tags unchanged at their original positions. Do not rewrite <equation> as $...$. Do not emit pipe-wrapped |lark-table ...| — use <lark-table> XML or standard markdown tables. See [references/optimization-guide.md](/references/optimization-guide.md) § "Verified Syntax Reference" for full correct/incorrect patterns.

    • CRITICAL — equations: Never write bare LaTeX subscripts (_{\text{...}}) outside $...$ or <equation> delimiters — bare _ becomes italic. Multi-subscript bug: 2+ _{...} in one formula breaks (lark-cli pairs _ as italic). Workaround: use single-char subscripts without braces (_p, _h). Single _{...} per formula is safe.
    • CRITICAL — lark-table cells: ***bold-italic*** with underscored content (e.g. ***sm__throughput***) breaks — lark-cli misinterprets _ inside ***. Use backtick code format (`sm__throughput`) for metric names with underscores.
  8. <quote-container> handling — lark-cli upload does NOT support <quote-container> (silently drops). Pipeline auto-converts: → blockquote (outside tables) / <callout> grey (inside tables). Leave as-is or convert manually.

What NOT to change:
  • Do not rewrite paragraphs for style
  • Do not add new sections or remove existing sections
  • Do not change technical details or recommendations
  • Do not restructure the document's argument flow
Task 5.5: Content Preservation Audit

CRITICAL: Before writing to Feishu, verify that no content was lost.

Compare the optimized version against the source:

  • All sections present (no sections removed)
  • All paragraphs present (no paragraphs dropped)
  • All code blocks present (no code removed)
  • All tables present (no data lost)
  • All links preserved (no links removed)
  • Technical details intact (numbers, formulas, commands)
  • All <image token="..."> tags present (count source vs output — zero missing)
  • All <equation> blocks present and unchanged (do not rewrite or split formulas)

If content is missing: Add it back. The optimized version must have 100% of the original content.

Task 5.6: Emphasis Audit

Verify that emphasis density is appropriate:

  • Red emphasis: 10-20 instances in a long document (or proportional to length)
  • Green emphasis: 5-10 instances for first-mention technical terms
  • Not over-emphasized: No more than 3 emphasized items per paragraph
  • Not under-emphasized: Key conclusions are highlighted
Task 5.7: Rendered-Layout Regression Check

Verify that the optimized document will not have visual regressions:

  • Headings will render correctly (proper hierarchy)
  • Code blocks have language tags
  • Tables will render (proper markdown table syntax)
  • Callouts will render (proper blockquote syntax)
  • No unclosed markdown syntax
Task 6: Write to Feishu

If the source was a local file (e.g., report.md): write the optimized content to report_upload.md (same directory, _upload suffix). Never modify the original file. Never use a /tmp/ path.

If the source was fetched from Feishu: write to any convenient temp file (e.g., <title>_upload.md in current directory).

# Step 1: Write optimized content to upload file
# For local source report.md → use report_upload.md
cat > report_upload.md << 'OPTIMIZED_CONTENT_END'
[optimized markdown content here]
OPTIMIZED_CONTENT_END

# Step 2: Upload — default is always to create a new sibling page
lark-hirono optimize --doc <doc-id> --input report_upload.md --new \
  --title "Optimized: [Original Title]"

# Only update in place if the user explicitly asked to overwrite the original:
# lark-hirono optimize --doc <doc-id> --input report_upload.md

Note the --new flag creates a sibling page under the same parent node. Capture the returned URL/doc-id for the verification step below.

Task 7: Post-Upload Verification (Required)

After uploading, verify the rendered document has no regressions before reporting to the user.

lark-hirono verify --doc <new-doc-id>

Check the output for:

  • Callout present (narrative docs)
  • Headings numbered sequentially, no Chinese ordinals
  • No \# artifacts (escaped hashes leaked into text — pipeline uses ZWSP instead)
  • No plain-text <text color> tags visible in content
  • Content count plausible (not drastically shorter than source)

If issues are found → fix the local upload file, re-upload with --new (or overwrite the just-created page if you have its ID), and verify again. Iterate up to 3 times total.

After a clean verify (or after exhausting 3 attempts), report to user:

  1. URL of the new page
  2. Changes made — brief list of formatting improvements applied
  3. Confidence level — how confident you are in the changes; note any unresolved issues from the retry loop

Action: fetch

Retrieve Feishu document as markdown.

lark-hirono fetch --doc <doc-id> [--output file.md]

Options:

  • --doc <id> — Document ID (required)
  • --output <file> — Save to file (default: stdout)

Outputs markdown to stdout unless --output is given.


Action: analyze

Analyze markdown document structure.

lark-hirono analyze <input.md>

Returns JSON with:

  • document_type — narrative | data_table | catalog_table | mixed
  • heading_count — Number of headings
  • table_count — Number of tables
  • table_rows — Total table rows
  • suggested_modules — Recommended transformations

Action: highlight

Extract table titles for LLM keyword selection, or apply keywords to markdown.

Extract
lark-hirono highlight extract <input.md> [--batch-size N]

Extracts Code/Title columns from tables, saves as:

  • input.md.keywords_batch_0.json
  • input.md.keywords_batch_1.json (if >200 titles)

Next step: Send JSON files to LLM, save response as input.md.selected_keywords.json

Apply
lark-hirono highlight apply <input.md> <keywords.json> [--inplace]

Wraps keywords in {red:**keyword**} tags within table titles.

Note: upload and optimize auto-apply if .selected_keywords.json exists.


Action: verify

Fetch and verify Feishu document quality.

lark-hirono verify --doc <doc-id>
lark-hirono verify <doc-id>          # positional form

Options:

  • --doc <id> — Document ID (required unless passed positionally)
  • -v, --verbose — Verbose output

Reports:

  • Block/heading/table counts, heading background coverage
  • Red highlights and bold header counts
  • Residual HTML tags (should be empty)
  • Pass/fail checks for structural and content-level expectations

Exit code 0 on pass, 1 on any failing check.


Action: auth

Feishu authentication management (passthrough to lark-cli).

lark-hirono auth login
lark-hirono auth status

Document Types

Narrative — Text-heavy documents with headings

  • Transforms: normalize, headings, callout
  • No LLM needed

Catalog_table — Tables with Code/Title columns, 50+ rows

  • Transforms: normalize, tables, keyword highlighting
  • LLM needed for keyword selection

Data_table — Tables with <50 rows

  • Transforms: normalize, tables
  • No LLM needed

Workflow Examples

Upload narrative doc
lark-hirono upload my-article.md
Upload catalog_table doc with keywords
lark-hirono highlight extract catalog.md
# Send catalog.md.keywords_batch_0.json to LLM
# Save response as catalog.md.selected_keywords.json
lark-hirono upload catalog.md
Optimize existing Feishu doc
lark-hirono optimize --doc CcKqdWjF2o2UzixXZDecXxvInyc
Update Feishu doc from local file
lark-hirono optimize --doc CcKqdWjF2o2UzixXZDecXxvInyc --input local.md
Upload a note with frontmatter + native backlinks
# mentions.json is a JSON object keyed by doc URL:
# { "https://www.feishu.cn/wiki/<node_token>": { "obj_token": "<obj_token>" } }
lark-hirono upload post.md \
  --frontmatter-as-callout \
  --mention-map mentions.json

After upload, any markdown link to a URL in mentions.json becomes a native Feishu doc mention, populating the backlinks panel on the target doc.


Supporting Files

  • references/optimization-guide.md — Quality standards and reference patterns
  • references/mermaid-guide.md — Mermaid diagram patterns and examples

Comments

Markdown supported