homebrew-pipeline
A deterministic, local-first pipeline for rendering Markdown through a pinned Homebrewery checkout and exporting verified Letter PDFs.
End-user installation
The release target is a normal desktop install: download a Windows .exe, a
Debian/Ubuntu .deb, or a general Linux .AppImage, then install or launch it
without opening a terminal. Node, npm, Rust, Playwright, Poppler, Git, Docker,
and this source repository are developer dependencies only and are bundled or
otherwise absent from the end-user experience.
That work is split into M10a (linked-vault configuration and a simpler document workspace), M10b (managed single-file import/export), and M10c (published installers and clean-machine release verification). M10a and M10b are complete. The repository contains verified Linux packaging foundations and native build definitions, but it does not yet publish release-grade installers for general users. Do not direct nontechnical users to the development commands below as an installation method.
Developer requirements
Use Node >=26.4.0 and npm >=10.8 <12. The repository pins Node
26.7.0 in .node-version. Git is required for the Homebrewery submodule,
Poppler supplies pdfinfo/pdftotext, and Playwright Chromium performs PDF
export.
On Debian/Ubuntu, install Poppler with:
sudo apt-get install poppler-utils
Developer clean-clone setup
Run these commands from the repository root, in order:
git submodule update --init --recursive
npm install
npx playwright install --with-deps chromium
npm run build
npm exec -- homebrew-pipeline doctor
npm exec -- homebrew-pipeline build tests/fixtures/basic/example.md
The first install links a committed CLI launcher; no second install is
needed after the build. Generated PDFs are written beneath output/ unless
--output is supplied.
Commands
# Check required and optional local dependencies
npm exec -- homebrew-pipeline doctor
# Build one Markdown file
npm exec -- homebrew-pipeline build path/to/note.md --output output/note.pdf
# Build with a project-configured ComfyUI provider and manual prompt
npm exec -- homebrew-pipeline build path/to/note.md \
--image-prompt "A brass owl in an enchanted orchard" --image-seed 42
# Explicitly enable bounded optional transforms for this job
npm exec -- homebrew-pipeline build path/to/note.md \
--ai-rewrite "Make concise without changing rules" --ai-image-prompt
# Recursively build a configured project; unchanged files skip rendering
npm exec -- homebrew-pipeline build-dir path/to/project
# Inspect durable jobs (override state location when needed)
npm exec -- homebrew-pipeline jobs --state-root .homebrew-pipeline
npm exec -- homebrew-pipeline job <job-id> --state-root .homebrew-pipeline
# Build and start the local web control panel
npm run web
A project is a directory containing .homebrew-pipeline/config.json.
Configuration controls source/output roots, include/exclude globs, local asset
roots, Obsidian parsing, and render settings. Builds never modify source notes.
CLI jobs and cache use .homebrew-pipeline or PIPELINE_STATE_ROOT when set;
the desktop app instead keeps registry state under its OS config directory and
per-project jobs/cache under OS app data.
The linked-vault wizard can inspect an existing config or create these reviewed local defaults without hand-authoring JSON:
{
"version": 1,
"sourceRoot": ".",
"outputRoot": "./PDF",
"assetRoots": ["."],
"include": ["**/*.md"],
"exclude": [".git/**", ".obsidian/**", ".trash/**", ".homebrew-pipeline/**", "PDF/**"],
"markdown": { "obsidian": true },
"render": { "paper": "letter", "autoPaginate": true },
"images": { "provider": "manual" },
"ai": { "provider": "none" }
}
Creation requires review and confirmation, refuses to clobber a config that appeared or changed after inspection, and rejects configured paths that escape the selected vault. Resetting invalid JSON is a separate confirmed action that first preserves a timestamped backup beside the config.
Local web control panel
Run npm run web, then open http://127.0.0.1:4173. The Fastify server is
loopback-only by default and serves the production React bundle plus the local
API. The primary Documents workspace combines the project/document browser,
selected-document Build action, collapsed optional settings, progress, and a
verification-gated PDF preview. Advanced contains project management, Batch
build, Folder Watch, Jobs, Settings, and Diagnostics. These remain control
surfaces over the same core services, manifests, and logs used by the CLI.
Projects are read from ignored config/sources.local.json. On first run, enter
a mounted or absolute folder path; BrewVault inspects it before offering to use,
create, or explicitly back up and reset its configuration. Set
PIPELINE_SOURCES_CONFIG to keep the development registry elsewhere, and set
PORT to change the local port. Browser requests cannot escape a project's
configured source/output roots.
The Open Markdown File branch imports exactly one selected .md file into a
private workspace below OS app data. It copies only uniquely resolved local
images referenced through standard Markdown or Obsidian image syntax; sibling
Markdown is never imported. Missing, ambiguous, remote, or unsupported images
are reported as visible warnings. The original file and assets remain
unchanged.
Managed workspaces contain private Source, Assets, and PDF directories
plus a one-document, composition-ready manifest. A completed build can be
exported only after PDF verification; an existing destination requires a
separate overwrite confirmation. Removing a managed project offers either
unregister-and-keep or an explicitly confirmed workspace deletion. Removing a
linked project only unregisters it and never deletes vault content.
Automatic pagination
Set render.autoPaginate to true in a project's
.homebrew-pipeline/config.json to enable deterministic Letter-page layout.
The pipeline renders and measures top-level document blocks in isolated
Chromium, inserts a break at the previous safe boundary, and repeats up to its
fixed retry ceiling. Explicit \page markers are preserved. Source Markdown is
never rewritten; the paginated IR, final candidate Markdown, per-pass geometry,
HTML, and PNG page previews are retained inside the durable job directory.
Docker
Copy the example environment file and set BREWVAULT_SOURCE to an absolute
host path for the vault that should be mounted read-only:
cp .env.example .env
# Edit .env and set BREWVAULT_SOURCE=/absolute/path/to/your/vault
mkdir -p output
docker compose build app
docker compose run --rm app doctor
docker compose run --rm app build tests/fixtures/basic/example.md --output output/example.pdf
The vault is mounted at the neutral container path /projects/vault.
Mutable job/cache state and generated PDFs stay in the writable output/
volume. The image includes Node, Playwright Chromium, and Poppler; ComfyUI is
optional and remains external.
For web-driven Docker use, every selectable host project must be mounted into the container first. A browser folder picker cannot grant the container new filesystem access. Give each project a stable container path and register that path—not its host path—in the web project registry:
volumes:
- type: bind
source: /home/user/Documents/MyVault
target: /projects/MyVault
read_only: true
- type: bind
source: ./output/MyVault-PDF
target: /projects/MyVault/PDF
- type: bind
source: ./output/state
target: /app/output
The nested writable PDF mount must match that project's configured
outputRoot; this preserves a read-only source mount while allowing web and
batch builds to install PDFs. Keep PIPELINE_STATE_ROOT and, when the web
server itself runs in the container, PIPELINE_SOURCES_CONFIG, on the writable
/app/output mount. Additional project roots follow the same
/projects/<name> convention.
Practical development vault
This checkout can register a local practical vault through ignored
config/sources.local.json and .env files. Those machine-specific values
are development conveniences, not part of the shared application contract.
Any compatible external vault can be used.
The linked-vault wizard now supplies the missing configuration contract. It shows the exact config/output policy and writes only after confirmation; merely inspecting or registering an already-valid vault does not modify source files.
Optional ComfyUI images
Set images.provider to comfyui in project configuration, point it to an
API-format workflow below the project root, and identify the prompt, seed,
and filename-prefix node IDs. The CLI requires a manual --image-prompt;
no LLM is involved. Submission state is durable, so restarting a build that
was interrupted during polling resumes its existing ComfyUI prompt. See
workflows/comfyui/README.md for the configuration contract. M6 supports one
generated Obsidian image embed per build, matching its one-manual-prompt CLI
contract.
Optional AI transforms
Project configuration may select the provider-neutral json-http transform
adapter, but AI remains off until each job explicitly sets --ai-rewrite or
--ai-image-prompt (or the corresponding web controls). Only paragraph rewrite
and ComfyUI image-prompt generation are supported. Every call contains one
strict bounded request; there is no chat history, tools, filesystem context,
workflow orchestration, or web-image search. Provider output is schema-checked
before the resolved IR or transform artifact is written. See
packages/ai/README.md for configuration, environment-only credentials, hard
limits, and the JSON endpoint contract.
Desktop application
M9 adds a Tauri 2 shell around the same local web/core runtime. It provides a native project-folder picker, drag and drop, build notifications, application menus, debounced folder watching, and optional close-to-tray behavior. The packaged Node 26 runtime, production dependencies, pinned Homebrewery resources, PDF.js verifier, and Playwright Chromium are installer resources; users do not need a separate Node or Poppler installation for desktop builds.
Desktop development requires Rust 1.98 and Tauri's platform libraries. On Debian/Ubuntu:
sudo apt-get install libwebkit2gtk-4.1-dev build-essential curl wget file \
libxdo-dev libssl-dev libayatana-appindicator3-dev librsvg2-dev patchelf
rustup toolchain install 1.98.0 --profile minimal
npm run desktop:dev
Run npm run desktop:build for native installers. Linux produces deb and
AppImage, Windows produces NSIS, and the existing M9 workflow can build macOS
app/dmg. M10c will restrict tag-triggered publication to Windows/Linux; macOS
may remain a manual internal Actions artifact but cannot enter the public
release job. No cross-OS installer is claimed from a Linux host. Installer
staging and Rust build output are ignored under apps/desktop/src-tauri.
These npm commands are for developers building releases; end users must receive
the already-packaged artifact.
M10a–M10c add the release-grade journey in independently verifiable steps:
linked-vault configuration/workspace UX, managed-file import/export, then
versioned artifacts with checksums and clean-machine verification. See
DEVELOPMENT_HANDOFF.md for the exact pickup state.
Project status
Milestones M0–M9 are complete: repository/toolchain, deterministic
single-file rendering, AST-based Obsidian compatibility, manual/local
images, durable recoverable jobs, cached batch builds, and independently
reproduced clean-clone onboarding, optional durable ComfyUI image generation,
the local web control panel, automatic DOM-measured pagination, and explicitly
enabled bounded text transforms, and native Tauri packaging around the unchanged
core. M10a (project configuration and simplified workspace) and M10b (managed
single-file import/export) are complete. M10c is not started and awaits the
revised release direction. See
MILESTONES.md for the authoritative tracker and DEVELOPMENT_HANDOFF.md for
developer/agent pickup instructions.
How to Install
- Download the ZIP or clone the repository
- Open the folder as a vault in Obsidian (File → Open Vault)
- Obsidian will prompt you to install required plugins
Stats
Stars
0
Forks
0
Last updated 5d ago
Categories