woodshop/README.md

140 lines
5.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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."*
You can also **attach a reference photo** (📎, drag-drop, paste, or an image URL)
and say *"build something like this"* — WoodShop hands the image to the model and
builds a simplified, buildable interpretation in dimensional lumber that you then
refine by voice/text. (It's an interpretation, not a measured replica.)
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; Ctrl+click to
select several), a **parts panel** (list + selected-part inspector +
quick-action buttons), a **numberpad control panel** (move/rotate the selection
by clicking or with your keyboard's numpad — 2/4/6/8 move, 1/3/7/9 rotate, +/
raise/lower, 0/. front/iso, 5 fit), and a **command bar** where you type or
push-to-talk (🎤). Mouse, keyboard, and voice all drive the same scene and the
same visible selection — so "move these 4 inches", the numpad 8 key, and the
move button are interchangeable, and act on every selected board at once (one
undo). 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 # 200+ tests
```
Key modules:
| Module | Role |
|--------|------|
| `scene.py` | Part/Joint/Connection/Feature/Scene model, ops, undo, persistence |
| `lumber.py` | nominal → actual dimensions, material colors/defaults |
| `colors.py` | color name → hex + lightness blends for the viewer |
| `units.py` | parse "6 ft" / "3 ft 6 in" / "-2 ft" → inches |
| `cli.py` | the `woodshop` command |
| `geometry.py` | build123d solids (incl. joinery booleans) + STL/STEP export |
| `cutlist.py` | quick cut list / board-feet / shopping summary |
| `cutplan.py` | the deterministic keystone: kerf-aware nesting, rough/final, batch, offcut reuse |
| `prices.py` | editable price book (Kent NB) + material-aware cost estimate |
| `estimate.py` | project quote: consumables + labor + suggested selling price |
| `inventory.py` | shop-wide event-sourced stock / offcut / build ledger |
| `instructions.py` / `jigs.py` | deterministic build steps & jig suggestions |
| `viewer.py` | live pyvista 3D viewport (`woodshop-view`) |
| `driver.py` | conversational loop (`woodshop-talk`) |
| `gui/` | the unified PySide6 studio (`woodshop-gui`), incl. the Cut List & BOM window |
| `scripts/gen_wood_tools.py` | (re)generate the `wood-*` CmdForge tools |
### Known limitations
- **Joinery** is parametric (tenon/mortise/dado/rabbet/hole/slot/chamfer as
build123d boolean ops, with connections/assemblies); what's *not* modeled is
joinery-fit compensation for material lost to sanding, and lap/pocket-hole
presets. Boards still attach as flush butt joints unless you add features.
- Render is flat colors per material/finish — no image textures (wood grain) yet.
- Command interpretation latency is ~713s per utterance (one `claude -p` call).
## License
MIT