This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
This is a Python-based command-line utility system that provides standardized scripts for DAZ Studio (3D rendering software). It acts as a bridge between Python CLI interfaces and DAZ Studio's scripting language (DSA - DAZ Script).
# Install in editable/development mode (recommended)
pip install -e .
# Install with dev dependencies (includes pytest, coverage, etc.)
pip install -e ".[dev]"This creates console scripts: vangard, vangard-cli, vangard-interactive, vangard-server, vangard-gui, vangard-pro
# Run all tests (excludes e2e and manual by default)
pytest tests/
# Run specific test categories using markers
pytest tests/ -m unit # Fast unit tests only
pytest tests/ -m integration # Integration tests
pytest tests/ -m command # Individual command tests
pytest tests/ -m "not slow" # Exclude slow tests
# Run tests in a specific directory
pytest tests/commands/ # All command tests (137 tests)
pytest tests/unit/ # Unit tests (39 tests)
pytest tests/integration/ # Integration tests (8 tests)
# Run a single test file
pytest tests/unit/test_framework.py
# Run a specific test function
pytest tests/unit/test_framework.py::test_load_config
# Run with verbose output and coverage
pytest tests/ -v --cov=vangard --cov=core --cov-report=htmlTest Markers: The project uses pytest markers for test organization:
unit: Fast tests with no external dependenciesintegration: Integration tests (no DAZ required)command: Individual command testscontract: Contract/interface testse2e: End-to-end tests (require DAZ Studio - not run by default)manual: Manual tests (documentation only - not run by default)slow: Time-consuming tests
# Check for syntax errors and undefined names (strict)
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
# Full style check (non-blocking)
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
# Code quality analysis
pylint core/ vangard/ --exit-zero# Regenerate config_reference.md from config.yaml
python generate_docs.pyNote: The script generates config_reference.md, not ARGS.md. Both files may exist but config_reference.md is the auto-generated one.
-
Configuration-Driven System (
config.yaml)- Central YAML file defines all available commands, their arguments, and which Python classes handle them
- Commands are dynamically loaded and parsed at runtime
- Each command specifies: name, Python class path, help text, and argument definitions
-
Core Framework (
core/framework.py)load_config(): Loads config.yamlbuild_parser(): Dynamically builds argparse parser from configload_class(): Dynamically imports command classes using string pathsrun_command(): Instantiates command class and executes it
-
Command System
- Python Commands (
vangard/commands/): Python classes that inherit fromBaseCommand - DSA Scripts (
vangard/scripts/): Corresponding DAZ Studio scripts (.dsafiles) - Flow: User invokes Python command → Command class processes args → Launches DAZ Studio with .dsa script
- Python Commands (
-
Multiple Interface Modes (selected via
main.py)- CLI (
cli.py): Standard command-line execution - Interactive (
interactive.py): Shell with prompt-toolkit, command completion, and history - Server (
server.py): FastAPI web server with dynamically generated REST endpoints - GUI (
gui.py): Simple graphical interface - Pro (
pro.py): Modern web interface with dark theme, dynamic forms, and real-time feedback
- CLI (
- User runs command via any interface:
vangard-cli [command] [args]orpython -m vangard.cli [command] [args] - Interface layer (
cli.py,interactive.py,server.py,gui.py, orpro.py) loads config and builds parser - Parser identifies command and its associated Python class from
config.yaml - Command class instantiated,
process()method called BaseCommand.exec_remote_script()determines execution mode:- Subprocess mode (default): Spawns DAZ Studio with script path and JSON args via
-scriptArg - Server mode: Sends POST request to DAZ Script Server plugin at
/executeendpoint
- Subprocess mode (default): Spawns DAZ Studio with script path and JSON args via
- DAZ Studio executes the .dsa script with provided arguments
tests/
├── commands/ # 137 tests - One test file per command class
├── unit/ # 39 tests - Core framework and utility tests
├── integration/ # 8 tests - Cross-component integration tests
├── contract/ # Contract/interface tests
├── e2e/ # End-to-end tests (require DAZ Studio)
├── manual/ # Manual test documentation
├── fixtures/ # Shared test fixtures
└── conftest.py # Pytest configuration and shared fixtures
The test suite totals 179 automated tests. E2E and manual tests are excluded from default runs.
BaseCommand (vangard/commands/BaseCommand.py)
- All command classes inherit from this abstract base class
__init__(parser, config): Initializes with optional parser and config referencesprocess(args): Main execution method that subclasses can override for custom behavior. Default implementation callsexec_default_script()exec_default_script(args): Convenience method that callsexec_remote_script()with a script name matching the class nameexec_remote_script(script_name, script_vars, daz_command_line): Static method that executes scripts via subprocess or DAZ Script Server based onDAZ_SCRIPT_SERVER_ENABLEDenvironment variableto_dict(args, exclude): Static method that converts argparse.Namespace to dict, automatically excluding framework keys ('command', 'class_to_run')
Important: When creating a new command, you typically only need to create the class and the .dsa script. The default process() implementation handles everything unless you need custom Python-side logic.
Required environment variables (typically in .env file):
Subprocess Mode (Default):
DAZ_ROOT: Absolute path to DAZ Studio executable- Windows:
C:/Program Files/DAZ 3D/DAZStudio4/DAZStudio.exe - macOS:
/Applications/DAZ 3D/DAZStudio4 64-bit/DAZStudio.app/Contents/MacOS/DAZStudio
- Windows:
DAZ_ARGS: Optional additional arguments for DAZ Studio
DAZ Script Server Mode (Optional):
DAZ_SCRIPT_SERVER_ENABLED: Set totrueto enable server mode (default:false)DAZ_SCRIPT_SERVER_HOST: Server host (default:127.0.0.1)DAZ_SCRIPT_SERVER_PORT: Server port (default:18811)
Note: DAZ Script Server is a separate plugin available at https://github.com/bluemoonfoundry/vangard-daz-script-server. When enabled, commands are sent as POST requests to http://<host>:<port>/execute with JSON payload containing scriptFile (absolute path) and args (JSON object) instead of spawning DAZ Studio subprocesses.
After installing with pip install -e ., use the console scripts:
# CLI mode (two equivalent ways)
vangard-cli [command] [args]
vangard cli [command] [args]
# Interactive shell
vangard-interactive
vangard interactive
# FastAPI server (runs on http://127.0.0.1:8000)
vangard-server
vangard server
# GUI mode
vangard-gui
vangard gui
# Pro Mode - modern web interface (runs on http://127.0.0.1:8000)
vangard-pro
vangard proAlternative (without installation):
python -m vangard.cli [command] [args]
python -m vangard.interactive
python -m vangard.server
python -m vangard.gui
python -m vangard.pro
# or
python -m vangard.main cli [command] [args]-
Add command definition to
config.yaml:- name: "my-command" class: "vangard.commands.MyCommandSU.MyCommandSU" help: "Description of what the command does" arguments: - names: ["required_arg"] dest: "required_arg" type: "str" required: true help: "Description of argument"
-
Create Python command class in
vangard/commands/MyCommandSU.py:from vangard.commands.BaseCommand import BaseCommand class MyCommandSU(BaseCommand): # Default behavior: calls MyCommandSU.dsa script # Override process() if custom behavior needed pass
-
Create corresponding DAZ Studio script in
vangard/scripts/MyCommandSU.dsa- Include
DazCopilotUtils.dsaat the top of your script for utility functions - Use
init_script_utils(sFunctionName)to parse incoming JSON args - Access args via
oScriptVars['arg_name'] - Use
log_success_event()andlog_failure_event()for consistent logging - Call
close_script_utils()at the end to clean up - Additional shared DSA utility libraries available to include:
DazCameraUtils.dsa,DazCoreUtils.dsa,DazFileUtils.dsa,DazLoggingUtils.dsa,DazNodeUtils.dsa,DazRenderUtils.dsa,DazStringUtils.dsa,DazTransformUtils.dsa
- Include
-
Regenerate documentation:
python generate_docs.py
This updates
config_reference.mdwith the new command information.
- Python command classes:
CommandNameSU(suffix "SU" for Script Utility) - DSA script files:
CommandNameSU.dsa(matches class name) - CLI command names: Use kebab-case (e.g.,
load-scene,batch-render)
Pro mode serves static files from vangard/static/:
index.html: Main Pro interfacecss/styles.css: Styling and theme definitionsjs/app.js: Frontend JavaScript, including command icons and form generation
These files are automatically included via package_data in setup.py and served by vangard/pro.py using FastAPI's static file mounting. To customize the Pro interface appearance or add command icons, edit these files. See PRO_MODE.md for detailed customization instructions.
Prefer these fixtures over manual @mock.patch in command tests:
mock_daz_execution— patchesBaseCommand.exec_remote_script, yields the mock directlysample_config— loads actualconfig.yamltemp_env/clean_env— sets/clears DAZ environment variablesmock_parser— provides a mockArgumentParser
Test assets located in test/ directory include:
CubeTestScene.duf: Test scene fileCubeTestScene_Camera*.png: Expected render outputs
See the "Common Development Commands" section above for test execution commands.