How book-to-skill Manages Its Per-Run Work Directory

book-to-skill creates a unique, isolated work directory for every extraction using the current process ID, stores it under the system temp folder, and allows full override via the BOOK_SKILL_WORKDIR environment variable.

The virgiliojr94/book-to-skill repository implements a per-run work directory strategy that keeps each book extraction self-contained. This design prevents concurrent runs from stepping on each other's files, avoids legacy cleanup hazards, and gives operators full control when needed.


Location and Default Path Generation

The default work directory lives in the system temporary folder, but with a critical safeguard: it sits as a sibling to the legacy fixed path, not a child.

In book_to_skill/config.py, the default_output_dir() function constructs this path:

def default_output_dir() -> Path:
    """Per-run work directory, unique to this process.
    ... (see full docstring) ...
    """
    return Path(tempfile.gettempdir()) / f"book_skill_work-{os.getpid()}"

This placement—/tmp/book_skill_work-{PID} rather than /tmp/book_skill_work/{PID}—ensures that old cleanup scripts targeting $TMPDIR/book_skill_work cannot accidentally delete an active extraction's data.


Process Isolation via PID-Based Naming

Uniqueness is guaranteed by embedding os.getpid() in the directory name. Two extractions running simultaneously receive distinct paths, eliminating race conditions and file corruption.

The computed paths are exported as module-level constants:

OUTPUT_DIR = Path(os.environ.get("BOOK_SKILL_WORKDIR") or default_output_dir())
OUTPUT_TEXT = OUTPUT_DIR / "full_text.txt"
OUTPUT_META = OUTPUT_DIR / "metadata.json"

These resolve at import time. Any code importing from book_to_skill.config sees a stable, process-scoped workspace for the full extraction lifecycle.


Environment Variable Override

Operators can bypass automatic path generation entirely using BOOK_SKILL_WORKDIR.

Scenario Behavior
Variable unset Uses default_output_dir() with PID-based temp path
Variable set to valid path Uses that path exactly
Variable set to empty string Still falls back to PID-based temp path (empty string is not interpreted as current directory)

Override example:

export BOOK_SKILL_WORKDIR=/my/custom/workdir
python -m book_to_skill path/to/book.pdf
from book_to_skill.config import OUTPUT_DIR
assert OUTPUT_DIR == Path("/my/custom/workdir")

Practical Usage Examples

Accessing the default work directory

from book_to_skill.config import OUTPUT_DIR, OUTPUT_TEXT, OUTPUT_META

print("Work directory:", OUTPUT_DIR)          # e.g. /tmp/book_skill_work-12345

print("Full-text file:", OUTPUT_TEXT)         # /tmp/book_skill_work-12345/full_text.txt

print("Metadata file:", OUTPUT_META)          # /tmp/.../metadata.json

Verifying uniqueness across forked workers

import multiprocessing, os
from book_to_skill.config import default_output_dir

def worker(_):
    print(f"PID {os.getpid()}{default_output_dir()}")

with multiprocessing.Pool(2) as pool:
    pool.map(worker, range(2))

# Output shows two distinct temp dirs, each ending with the worker's PID

Testing and Validation

The test suite in tests/test_per_run_workdir.py enforces four critical guarantees:

  • Uniqueness: Default directories differ between calls in the same process (PID-based).
  • Sibling placement: The directory is not a child of the legacy path.
  • Temp containment: The directory resides inside the system temp folder.
  • Override integrity: Explicit BOOK_SKILL_WORKDIR wins, and empty values do not collapse to CWD.

These tests ensure the per-run work directory behaves correctly across platforms and deployment scenarios.


Where the Work Directory Is Consumed

File Role
book_to_skill/config.py Defines default_output_dir(), reads BOOK_SKILL_WORKDIR, exports OUTPUT_DIR, OUTPUT_TEXT, OUTPUT_META
book_to_skill/utils.py References OUTPUT_DIR for temporary file handling and token estimation (via "workdir": str(OUTPUT_DIR) in utility dictionaries)
tests/test_per_run_workdir.py Validates uniqueness, placement, and override behavior

Summary

  • PID-scoped paths (book_skill_work-{PID}) guarantee isolation between concurrent extractions.
  • Sibling placement to the legacy path prevents accidental deletion by stale cleanup scripts.
  • BOOK_SKILL_WORKDIR provides full operator override without misinterpreting empty strings.
  • Computed once at import, the work directory remains stable throughout the extraction process.

Frequently Asked Questions

How does book-to-skill prevent two runs from using the same directory?

It embeds the current process ID (os.getpid()) in the directory name via default_output_dir(). Since operating systems guarantee unique PIDs for concurrent processes, no two active runs can collide.

Can I specify a custom work directory instead of the temp folder?

Yes. Set the BOOK_SKILL_WORKDIR environment variable to any absolute path. The code checks this variable first and uses it directly, bypassing the PID-based default entirely.

What happens if BOOK_SKILL_WORKDIR is set to an empty string?

The code treats an empty string as unset and falls back to the PID-based temporary path. This prevents accidental use of the current working directory, which could pollute your project files.

Where are the extracted full text and metadata files stored?

Inside the per-run work directory as full_text.txt and metadata.json. These paths are pre-computed as OUTPUT_TEXT and OUTPUT_META in book_to_skill/config.py and imported wherever the files are written or read.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →