142 lines
5.9 KiB
Markdown
142 lines
5.9 KiB
Markdown
# 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** (📎, drag-drop, paste, or a URL) and say
|
||
*"build something like this"*: a **photo**, a **PDF plan**, a **3D model**
|
||
(STL/STEP/OBJ — rendered to an image, with its bounding box measured), or a
|
||
**web-page guide** (its text is pulled). WoodShop 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 ~7–13s per utterance (one `claude -p` call).
|
||
|
||
## License
|
||
|
||
MIT
|