calibre-metadata-apply
A skill for updating metadata of existing Calibre books.
Skill selection contract (strict)
- If the user intent is metadata edit/fix/update, this skill is mandatory.
- If the request mentions ID-based title fix (e.g.
ID1011 タイトル修正), this skill is mandatory.
calibre-catalog-read must not be used for those edit intents.
Use this skill when the user asks any of:
- "ID指定でタイトル修正"
- "メタデータ編集"
title/authors/series/series_index/tags/publisher/pubdate/languages updates
Do NOT route those requests to calibre-catalog-read.
Requirements
calibredb must be available on PATH in the runtime environment
subagent-spawn-command-builder installed (for spawn payload generation)
pdffonts is optional/recommended for PDF evidence checks
- Reachable Calibre Content server URL
http://HOST:PORT/#LIBRARY_ID
- If
LIBRARY_ID is unknown, use #- once to list available IDs on the server.
--with-library can be omitted only when one of these is configured:
- env:
CALIBRE_WITH_LIBRARY or CALIBRE_LIBRARY_URL or CALIBRE_CONTENT_SERVER_URL
- config:
~/.config/calibre-metadata-apply/config.json with with_library
- optional library id completion:
CALIBRE_LIBRARY_ID or config library_id
- Host failover (IP change resilience):
- Optional env:
CALIBRE_SERVER_HOSTS=host1,host2,...
- Script auto-tries candidates, including WSL host-side
nameserver from /etc/resolv.conf.
- If authentication is enabled, prefer
/home/altair/.openclaw/.env:
CALIBRE_USERNAME=<user>
CALIBRE_PASSWORD=<password>
- Auth scheme policy for this workflow:
- Non-SSL deployment assumes Digest authentication.
- Do not pass auth mode arguments such as
--auth-mode / --auth-scheme.
- Pass
--password-env CALIBRE_PASSWORD (username auto-loads from env)
- You can still override explicitly with
--username <user>.
- Optional auth cache:
--save-auth (default file: ~/.config/calibre-metadata-apply/auth.json)
Supported fields
Direct fields (set_metadata --field)
title
title_sort
authors (string with & or array)
author_sort
series
series_index
tags (string or array)
publisher
pubdate (YYYY-MM-DD)
languages
comments
Helper fields
comments_html (OC marker block upsert)
analysis (auto-generates analysis HTML for comments)
analysis_tags (adds tags)
tags_merge (default true)
tags_remove (remove specific tags after merge)
Required execution flow
A. Target confirmation (mandatory)
- Run read-only lookup to narrow candidates
- Show
id,title,authors,series,series_index
- Get user confirmation for final target IDs
- Build JSONL using only confirmed IDs
B. Proposal synthesis (when metadata is missing)
- Collect evidence from file extraction + web sources
- Show one merged proposal table with:
candidate, source, confidence (high|medium|low)
title_sort_candidate, author_sort_candidate
- Get user decision:
approve all
approve only: <fields>
reject: <fields>
edit: <field>=<value>
- Apply only approved/finalized fields
- If confidence is low or sources conflict, keep fields empty
C. Apply
- Run dry-run first (mandatory)
- Run
--apply only after explicit user approval
- Re-read and report final values
Analysis worker policy
- Use
subagent-spawn-command-builder to generate sessions_spawn payload for heavy candidate generation
task is required.
- Profile should include model/thinking/timeout/cleanup for this workflow.
- Use lightweight subagent model for analysis (avoid main heavy model)
- Keep final decisions + dry-run/apply in main
Data flow disclosure
- Local execution:
- Build
calibredb set_metadata commands from JSONL.
- Read/write local state files (
state/runs.json) and optional auth/config files under ~/.config/calibre-metadata-apply/.
- Subagent execution (optional for heavy candidate generation):
- Uses
sessions_spawn via subagent-spawn-command-builder.
- Text/metadata sent to subagent can reach model endpoints configured by runtime profile.
- Remote write:
calibredb set_metadata updates metadata on the target Calibre Content server.
Security rules:
- Do not use
--save-plain-password unless explicitly instructed by the user.
- Prefer env-based password (
--password-env CALIBRE_PASSWORD) over inline --password.
- If user does not want external model/subagent processing, keep flow local and skip subagent orchestration.
- In agent/chat execution, do not call
calibredb directly for edit operations.
- Always execute
node skills/calibre-metadata-apply/scripts/calibredb_apply.mjs.
- Never run
calibre-server from this skill.
- This workflow always targets an already-running Calibre Content server.
Connection bootstrap (mandatory)
- Do not ask the user for
--with-library first.
- First, execute using saved defaults (env/config) with no explicit
--with-library.
- Scripts auto-load
.env and resolve CALIBRE_WITH_LIBRARY / CALIBRE_CONTENT_SERVER_URL.
- Ask user for URL only when command output shows unresolved connection, such as:
missing --with-library
unable to resolve usable --with-library
- repeated connection failures for all candidates
Long-run turn-split policy (library-wide)
For library-wide heavy processing, always use turn-split execution.
Unknown-document recovery flow (M3)
Batch sizing rule:
- Keep each unknown-document batch small enough to show full row-by-row results in chat (no representative sampling).
- If unresolved items remain, stop and wait for explicit user instruction to start the next batch.
User intervention checkpoints (fixed)
Light pass (metadata-only)
- Always run this stage by default (no extra user instruction required)
- Analyze existing metadata only (no file content read)
- Present a table to user:
- current file/title
- recommended title/metadata
- confidence/evidence summary
- Stop and wait for user instruction before any deeper stage
On user request: page-1 pass
- Read only the first page and refine proposals
- Report delta from light pass
If still uncertain: deep pass
- Read first 5 pages + last 5 pages
- Add web evidence search
- Produce finalized proposal with confidence + rationale
Approval gate
- Show detailed findings and request explicit approval before apply
Pending and unsupported handling
- Use
pending-review tag for unresolved/hold items.
- If document is unresolved in current flow, do not force metadata guesses.
- Tag with
pending-review and keep for follow-up investigation.
Diff report format (for unknown batch runs)
Return full results (not samples):
- execution summary (target/changed/pending/skipped/error)
- full changed list with
id + key before/after fields
- full pending list with
id + reason
- full error list with
id + error summary
- confidence must be expressed as
high|medium|low
Runtime artifact policy
- Keep run-state and temporary artifacts only while a run is active.
- On successful completion, remove per-run state/artifacts.
- On failure, keep minimal artifacts only for retry/debug, then clean up after resolution.
Internal orchestration (recommended)
- Use lightweight subagent for all analysis stages
- Keep apply decisions in main session
- Persist run state for each stage in
state/runs.json
Turn 1 (start)
- Main defines scope
- Main generates spawn payload via
subagent-spawn-command-builder (profile example: calibre-meta), then calls sessions_spawn
- Save
run_id/session_key/task via scripts/run_state.mjs upsert
- Immediately tell the user this is a subagent job and state the execution model used for analysis
- Reply with "analysis started" and keep normal chat responsive
Turn 2 (completion)
- Receive subagent completion notice
- Save result JSON
- Complete state handling via
scripts/handle_completion.mjs --run-id ... --result-json ...
- Return summarized proposal (apply only when needed)
Run state file:
PDF extraction policy
- Try
ebook-convert first
- If empty/failed, fallback to
pdftotext
- If both fail, switch to web-evidence-first mode
Sort reading policy
- Use user-configured
reading_script for Japanese/non-Latin sort fields
katakana / hiragana / latin
- Ask once on first use, then persist and reuse
- Default policy is full reading (no truncation)
- Config path:
~/.config/calibre-metadata-apply/config.json
Usage
Dry-run:
cat changes.jsonl | node skills/calibre-metadata-apply/scripts/calibredb_apply.mjs \
--with-library "http://127.0.0.1:8080/#MyLibrary" \
--password-env CALIBRE_PASSWORD \
--lang ja
Dry-run (when default library is preconfigured via env/config):
cat changes.jsonl | node skills/calibre-metadata-apply/scripts/calibredb_apply.mjs \
--password-env CALIBRE_PASSWORD \
--lang ja
Apply:
cat changes.jsonl | node skills/calibre-metadata-apply/scripts/calibredb_apply.mjs \
--with-library "http://127.0.0.1:8080/#MyLibrary" \
--password-env CALIBRE_PASSWORD \
--apply
Do not
- Do not run direct
--apply using ambiguous title matches only
- Do not include unconfirmed IDs in apply payload
- Do not auto-fill low-confidence candidates without explicit confirmation
- Do not start a local server with guessed path like
~/Calibre Library
1---2name: calibre-metadata-apply3description: Primary skill for Calibre metadata edits over a running Content server. Use this for ID-based title/authors/series/series_index/tags/publisher/pubdate/languages updates and controlled apply after confirmation.4---56# calibre-metadata-apply78A skill for updating metadata of existing Calibre books.910## Skill selection contract (strict)1112- If the user intent is metadata edit/fix/update, this skill is mandatory.13- If the request mentions ID-based title fix (e.g. `ID1011 タイトル修正`), this skill is mandatory.14- `calibre-catalog-read` must not be used for those edit intents.1516Use this skill when the user asks any of:17- "ID指定でタイトル修正"18- "メタデータ編集"19- `title/authors/series/series_index/tags/publisher/pubdate/languages` updates2021Do NOT route those requests to `calibre-catalog-read`.2223## Requirements2425- `calibredb` must be available on PATH in the runtime environment26- `subagent-spawn-command-builder` installed (for spawn payload generation)27- `pdffonts` is optional/recommended for PDF evidence checks28- Reachable Calibre Content server URL29 - `http://HOST:PORT/#LIBRARY_ID`30 - If `LIBRARY_ID` is unknown, use `#-` once to list available IDs on the server.31- `--with-library` can be omitted only when one of these is configured:32 - env: `CALIBRE_WITH_LIBRARY` or `CALIBRE_LIBRARY_URL` or `CALIBRE_CONTENT_SERVER_URL`33 - config: `~/.config/calibre-metadata-apply/config.json` with `with_library`34 - optional library id completion: `CALIBRE_LIBRARY_ID` or config `library_id`35- Host failover (IP change resilience):36 - Optional env: `CALIBRE_SERVER_HOSTS=host1,host2,...`37 - Script auto-tries candidates, including WSL host-side `nameserver` from `/etc/resolv.conf`.38- If authentication is enabled, prefer `/home/altair/.openclaw/.env`:39 - `CALIBRE_USERNAME=<user>`40 - `CALIBRE_PASSWORD=<password>`41- Auth scheme policy for this workflow:42 - Non-SSL deployment assumes **Digest** authentication.43 - Do not pass auth mode arguments such as `--auth-mode` / `--auth-scheme`.44- Pass `--password-env CALIBRE_PASSWORD` (username auto-loads from env)45- You can still override explicitly with `--username <user>`.46- Optional auth cache: `--save-auth` (default file: `~/.config/calibre-metadata-apply/auth.json`)4748## Supported fields4950### Direct fields (`set_metadata --field`)51- `title`52- `title_sort`53- `authors` (string with `&` or array)54- `author_sort`55- `series`56- `series_index`57- `tags` (string or array)58- `publisher`59- `pubdate` (`YYYY-MM-DD`)60- `languages`61- `comments`6263### Helper fields64- `comments_html` (OC marker block upsert)65- `analysis` (auto-generates analysis HTML for comments)66- `analysis_tags` (adds tags)67- `tags_merge` (default `true`)68- `tags_remove` (remove specific tags after merge)6970## Required execution flow7172### A. Target confirmation (mandatory)731. Run read-only lookup to narrow candidates742. Show `id,title,authors,series,series_index`753. Get user confirmation for final target IDs764. Build JSONL using only confirmed IDs7778### B. Proposal synthesis (when metadata is missing)791. Collect evidence from file extraction + web sources802. Show one merged proposal table with:81 - `candidate`, `source`, `confidence (high|medium|low)`82 - `title_sort_candidate`, `author_sort_candidate`833. Get user decision:84 - `approve all`85 - `approve only: <fields>`86 - `reject: <fields>`87 - `edit: <field>=<value>`884. Apply only approved/finalized fields895. If confidence is low or sources conflict, keep fields empty9091### C. Apply921. Run dry-run first (mandatory)932. Run `--apply` only after explicit user approval943. Re-read and report final values9596## Analysis worker policy9798- Use `subagent-spawn-command-builder` to generate `sessions_spawn` payload for heavy candidate generation99 - `task` is required.100 - Profile should include model/thinking/timeout/cleanup for this workflow.101- Use lightweight subagent model for analysis (avoid main heavy model)102- Keep final decisions + dry-run/apply in main103104## Data flow disclosure105106- Local execution:107 - Build `calibredb set_metadata` commands from JSONL.108 - Read/write local state files (`state/runs.json`) and optional auth/config files under `~/.config/calibre-metadata-apply/`.109- Subagent execution (optional for heavy candidate generation):110 - Uses `sessions_spawn` via `subagent-spawn-command-builder`.111 - Text/metadata sent to subagent can reach model endpoints configured by runtime profile.112- Remote write:113 - `calibredb set_metadata` updates metadata on the target Calibre Content server.114115Security rules:116- Do not use `--save-plain-password` unless explicitly instructed by the user.117- Prefer env-based password (`--password-env CALIBRE_PASSWORD`) over inline `--password`.118- If user does not want external model/subagent processing, keep flow local and skip subagent orchestration.119- In agent/chat execution, do not call `calibredb` directly for edit operations.120 - Always execute `node skills/calibre-metadata-apply/scripts/calibredb_apply.mjs`.121- Never run `calibre-server` from this skill.122 - This workflow always targets an already-running Calibre Content server.123124## Connection bootstrap (mandatory)125126- Do not ask the user for `--with-library` first.127- First, execute using saved defaults (env/config) with no explicit `--with-library`.128 - Scripts auto-load `.env` and resolve `CALIBRE_WITH_LIBRARY` / `CALIBRE_CONTENT_SERVER_URL`.129- Ask user for URL only when command output shows unresolved connection, such as:130 - `missing --with-library`131 - `unable to resolve usable --with-library`132 - repeated connection failures for all candidates133134## Long-run turn-split policy (library-wide)135136For library-wide heavy processing, always use turn-split execution.137138## Unknown-document recovery flow (M3)139140Batch sizing rule:141- Keep each unknown-document batch small enough to show full row-by-row results in chat (no representative sampling).142- If unresolved items remain, stop and wait for explicit user instruction to start the next batch.143144### User intervention checkpoints (fixed)1451461. **Light pass (metadata-only)**147 - Always run this stage by default (no extra user instruction required)148 - Analyze existing metadata only (no file content read)149 - Present a table to user:150 - current file/title151 - recommended title/metadata152 - confidence/evidence summary153 - Stop and wait for user instruction before any deeper stage1541552. **On user request: page-1 pass**156 - Read only the first page and refine proposals157 - Report delta from light pass1581593. **If still uncertain: deep pass**160 - Read first 5 pages + last 5 pages161 - Add web evidence search162 - Produce finalized proposal with confidence + rationale1631644. **Approval gate**165 - Show detailed findings and request explicit approval before apply166167### Pending and unsupported handling168169- Use `pending-review` tag for unresolved/hold items.170- If document is unresolved in current flow, do not force metadata guesses.171 - Tag with `pending-review` and keep for follow-up investigation.172173### Diff report format (for unknown batch runs)174175Return full results (not samples):176- execution summary (target/changed/pending/skipped/error)177- full changed list with `id` + key before/after fields178- full pending list with `id` + reason179- full error list with `id` + error summary180- confidence must be expressed as `high|medium|low`181182### Runtime artifact policy183184- Keep run-state and temporary artifacts only while a run is active.185- On successful completion, remove per-run state/artifacts.186- On failure, keep minimal artifacts only for retry/debug, then clean up after resolution.187188### Internal orchestration (recommended)189190- Use lightweight subagent for all analysis stages191- Keep apply decisions in main session192- Persist run state for each stage in `state/runs.json`193194### Turn 1 (start)1951. Main defines scope1962. Main generates spawn payload via `subagent-spawn-command-builder` (profile example: `calibre-meta`), then calls `sessions_spawn`1973. Save `run_id/session_key/task` via `scripts/run_state.mjs upsert`1984. Immediately tell the user this is a subagent job and state the execution model used for analysis1995. Reply with "analysis started" and keep normal chat responsive200201### Turn 2 (completion)2021. Receive subagent completion notice2032. Save result JSON2043. Complete state handling via `scripts/handle_completion.mjs --run-id ... --result-json ...`2054. Return summarized proposal (apply only when needed)206207Run state file:208- `state/runs.json`209210## PDF extraction policy2112121. Try `ebook-convert` first2132. If empty/failed, fallback to `pdftotext`2143. If both fail, switch to web-evidence-first mode215216## Sort reading policy217218- Use user-configured `reading_script` for Japanese/non-Latin sort fields219 - `katakana` / `hiragana` / `latin`220- Ask once on first use, then persist and reuse221- Default policy is full reading (no truncation)222- Config path: `~/.config/calibre-metadata-apply/config.json`223 - key: `reading_script`224225## Usage226227Dry-run:228229```bash230cat changes.jsonl | node skills/calibre-metadata-apply/scripts/calibredb_apply.mjs \231 --with-library "http://127.0.0.1:8080/#MyLibrary" \232 --password-env CALIBRE_PASSWORD \233 --lang ja234```235236Dry-run (when default library is preconfigured via env/config):237238```bash239cat changes.jsonl | node skills/calibre-metadata-apply/scripts/calibredb_apply.mjs \240 --password-env CALIBRE_PASSWORD \241 --lang ja242```243244Apply:245246```bash247cat changes.jsonl | node skills/calibre-metadata-apply/scripts/calibredb_apply.mjs \248 --with-library "http://127.0.0.1:8080/#MyLibrary" \249 --password-env CALIBRE_PASSWORD \250 --apply251```252253## Do not254255- Do not run direct `--apply` using ambiguous title matches only256- Do not include unconfirmed IDs in apply payload257- Do not auto-fill low-confidence candidates without explicit confirmation258- Do not start a local server with guessed path like `~/Calibre Library`