# WoodShop **Voice-driven conversational 3D woodworking & furniture modeler.** Talk to it like the Star Trek holodeck and watch furniture build itself: > *"Place a 6 foot 2x4, sand it, then attach a 2 foot 2x4 at 90 degrees, 10 inches from the end."* > *"Build a coffee table: a four foot by two foot frame from 2x4s, with four legs 18 inches tall standing at the corners."* Each board is real dimensional lumber (a 2x4 is modeled at its true 1.5″ × 3.5″), so the result is buildable — export to **STEP** (CAD/CNC) or **STL** (3D print), and get a **cut list with board-feet and a shopping estimate**. ## How it works WoodShop reuses the existing [CmdForge](https://gitea.brrd.tech/rob/cmdforge) tool ecosystem for everything that isn't woodworking-specific, so no wheels are reinvented: ``` woodshop-talk ── the conversational loop │ dictate ............. speech → text (CmdForge tool) │ pa-load-tools ....... wood-* → Claude schemas (CmdForge tool) │ claude -p ........... interpret → tool calls (provider) │ pa-execute-tool ..... dispatch each wood-* (CmdForge tool) │ read-aloud .......... speak confirmation (CmdForge tool) ▼ scene.json ← single source of truth (parts, joints, selection, undo) ▲ │ writes │ reads/mutates ▼ wood-* CmdForge tools woodshop-view (place/join/stand/move/...) live pyvista 3D, watches scene.json ``` The `wood-*` tools are thin wrappers over the `woodshop` CLI, so the modeling logic lives in one place and the tools double as the LLM's documented command vocabulary. ## Installation ```bash python -m venv .venv && source .venv/bin/activate pip install -e ".[gui,dev]" # 'gui' pulls build123d + pyvista + PySide6 + pyvistaqt python scripts/gen_wood_tools.py # register the wood-* CmdForge tools ``` ## Usage ### The studio (recommended) ```bash woodshop # launches the unified desktop app ``` One window with the **3D viewport** (click a board to select it), a **parts panel** (list + selected-part inspector + quick-action buttons), and a **command bar** at the bottom where you type or push-to-talk (🎤). Mouse, keyboard, and voice all drive the same scene and the same visible selection, so "delete that" / the Delete button / saying "delete the front-left leg" are interchangeable. Menus cover New/Open/Save projects, Export STL/STEP, Save Image, Undo/Redo, camera views, and Build templates. ### Standalone tools (headless / scripting) ```bash woodshop-view & # just the live 3D window (watches the scene) woodshop-talk # just the voice/text loop; --voice to speak woodshop-talk --once "build a workbench top from five 2x6 boards 6 feet long" ``` Or drive it directly from the CLI: ```bash woodshop place 2x4 "6 ft" # place a board woodshop stand # stand it up (a leg) woodshop join p2 --to p1 --angle 90 --offset "10 in" woodshop rename "front-left leg" woodshop cutlist # bill of materials woodshop export table.step # STEP / STL export woodshop save "coffee table" # named projects woodshop open "coffee table" ``` Run `woodshop --help` for the full command list (place, join, stand, lay, rotate, move, trim, copy, rename, sand, delete, undo, clear, status, cutlist, export, save, open, projects). The active scene lives at `$WOODSHOP_SCENE` or `~/.local/share/woodshop/scene.json`; named projects in `~/.local/share/woodshop/projects/`. ## Development ```bash pytest # 41 tests ``` Key modules: | Module | Role | |--------|------| | `scene.py` | Part/Joint/Scene model, operations, undo, persistence | | `lumber.py` | nominal → actual dimensional lumber table | | `units.py` | parse "6 ft" / "3 ft 6 in" / "-2 ft" → inches | | `cli.py` | the `woodshop` command | | `geometry.py` | build123d solids + STL/STEP export | | `cutlist.py` | cut list, board-feet, shopping estimate | | `viewer.py` | live pyvista 3D viewport (`woodshop-view`) | | `driver.py` | conversational loop (`woodshop-talk`) | | `scripts/gen_wood_tools.py` | (re)generate the `wood-*` CmdForge tools | ### Known limitations - Joins are flush butt joints: B's end sits against A's face and B aligns to A's reference corner (tops level + one side flush), so mixed-size boards line up. Joinery *cuts* (mortise/tenon, lap, pocket holes) aren't modeled yet. - Command interpretation latency is ~7–13s per utterance (one `claude -p` call). ## License MIT