Getting Started
Installation & Run

Installation & Run

Everything you need to set up Dexter and run the pipeline through the OpenCode TUI. Confirm Requirements first, missing Blender, API keys, or OpenCode auth will block specific steps.


Setup

Clone the repository

git clone https://github.com/aakashvarma/dexter.git
cd dexter

Install OpenCode

curl -fsSL https://opencode.ai/install | bash
opencode --version

Authenticate

opencode          # open the TUI
/connect          # authenticate at opencode.ai/auth

OpenCode slash commands including /connect and /init

Initialise the project

From the repo root inside OpenCode:

/init

This writes AGENTS.md: the agent-facing source of truth for pipeline semantics.

Install Python dependencies

pip install -r requirements.txt

Recommended with a virtual environment:

python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt

Install Blender

macOS: brew install --cask blender
Linux: sudo snap install blender --classic

Verify: blender --version

Set API keys

Add to ~/.zshrc or ~/.bashrc, then reload:

export OPENAI_API_KEY=sk-...   # component PNGs
export FAL_KEY=...             # image-to-3D GLBs

Verify installation

python3 -c "import fal_client, openai, jsonschema, yaml; print('Python OK')"
blender --background --version
test -n "$OPENAI_API_KEY" && echo "OpenAI OK"
test -n "$FAL_KEY" && echo "fal OK"
opencode --version && echo "OpenCode OK"

Blender not on PATH? Set the full path in configs/base.yaml under paths.blender_binary (see Optional settings below).


Run the pipeline (TUI)

Open OpenCode in the repo

cd /path/to/dexter
opencode

Select the orchestrator agent

Press Tab or type /agents, then choose orchestrator:

Select the orchestrator agent in OpenCode

Describe your task

Type a prompt in the chat. For a new asset:

build the dishwasher from input_images/dishwasher.png

The orchestrator copies the image to .intermediate/<asset>/<NNN>/source.png, picks the next run number, and drives the full pipeline.

Respond at human gates

The run pauses twice for your input, do not let the agent continue on its own:

GateWhenWhat to review
PartsAfter parts.jsonPart names, descriptions, joint types, sizes and poses
PlacementAfter the critic loopBest iteration renders, critic score, assembled.blend

Reply in the TUI when you are satisfied, or ask for edits before continuing.

πŸ’‘

Useful slash commands: /agents (switch agent) Β· /connect (re-authenticate) Β· /init (re-analyse project) Β· /new (fresh session)


Resume or continue a run

Point the orchestrator at an existing run directory. Type prompts like these in the TUI:

resume .intermediate/dishwasher/001/
parts confirmed, continue .intermediate/dishwasher/001/
run 3 more placement iterations for .intermediate/dishwasher/001/

The orchestrator lists .intermediate/<asset>/<NNN>/ before every step and skips outputs that already exist and validate. You can safely resume after an interruption or a human gate.


What the pipeline does

High-level flow (orchestrator-owned; two subagents handle analyze and critic):

  1. Analyze: source image β†’ parts.json
  2. Parts gate: you confirm the part list
  3. Components: generate_components.py β†’ PNGs, GLBs, component_dims.json
  4. Placement init: initialize_placement.py β†’ iterations/001/assembly.json (with pre-computed node_scale / node_origin)
  5. Placement ↔ critic loop: assemble β†’ render β†’ critique β†’ apply corrections until stop conditions hit
  6. Placement gate: you approve the best layout
  7. USD export: robot.usda + textures/ + robot_prim_map.json

Placement iterations are append-only. To tweak layout after the gate, start a new iteration through the critic loop, do not delete iterations/ or redo analyze/components.

Loop stops when any of: score β‰₯ loop.score_threshold (and N β‰₯ min_loops), N β‰₯ max_loops, or score has not improved for no_improvement_patience iterations. The best-scoring iteration is kept even if a later one regresses.


Run output

Every run writes to .intermediate/<asset>/<NNN>/ (gitignored):

.intermediate/<asset>/<NNN>/
β”œβ”€β”€ source.png
β”œβ”€β”€ parts.json
β”œβ”€β”€ component_dims.json
β”œβ”€β”€ component_images/
β”œβ”€β”€ component_glbs/
β”œβ”€β”€ iterations/
β”‚   └── NNN/
β”‚       β”œβ”€β”€ assembly.json
β”‚       β”œβ”€β”€ assembled.blend
β”‚       β”œβ”€β”€ render_views.json
β”‚       β”œβ”€β”€ renders/          # front, top, left, isometric
β”‚       └── critic.json
β”œβ”€β”€ robot.usda                # final deliverable
β”œβ”€β”€ robot_prim_map.json
└── textures/
PatternExampleMeaning
<asset>dishwasherFrom parts.json β†’ object
<NNN>001Zero-padded run number

Optional settings

All knobs live in configs/base.yaml (opens in a new tab). Defaults work for a first run: only change these when you have a specific reason.

Loop behaviour (loop in configs/base.yaml)

KeyDefaultWhat it does
min_loops1Minimum placement ↔ critic rounds
max_loops5Hard cap on iterations
score_threshold85Stop when critic score reaches this (and N β‰₯ min_loops)
no_improvement_patience2Stop after this many iterations with no score improvement

Faster iteration: lower max_loops to 3. Higher quality: raise max_loops to 8 and score_threshold to 90.

Component images (image_generation)

Controls OpenAI image generation in generate_components.py. Paths are relative to <run_dir>/.

KeyDefaultWhat it does
modelgpt-image-2Image model (dall-e-3 also supported)
size1024x1024Output resolution
qualitymediumlow / medium / high: lower saves cost
background_instructionwhite background textAppended to every part prompt

Cheaper runs: set quality: "low".

3D meshes (fal)

Controls fal.ai image-to-3D in generate_components.py.

KeyDefaultWhat it does
endpointfal-ai/hunyuan-3d/v3.1/pro/image-to-3dfal.ai model
face_count40000Target mesh density
enable_pbrtruePBR materials on GLBs
download_timeout_seconds300GLB download timeout

Render quality (render)

Defaults the orchestrator uses when writing render_views.json each iteration.

KeyDefaultWhat it does
resolution[1920, 1080]Render size in pixels
samples64Cycles samples (higher = slower, cleaner)
engineCYCLESBlender render engine

Faster previews: [1280, 720] resolution and samples: 32.

Paths (paths)

KeyDefaultWhat it does
blender_binaryblenderBlender executable, set full path if not on PATH
input_dirinput_imagesBundled source photos
intermediate_root.intermediateRun output root

USD export (usd)

KeyDefaultWhat it does
root_prim_path/World/RobotRoot prim path in robot.usda for Isaac Sim
⚠️

Agent permissions live in opencode.json, not base.yaml. Subagent prompts are under .opencode/agents/. Change these only when extending the pipeline, see Extending the Pipeline.


Troubleshooting setup

ProblemFix
blender: command not foundInstall Blender or set paths.blender_binary in configs/base.yaml
ModuleNotFoundError: fal_clientpip install -r requirements.txt in your active venv
OpenCode /connect failsCheck network; try npm install -g opencode-ai
Blender hangs on first runNormal on macOS, grant permissions in System Settings

Next steps

TopicPage
End-to-end walkthrough with example outputsSample Run: Dishwasher
Pipeline stages and loop logicAgentic Loop
Common failures during a runTroubleshooting