A personal, always-on, phone-friendly workspace for designing, slicing, and printing physical objects through conversation.
This project is intentionally a thin 3D-printing distribution of Pi + Pi Web, combined with a set of custom skills to automate model creation, slicing, and printing. It is not a new CAD system, slicer, printer controller, agent runtime, or general-purpose project-management product. Pi owns the agent, sessions, filesystem, shell, skills, and subscription-backed model authentication. Pi Web supplies the responsive chat, projects, files, uploads, Git, activity, and debugging UI. The custom layer makes that foundation feel like a focused appliance.
Open the app on a phone, choose a project, and continue a chat. Send text, a photo, a file, or a URL. The agent uses installed 3D-printing skills to obtain or create a model, render and validate an STL, and—when asked—slice and print it. The resulting model is immediately inspectable in the browser. Iterate through chat until the physical design is right.
The core loop is:
chat + photos/files/URLs
↓
agent works in project folder
↓
STL appears or changes
↓
rotate / pan / zoom / inspect
↓
describe the next change
↺
The system must support the full spectrum from execution to collaboration:
- “Print this model URL with the filament that is loaded.”
- “Use this photo to make a 50 mm spacer.”
- “Help me develop a tablet stand for this tablet and this pole.”
The agent should resolve safe, reversible details itself and ask only when ambiguity matters. It may freely research, download, model, render, validate, and slice. Starting a physical print remains a deliberate human action: the person still chooses/loads filament, clears the plate, and confirms the print.
| Area | Decision |
|---|---|
| Audience | Personal appliance: one primary user, one always-on host, initially one printer |
| Access | Responsive web UI over a private network/VPN such as Tailscale |
| Agent foundation | Pi, coupled directly rather than hidden behind a portability layer |
| Web foundation | Pi Web, lightly patched and extended |
| Model access | Frontier models through subscription authentication; initially ChatGPT Plus/Pro OAuth through Pi |
| Project creation | Explicit New Project action; name only for MVP |
| Conversations | Multiple independent Pi sessions inside each project |
| Persistence | Pi sessions for conversation; project filesystem and Git for artifacts/history |
| Domain behavior | Existing 3D modeling, slicing, and printer-control skills |
| MVP artifact | STL with interactive in-browser viewing |
| Git | Automatic commit after each completed user/agent interaction that changed files |
| Checkpoints | Optional, human-significant annotated Git tags; ordinary commits remain low-ceremony |
| Voice | Use OS transcription for now; native voice is later scope |
| Portability/multi-user SaaS | Explicitly not a goal |
The product deliberately exposes only two levels:
PROJECT
├── CHAT
├── CHAT
├── CHAT
├── FILES
├── CURRENT MODEL
└── HISTORY
A project is a physical thing or design effort. It is an explicitly created folder and Git repository.
A chat is a named, resumable Pi session rooted at that project folder. Multiple chats share artifacts, memory, instructions, printer-skill state, and Git history while retaining independent conversational context.
Pi Web internally has a Project → Workspace → Session hierarchy. For this appliance, the workspace is always the project root and is hidden or deemphasized in the normal UI. No separate project database, conversation database, ORM, or synchronization layer is added. The filesystem is the project database.
Example:
~/3d-projects/tablet-stand/
├── .git/
├── .gitignore
├── AGENTS.md
├── .pi-web/
├── reference/
│ ├── tablet-photo.jpg
│ └── pole-photo.jpg
├── tablet-stand.scad
├── tablet-stand.stl
└── tablet-stand.gcode
That folder might have chats named “Original design,” “Fix cable routing,” and “Reprint after failure,” all using the same working directory.
Phone / tablet / desktop browser
│
private VPN/LAN
│
▼
┌───────────────────────────────────────────┐
│ Autofab shell (apps/autofab-web/src) │
│ AutofabApp extends PiWebApp — arrangement │
│ only: projects screen, appliance bar, │
│ phone tab bar, Industry design system │
├───────────────────────────────────────────┤
│ Pi Web client (vendored, pinned tag) │
│ chat · uploads · files · Git · activity │
│ terminal · settings · plugin host │
├───────────────────────────────────────────┤
│ pi-web-server + pi-web-sessiond │
│ stock npm, untouched; the custom client │
│ is served through buildApp({ clientDist })│
└───────────────────┬───────────────────────┘
│ Pi sessions
▼
┌───────────────────────────────────────────┐
│ Pi │
│ OAuth · session persistence · AGENTS.md │
│ filesystem · shell · agent skills │
│ │
│ Custom: auto-commit + checkpoint extension│
└───────────────────┬───────────────────────┘
│
▼
┌───────────────────────────────────────────┐
│ Per-project folder and Git repository │
│ references · CAD source · STL · G-code │
│ renders · skill state · project memory │
└───────────────────┬───────────────────────┘
│ installed skills
▼
modeler · slicer · printer
The shell knows projects, chats, files, model artifacts, agent status, and history. It does not know how to model, how a slicer works, what printer is connected, or how filament/printer state is represented. Those are skill concerns. A skill-owned state file may be visible through the files UI, but the app must not duplicate or reinterpret it.
This foundation already provides the expensive, fundamental pieces: persistent agent sessions, project folders, mobile browser access, uploads, files, Git views, terminal access, activity state, subscription authentication, and skills. Pi Web’s plugin surface can add a first-class workspace panel, allowing the STL viewer to remain an extension rather than a large application fork.
OpenCode Web remains a plausible fallback if upstream Pi/Pi Web assumptions fail, but backend portability is not itself a requirement. The project should optimize for one excellent working configuration.
Pi Web's plugin API turned out to be sufficient for domain extensions and insufficient for the appliance's navigation: it contributes actions, workspace panels, workspace labels, and colour-only themes, and it has no verb for selecting a project, workspace, or session. ADR-0002 therefore vendors the Pi Web client at a pinned tag and extends it, while the server, session daemon, and Pi runtime stay untouched pinned dependencies. About 27,000 lines of chat streaming, transcript projection, prompt editor, terminal, files, Git, settings, and the plugin host keep working and keep improving on upgrade.
The intended custom surface is deliberately small.
The shell (apps/autofab-web/src) subclasses Pi Web's root element and owns only the arrangement: a project chooser instead of a navigation rail, an appliance top bar with agent status, the phone tab bar under the thumb, and the Industry design system. Every control calls a PiWebApp member that already exists.
The discipline that keeps this small: if a control cannot be expressed as calling existing Pi Web behaviour from a different place in the layout, it is not shell work — it belongs to a gated phase in PLAN.md. Vendored Pi Web sources are regenerated by scripts/sync-upstream.mjs and never hand-edited; the two patches applied to them are mechanical visibility and typing changes with asserted substitution counts.
Stock coding tools generally add an existing folder or repository. This product needs New Project with one required field: a name.
Creating “Tablet Stand” should:
- Generate a safe, collision-free folder slug under a configured projects root.
- Create the directory from the project template.
- Initialize Git and make an initial commit.
- Register/open the folder as a Pi Web project.
- Treat the project-root workspace as implicit.
- Create/open the first Pi session and focus the chat input.
Pi Web's addProject(path) registers an existing directory, so name-only transactional creation is new capability rather than arrangement. It is gated on the project-semantics decision (backlog I-001, Gate D).
The first project screen may be only a project list plus New Project. Rich cards, thumbnails, model badges, and summaries are later polish.
Add Model alongside Chat and Files. On mobile, Chat and Model are primary; Git, Terminal, and advanced activity can live in an overflow or advanced area.
For MVP the plugin:
- recursively discovers
.stlfiles in the project; - sorts them by modification time and infers the newest as current;
- allows manual selection when several exist;
- supports touch-friendly orbit, pan, zoom, reset/fit, and standard views;
- displays filename and model dimensions in millimetres;
- reloads when the current STL changes; and
- shows an update/unread indicator on the Model tab.
Use a small Three.js-based STL viewer rather than a CAD framework. Both ASCII and binary STL must work. Files on disk are the integration contract: there is no artifact database, required manifest, or publish_artifact() call in MVP.
Do not patch the transcript renderer for v1. An updated Model tab with a visible dot/button is sufficient. Inline model cards can be added later only if real use shows they are worth the additional fork maintenance.
After a user request finishes and the agent settles:
agent settled
↓
project Git status
↓
changes? ── no ──► do nothing
│ yes
▼
stage project changes
↓
commit with a short description of the completed change
Use the lifecycle boundary corresponding to one completed human↔agent interaction (for example, Pi’s settled event), not every internal model/tool step. Serialize Git mutation per project so two sessions cannot race. If a prior run left changes behind, preserve them and describe the actual committed state; never discard files to manufacture a clean history.
Ordinary commits are frequent implementation history and mostly stay out of the primary UI. Save Checkpoint creates an annotated tag on the current commit, using an optional human name, for example:
checkpoint/fits-tablet-correctly
The agent may suggest a checkpoint when a complete, printable, or explicitly approved milestone emerges. It may create one proactively when agreement is unambiguous, but must report that it did so. Checkpoints should remain meaningful and relatively rare.
- Always-on Pi + Pi Web installation reachable from a phone over a private network.
- ChatGPT subscription authentication through the chosen Pi flow.
- Existing 3D-printing skills installed and usable by Pi.
- Explicit, name-only project creation.
- Project folder/template creation and Git initialization.
- Multiple resumable chats per project, all rooted at the same folder.
- Text chat, photo/file upload, URL input, and visible working/idle state.
- Project files and downloads through Pi Web.
- Interactive STL Model view with current-model inference and refresh.
- Automatic Git commit after each settled interaction that changed files.
- Manual named/unnamed Save Checkpoint using annotated tags.
- Advanced access to native Pi Web Files, Git, Terminal, and activity views for debugging.
- Cleaner project cards with current-chat, activity, and STL indicators.
- G-code as an emphasized artifact with metadata/download.
- Better progress summaries over raw tool activity.
- Version/checkpoint browsing and model preview at a selected checkpoint.
- Installation/update scripts and basic backup guidance.
- G-code layer preview.
- 3MF preview.
- Inline STL cards in chat.
- Point/circle/region annotations on model previews that become chat context.
- Model-to-model visual diff.
- Native voice input.
- Sharing/export of resulting models.
- Multi-printer or multi-user support, only if actual usage calls for it.
- A custom agent/session runtime.
- A custom conversation or project database.
- A general project-management system.
- Reimplementation of CAD, slicing, printer control, or printer state.
- Backend portability for its own sake.
- Public internet exposure or a multi-tenant security model.
- A polished saleable product before the personal workflow is proven.
- Physical model annotation, rich transcript artifacts, or G-code visualization in the first MVP.
ai-print-lab/
├── README.md product ideation (this file)
├── PLAN.md implementation sequence
├── AGENTS.md working agreements
├── docs/architecture/ drivers, decision backlog, ADRs
├── apps/
│ └── autofab-web/ the appliance UI
│ ├── src/ Autofab shell — ours
│ ├── upstream/pi-web/ vendored Pi Web client — generated
│ ├── upstream/patches.mjs mechanical patch set
│ ├── upstream/UPSTREAM.json tag, commit, tree hash
│ └── scripts/ sync-upstream, serve
├── phase0/
│ ├── pi/extensions/ Pi lifecycle probe
│ ├── pi-web-plugins/ model-probe, appliance-skin
│ └── project-template/ fixtures
├── deploy/docker/ pinned OCI image and Compose
├── scripts/ verifier, provenance, probes
└── tests/
The boundary that matters is inside apps/autofab-web: src/ is ours and upstream/ is not. Do not copy existing 3D-printing skill implementations into this repository unless packaging requires it; prefer installing or linking their canonical source.
npm --prefix apps/autofab-web install
npm --prefix apps/autofab-web run build # verifies vendored provenance, then builds
npm --prefix apps/autofab-web run serve # stock pi-web-server, custom clientDistnpm --prefix apps/autofab-web run sync:check fails if the vendored tree drifts from its recorded hash. Re-vendoring a new upstream release is node apps/autofab-web/scripts/sync-upstream.mjs --tag <version>; it aborts loudly if a patch no longer applies cleanly.
The first release succeeds when this can be done comfortably from a phone:
Open “Tablet Stand” → start a new chat → upload a photo → ask to move a support 3 mm → see that the agent is working → open the refreshed STL in Model → rotate and inspect it → request another change → save an approved checkpoint → ask the skills to slice it → explicitly confirm the physical print.
If that loop works reliably, the appliance is useful. Further UI polish should be driven by friction observed in that real workflow.