Skip to content

Configuration

Marko Koljancic edited this page May 25, 2026 · 5 revisions

Home

Configuration

Solarxy reads two separate configuration files. They do different jobs and live in different places:

File Scope Lives in Edited by
solarxy.toml Per-project policy - validation rules, triangle budgets, filename classification, review sidecar location Your repository (checked into version control) Hand-written; shared by the whole team
config.toml Per-user preferences - window size, theme, default view settings, recent files, dock layout A per-OS application-data directory The GUI (sidebar + Preferences modal); hand-editing optional

Project configuration: solarxy.toml

solarxy.toml is the per-project policy file. It controls validation - which checks run, the numeric thresholds they use, the per-category triangle budgets, and how a model's filename maps to a budget category. Studios check it into version control so every developer, and every CI run, validates against the same gates.

It is read by:

  • solarxy-cli --mode analyze (single-file analysis and the interactive TUI)
  • solarxy-cli --mode analyze --paths … (batch validation - see CI/CD Integration)
  • The GUI's validation overlay (Shift+V) and the Properties panel's Validation section

A solarxy.toml is entirely optional. With no config file present, Solarxy uses the built-in defaults documented below.

Discovery order

When you don't pass --config <PATH> explicitly, Solarxy searches for a solarxy.toml in this order:

  1. --config <PATH> - an explicit path. Errors if the file is missing.
  2. $SOLARXY_CONFIG environment variable - an absolute or relative path. Errors if the file is missing.
  3. solarxy.toml in the start directory.
  4. Walk parent directories from the start directory upward until one contains a .git/ directory (the repository root) or the filesystem root is reached - capped at 20 levels so the search stays bounded on large monorepos.
  5. If nothing is found, the built-in ProjectConfig defaults are used.

The start directory depends on how Solarxy was invoked:

Invocation Start directory
solarxy-cli --mode analyze -m <model> (single file) The model file's parent directory
solarxy-cli --mode analyze --paths … (batch validation) The current working directory

For batch validation, run solarxy-cli from your repository root (or pass --config) so discovery resolves the config you expect.

The resolved config path and a SHA-256 of its bytes are recorded in the batch validation run report, so you can prove exactly which policy validated which assets.

Editor schema support

A JSON Schema for solarxy.toml ships in the repo at schemas/solarxy-config.v1.json. Editors that honour $schema (VS Code with Even Better TOML, JetBrains IDEs, taplo) give you autocomplete and inline error highlighting. Add this as the first non-blank line of your solarxy.toml:

#:schema https://raw.githubusercontent.com/marko-koljancic/solarxy/main/schemas/solarxy-config.v1.json

The schema is generated from the canonical Rust types via schemars; regeneration steps are in schemas/README.md.

Annotated example

Every section is optional - omit any section or key and its defaults apply.

#:schema https://raw.githubusercontent.com/marko-koljancic/solarxy/main/schemas/solarxy-config.v1.json

format_version = 1

# Per-category triangle budgets. A model is classified into one category
# (see [[filenames.rules]] below) and checked against that budget.
[budgets]
hero        = 100000
prop        = 20000
environment = 50000
default     = 30000

# Per-check toggles. All default to true except allow_open_mesh.
[validation]
normal_mismatch      = true
flipped_normals      = true
non_manifold_edges   = true
triangle_budget      = true
allow_open_mesh      = false   # inverse modifier - see the table below
degenerate_triangles = true
material_refs        = true
uv_presence          = true
index_buffer         = true

# Numeric knobs read by some checks.
[thresholds]
triangle_budget_tolerance_percent = 20.0
flipped_normal_dot                = -0.5

# Map filename patterns to budget categories. First matching rule wins;
# unmatched files fall back to the `default` category.
[[filenames.rules]]
pattern  = "^hero_"
category = "hero"

[[filenames.rules]]
pattern  = "^env_"
category = "environment"

# Project-level review-system settings.
[review]
sidecar_dir = ".solarxy"

solarxy.toml field reference

Section / key Type Default Purpose
format_version integer 1 Schema version. A config written by a newer Solarxy than the one reading it loads on a best-effort basis with a tracing::warn!.
[budgets] table - Per-category triangle budgets.
budgets.hero integer 100000 Budget for hero-category assets.
budgets.prop integer 20000 Budget for prop-category assets.
budgets.environment integer 50000 Budget for environment-category assets.
budgets.default integer 30000 Budget for assets that match no [[filenames.rules]].
[validation] table - Per-check on/off toggles - see Validation checks.
[thresholds] table - Numeric knobs for the checks that take one.
thresholds.triangle_budget_tolerance_percent float 20.0 The warning-to-error boundary for triangle_budget: any triangle count over budget warns; a count above budget × (1 + tolerance%) is an error.
thresholds.flipped_normal_dot float -0.5 Dot-product cutoff for the flipped_normals check - a triangle is flagged when its averaged vertex normal dots below this value against the geometric (winding-derived) normal.
[[filenames.rules]] array of tables empty Ordered regex rules. Each rule has pattern (a regex matched against the filename only, not the full path) and category (hero, prop, environment, or default). First match wins.
[review] table - Project-level Review System settings.
review.sidecar_dir string (none) Override directory for .solarxy-review.json sidecars. A relative path resolves against the model's parent directory; an absolute path is used as-is. When unset, sidecars sit next to their model.

Validation checks

The [validation] table toggles nine checks. The analyzer, the batch validator (--paths), and the GUI's Shift+V overlay all share this set. All are on by default except allow_open_mesh. Each row notes the issue severity it raises - Error or Warning.

Toggle Default What it flags
normal_mismatch on Error - a mesh declares per-vertex normals but the normal count does not match the vertex count.
flipped_normals on Warning - a triangle's averaged vertex normal points away from its geometric (winding-derived) normal, below the thresholds.flipped_normal_dot cutoff. Catches reversed normals left after a mirror modifier.
non_manifold_edges on Error / Warning - edges shared by 3+ triangles (error), and - unless allow_open_mesh is set - boundary/open edges with a single adjacent face (warning).
triangle_budget on Warning / Error - the model's total triangle count exceeds the per-category [budgets] value: a warning over budget, an error past the tolerance band (thresholds.triangle_budget_tolerance_percent).
allow_open_mesh off Modifier (not a check) - when true, suppresses the boundary/open-edge warning from non_manifold_edges so deliberately unsealed assets don't trip CI gates.
degenerate_triangles on Warning - triangles with near-zero area (collinear or coincident vertices).
material_refs on Error - a mesh's material index points to a slot beyond the model's material list.
uv_presence on Warning - a UV-coordinate count that doesn't match the vertex count (any format), or missing UVs entirely. The missing-UV check runs for OBJ / glTF / GLB only - STL and PLY are exempt.
index_buffer on Error - an empty index buffer, or an index count not divisible by three (a non-triangulated mesh).

Strict parsing

solarxy.toml is parsed strictly - every section uses deny_unknown_fields. A typo doesn't get silently ignored; it hard-fails with a line and column reference. When the unknown key is close to a real one (Jaro-Winkler similarity ≥ 0.75), the error includes a "did you mean?" suggestion:

solarxy.toml:14:5: unknown field `flipped_normal_dott` (did you mean 'flipped_normal_dot'?)

This catches mistakes at load time rather than letting a misspelled rule quietly do nothing.


User preferences: config.toml

config.toml holds per-user GUI preferences: window size, MSAA, theme, the default view/render/lighting settings, recent files, the dock layout, and review-author identity. It is personal - not checked into version control, not shared.

You rarely need to edit this file by hand; the GUI manages it. It is documented here for completeness and for the occasional manual fix.

Where it lives

The path follows each platform's standard application-data convention:

OS Path
macOS ~/Library/Application Support/solarxy/config.toml
Linux ~/.config/solarxy/config.toml
Windows %APPDATA%\solarxy\config.toml (typically C:\Users\<User>\AppData\Roaming\solarxy\config.toml)

The Preferences modal's Startup tab displays the exact path and has an Open config file button that opens it in your default editor.

How to edit it

Three surfaces write to config.toml, each authoritative for a different slice (see the User Guide for the full breakdown):

  1. The sidebar + Edit → Save View Settings as Default. Tune display, rendering, post-processing and lighting live, then persist the current state as the launch default from the Edit menu.
  2. The Preferences modal (Edit → Preferences…, Ctrl/⌘+,) - startup-only fields (window size, MSAA), the theme, custom backgrounds, the reviewer name, recent-files capacity, and updater behaviour.
  3. Direct TOML editing - open the file from the Preferences modal's Startup tab and edit it in any text editor.

config.toml section reference

config.toml mirrors the Preferences struct. Every section is optional - omitting one fills it from defaults.

Section Holds
config_version Schema version (currently 1); reserved for future migrations.
[display] Background, view mode, normals mode, grid / axis-gizmo / local-axes toggles, bloom & SSAO toggles, IBL mode, tone-mapping mode, exposure, turntable state + RPM, inspection mode, and the texel-density target.
[rendering] Wireframe line weight, MSAA sample count (1, 2, or 4; default 4), shadow map size (default 2048).
[lighting] Light-lock state.
[window] Window width (640-7680, default 1280) and height (480-4320, default 720). Clamped to range on load.
[history] recent_files - the recent-files list, capped by ui.max_recent_files.
[ui] max_recent_files (default 20, hard cap 50), status_bar_visible (default true), theme (Ayu Mirage Dark or Ayu Mirage Light).
[updater] check_on_launch (default false), channel (Stable or Prerelease).
[review] author - the display name written onto new review annotations; unset ⇒ anonymous. panel_open - whether the Review Panel is open at launch.
[dock] last_layout_json (the dock layout auto-saved on quit) and saved_layout_json (the snapshot written by Layout → Save Layout). Both are JSON-serialized egui_dock states.
[view] custom_backgrounds - your user-defined background registry - plus next_custom_id, the id allocator.

Robustness

config.toml is forgiving - unlike solarxy.toml, it does not use strict parsing:

  • Every section is optional. Older config files upgrade cleanly when a new Solarxy version adds a section.
  • Unknown fields and unknown sections are ignored (forward-compatible) - a config written by a newer Solarxy loads without error in an older build.
  • An invalid rendering.msaa_sample_count (anything other than 1, 2, or 4) is rejected with a tracing::warn! and falls back to 4.
  • Window dimensions are clamped to the supported range on load.
  • Corrupt TOML triggers a tracing::warn! and the whole file falls back to defaults - the file is not overwritten until you explicitly save.
  • A corrupt or schema-incompatible [dock] layout blob falls back silently to the default layout (with a tracing::debug! line); the rest of preferences load normally.

To reset everything, delete config.toml - Solarxy recreates it on the next save. See Troubleshooting → Config reset.


See also: CLI Reference · CI/CD Integration · Review System · User Guide · Troubleshooting

Clone this wiki locally