SkillHub

calibre-catalog-read

v1.0.6

Read-only Calibre catalog lookup and one-book analysis-comments workflow over a running Content server. Use only for list/search/id and analysis comments block updates, never for title/authors/tags/series/series_index metadata edits.

Sourced from ClawHub, Authored by NEXTAltair

Installation

Please help me install the skill `calibre-catalog-read` from SkillHub official store. npx skills add NEXTAltair/calibre-catalog-read

calibre-catalog-read

Use this skill for: - Read-only catalog lookup (list/search/id) - One-book AI reading workflow (export -> analyze -> cache -> comments HTML apply)

Skill selection contract (strict)

  • This skill is read-only for catalog lookup + analysis workflow.
  • If user intent includes metadata edit/fix/update (title/authors/series/series_index/tags/publisher/pubdate/languages), route to calibre-metadata-apply and do not execute edit paths here.

Do NOT use this skill for: - Editing title/authors/series/series_index/tags/publisher/pubdate/languages - Any user request that says "metadata edit", "title fix", "ID指定で編集" - Those must use calibre-metadata-apply

Requirements

  • calibredb available on PATH in the runtime where scripts are executed.
  • ebook-convert available for text extraction.
  • subagent-spawn-command-builder installed (for spawn payload generation).
  • Reachable Calibre Content server URL in --with-library format:
  • http://HOST:PORT/#LIBRARY_ID
  • If LIBRARY_ID is unknown, use #- once to list available IDs on the server.
  • Do not assume localhost/127.0.0.1; always pass explicit reachable HOST:PORT.
  • --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-catalog-read/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 auth is enabled:
  • Preferred: set in /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.
  • Then pass only --password-env CALIBRE_PASSWORD (username auto-loads from env)
  • You can still override with --username <user> explicitly.
  • Optional auth cache file: ~/.config/calibre-catalog-read/auth.json
    • Avoid --save-plain-password unless explicitly requested.

Commands

List books (JSON):

node skills/calibre-catalog-read/scripts/calibredb_read.mjs list 
  --with-library "http://192.168.11.20:8080/#Calibreライブラリ" 
  --password-env CALIBRE_PASSWORD 
  --limit 50

Search books (JSON):

node skills/calibre-catalog-read/scripts/calibredb_read.mjs search 
  --with-library "http://192.168.11.20:8080/#Calibreライブラリ" 
  --password-env CALIBRE_PASSWORD 
  --query 'series:"中公文庫"'

Get one book by id (JSON):

node skills/calibre-catalog-read/scripts/calibredb_read.mjs id 
  --with-library "http://192.168.11.20:8080/#Calibreライブラリ" 
  --password-env CALIBRE_PASSWORD 
  --book-id 3

Run one-book pipeline (analyze + comments HTML apply + cache):

uv run python skills/calibre-catalog-read/scripts/run_analysis_pipeline.py 
  --with-library "http://192.168.11.20:8080/#Calibreライブラリ" 
  --password-env CALIBRE_PASSWORD 
  --book-id 3 --lang ja

Cache DB

Initialize DB schema:

uv run python skills/calibre-catalog-read/scripts/analysis_db.py init 
  --db skills/calibre-catalog-read/state/calibre_analysis.sqlite

Check current hash state:

uv run python skills/calibre-catalog-read/scripts/analysis_db.py status 
  --db skills/calibre-catalog-read/state/calibre_analysis.sqlite 
  --book-id 3 --format EPUB

Main vs Subagent responsibility (strict split)

Use this split to avoid long blocking turns on chat listeners.

Main agent (fast control plane)

  • Validate user intent and target book_id.
  • Confirm subagent runtime knobs: model, thinking, runTimeoutSeconds.
  • Start subagent and return a short progress reply quickly.
  • After subagent result arrives, run DB upsert + Calibre apply.
  • Report final result to user.

Subagent (heavy analysis plane)

  • Read extracted source payload.
  • Generate analysis JSON strictly by schema.
  • Do not run metadata apply or user-facing channel actions.

Never do in main when avoidable

  • Long-form content analysis generation.
  • Multi-step heavy reasoning over full excerpts.

Turn policy

  • One book per run.
  • Prefer asynchronous flow: quick ack first, final result after analysis.
  • If analysis is unavailable, either ask user or use fallback only when explicitly acceptable.

Subagent pre-flight (required)

Before first subagent run in a session, confirm once: - model - thinking (low/medium/high) - runTimeoutSeconds

Do not ask on every run. Reuse the confirmed settings for subsequent books in the same session unless the user asks to change them.

Subagent support (model-agnostic)

Book-reading analysis is a heavy task. Use a subagent with a lightweight model for analysis generation, then return results to main agent for cache/apply steps.

  • Prompt template: references/subagent-analysis.prompt.md
  • Input schema: references/subagent-input.schema.json
  • Output schema: references/subagent-analysis.schema.json
  • Input preparation helper: scripts/prepare_subagent_input.mjs
  • Splits extracted text into multiple files to avoid read-tool single-line size issues.

Rules: - Use subagent only for heavy analysis generation; keep main agent lightweight and non-blocking. - In this environment, Python commands must use uv run python. - Use the strict prompt template (references/subagent-analysis.prompt.md) as mandatory base; do not send ad-hoc relaxed read instructions. - Keep final DB upsert and Calibre metadata apply in main agent. - Process one book per run. - Confirm model/thinking/timeout once per session, then reuse; do not hardcode provider-specific model IDs in the skill. - Configure callback/announce behavior and rate-limit fallbacks using OpenClaw default model/subagent/fallback settings (not hardcoded in this skill). - Exclude manga/comic-centric books from this text pipeline (skip when title/tags indicate manga/comic). - If extracted text is too short, stop and ask user for confirmation before continuing. - The pipeline returns reason: low_text_requires_confirmation with prompt_en text. - For read operations in agent/chat, prefer node .../calibredb_read.mjs instead of direct calibredb calls. - Never run calibre-server from this skill. - This workflow always connects to an already-running Calibre Content server.

Connection bootstrap (mandatory)

  • Do not ask the user for --with-library first.
  • First, run read commands (list/search/id) without explicit --with-library and use saved defaults.
  • Scripts auto-load .env and resolve CALIBRE_WITH_LIBRARY / CALIBRE_CONTENT_SERVER_URL.
  • Ask user for URL only if resolution fails (missing --with-library / unable to resolve usable --with-library).

Language policy

  • Do not hardcode user-language prose in pipeline scripts.
  • Generate user-visible analysis text from subagent output, with language controlled by user-selected settings and lang input.
  • Fallback local analysis in scripts is generic/minimal; preferred path is subagent output following the prompt template.

Orchestration note (important)

run_analysis_pipeline.py is a local script and does not call OpenClaw tools by itself. Subagent execution must be orchestrated by the agent layer using sessions_spawn.

Required runtime sequence: 1. Main agent prepares subagent_input.json + chunked source_files from extracted text. - Use: bash node skills/calibre-catalog-read/scripts/prepare_subagent_input.mjs --book-id <id> --title "<title>" --lang ja --text-path /tmp/book_<id>.txt --out-dir /tmp/calibre_subagent_<id> 2. Main agent uses the shared builder skill subagent-spawn-command-builder to generate the sessions_spawn payload, then calls sessions_spawn. - Build with profile calibre-read and run-specific analysis task text. - Use the generated JSON as-is (or merge minimal run-specific fields such as label/task text). 3. Subagent reads all source_files and returns analysis JSON (schema-conformant). 4. Main agent passes that file via --analysis-json to run_analysis_pipeline.py for DB/apply.

If step 2 is skipped, pipeline falls back to local minimal analysis (only for emergency/testing).

Chat execution model (required, strict)

For Discord/chat, always run as two separate turns.

Turn A: start only (must be fast)

  • Select one target book.
  • Build spawn payload with subagent-spawn-command-builder (--profile calibre-read + run-specific --task).
  • Call sessions_spawn using that payload.
  • Record run state (runId) via run_state.mjs upsert.
  • Reply to user with selected title + "running in background".
  • Stop turn here.

Turn B: completion only (separate later turn)

Trigger: completion announce/event for that run. - Run one command only (completion handler): - scripts/handle_completion.mjs (get -> apply -> remove, and fail on error). - If runId is missing, handler returns stale_or_duplicate and does nothing. - Send completion/failure reply from handler result.

Hard rule: - Never poll/wait/apply in Turn A. - Never keep a chat listener turn open waiting for subagent completion.

Run state management (single-file, required)

For one-book-at-a-time operation, keep a single JSON state file: - skills/calibre-catalog-read/state/runs.json

Use runId as the primary key (subagent execution id).

Lifecycle: 1. On spawn acceptance, upsert one record: - runId, book_id, title, status: "running", started_at 2. Do not wait/poll inside the same chat turn. 3. On completion announce, load record by runId and run apply. 4. On successful apply, delete that record immediately. 5. On failure, set status: "failed" + error and keep record for retry/debug.

Rules: - Keep this file small and operational (active/failed records only). - Ignore duplicate completion events when record is already removed. - If record is missing at completion time, report as stale/unknown run and do not apply blindly.

Use helper scripts (avoid ad-hoc env var mistakes):

# Turn A: register running task
node skills/calibre-catalog-read/scripts/run_state.mjs upsert 
  --state skills/calibre-catalog-read/state/runs.json 
  --run-id <RUN_ID> --book-id <BOOK_ID> --title "<TITLE>"

# Turn B: completion handler (preferred)
node skills/calibre-catalog-read/scripts/handle_completion.mjs 
  --state skills/calibre-catalog-read/state/runs.json 
  --run-id <RUN_ID> 
  --analysis-json /tmp/calibre_<BOOK_ID>/analysis.json 
  --with-library "http://HOST:PORT/#LIBRARY_ID" 
  --password-env CALIBRE_PASSWORD --lang ja