Lucy bind paths + LAN host pins replaced with env defaults. Repository URLs → git.sulkta.com. Audit-changelog scaffolding stripped from inline comments (technical reasoning preserved). README sheds marketing scaffolding. AI-speak in load-bearing prompts/SOULs left alone — that IS the product. |
||
|---|---|---|
| docs | ||
| engines | ||
| migrations | ||
| seeds/authors | ||
| skald | ||
| skald-core | ||
| vendor/clawdforge | ||
| .gitignore | ||
| Cargo.lock | ||
| Cargo.toml | ||
| compose.yml | ||
| Dockerfile | ||
| entrypoint.sh | ||
| LICENSE | ||
| README.md | ||
skald
Long-form story-writer with canon-keeping, sequel continuity, and self-hosted audiobook narration. The database is the source of truth; the binary is the tooling.
Named for the Old Norse poets who composed and memorized kings' sagas across generations.
What's wired
- Rust workspace (
skald-core+skald) - Postgres schema for stories, characters, canon facts, chapters, passages, generation runs, audit findings, tags
- pgvector for future similarity search
skald import-markdowningests a story file (chapters + bible)skald serveexposes/health+ the web inspector and runs migrations on bootskald continueruns gen → cleanup → audit per chapter, with multi-chapter batching (cap 20)skald rewritere-authors a chapter in a named author's voiceskald auditruns whole-story prose-quality audit;skald dedupis the surgical fix half of the loopskald prepare-narrationannotates a chapter with[breath]/[pause:Xs]/[scene]beats and per-character[voice:...]tagsskald narraterenders a chapter to audio via one of three TTS engines (F5-TTS, Kokoro-82M, Tortoise-TTS) — seeengines/- Named-author "soul" personas via
skald authors seed; author voice replaces the model's base system prompt for gen/cleanup/ rewrite/dedup/narrate_prep
Schema (cheat sheet)
stories meta + status + parent/root for series
authors persona identity (slug, display_name, model)
author_revisions versioned souls; one current per author
characters real or fictional, story-scoped, voice-mappable
canon_facts setting, mystery, theme, rule, historical_anchor, hook
chapters full prose body + optional body_md_tts annotation
chapter_summaries short summaries for cheap context loading
passages paragraph-level + embedding vector(1536)
voices TTS voice rows (F5 ref clips / Kokoro / Tortoise names)
pronunciation_overrides per-story + global respellings for proper nouns
generation_runs every LLM call logged
audit_findings audit pass output (severity + area)
narration_runs per-chapter TTS renders
Quickstart
docker compose up -d
docker exec skald skald import-markdown --path /seed/<story>.md \
--title "<title>"
curl http://localhost:7780/health
The compose file expects POSTGRES_PASSWORD and (optionally)
CLAWDFORGE_URL + CLAWDFORGE_TOKEN in .env. Story markdown
goes into ./seed/; postgres data persists in ./pgdata/.
Architecture
v0.1 ships postgres inside the skald container — singleton until
the tool stabilises. To extract postgres later, swap the runtime
base to debian:bookworm-slim, drop entrypoint.sh, and point
DATABASE_URL at the external pg. The binary doesn't care where
the DB lives.
The generation passes call out to clawdforge (a bearer-token-gated
HTTP wrapper around claude -p). The Rust client is vendored at
vendor/clawdforge/. TTS calls go HTTP+JSON to the per-engine
sidecars under engines/.
License
MIT — see LICENSE.