Query, view, export, and diff stored configs and josh sources
Introduction
Every run registered in a joshpy registry stores its rendered config (.jshc) and josh source (.josh) content. The joshpy.inspect module lets you view, export, and diff these stored files – even after the original files have been modified or deleted.
This is useful for:
Discovering what’s in a registry: List labels, sessions, and run details from the terminal
Comparing runs: See exactly what changed between two parameter configurations
Debugging failures: Inspect the config and model source for a failed run
Auditing: Verify what was actually run, not what’s currently on disk
Setup
from joshpy.registry import RunRegistryfrom joshpy.jobs import JobConfigregistry = RunRegistry(":memory:")session_id = registry.create_session( config=JobConfig(simulation="Main"), experiment_name="inspect_demo",)# Register two runs with different configs and the same josh sourcejosh_source ="""\start simulation Main grid.size = 30 m grid.low = 33.9 degrees latitude, -116.05 degrees longitude grid.high = 33.91 degrees latitude, -116.04 degrees longitude steps.low = 0 count steps.high = 86 countend simulationstart patch Default Tree.init = create 10 count of Tree export.treeCount.step = count(Tree) export.averageHeight.step = mean(Tree.height)end patchstart organism Tree age.init = 0 years age.step = prior.age + 1 year height.init = 0 meters height.step = prior.height + sample uniform from 0 meters to config sweep_config.maxGrowthend organism"""registry.register_run( session_id=session_id, run_hash="abc123def456", josh_path="model.josh", josh_content=josh_source, config_content="maxGrowth = 5 meters\nfireYear = 75 count", file_mappings={"soil_quality": {"path": "data/soil_quality.jshd", "hash": "a1b2c3"}, }, parameters={"maxGrowth": 5, "fireYear": 75},)registry.label_run("abc123def456", "low_growth")registry.register_run( session_id=session_id, run_hash="fed987cba654", josh_path="model.josh", josh_content=josh_source, config_content="maxGrowth = 15 meters\nfireYear = 75 count", file_mappings={"soil_quality": {"path": "data/soil_quality.jshd", "hash": "a1b2c3"}, }, parameters={"maxGrowth": 15, "fireYear": 75},)registry.label_run("fed987cba654", "high_growth")# Record completed runs (3 replicates each)for run_hash in ["abc123def456", "fed987cba654"]:for rep inrange(3): run_id = registry.start_run( run_hash=run_hash, session_id=session_id, replicate=rep, output_path=f"output/{run_hash}/rep{rep}.csv", ) registry.complete_run(run_id, exit_code=0)registry.update_session_status(session_id, "completed")print(f"Registered 2 runs: low_growth, high_growth")
Registered 2 runs: low_growth, high_growth
Querying the Registry
Before viewing or diffing runs, you often need to know what’s in the registry. The joshpy.inspect module provides four query utilities that work from both Python and the command line – no interactive session required.
Listing Labels
Labels are the human-readable names assigned to run configurations. Use format_labels() to see what’s available:
from joshpy.inspect import format_labelsprint(format_labels(registry))
All four queries are available as CLI flags, so you can inspect a registry without writing any Python:
# List all labeled runspython-m joshpy.inspect experiment.duckdb --labels# List sessions with status and run countspython-m joshpy.inspect experiment.duckdb --sessions# Show full details for a run (by label or hash)python-m joshpy.inspect experiment.duckdb --info low_growth# Print a data summary for the whole registrypython-m joshpy.inspect experiment.duckdb --summary
Tip
Use --labels first to discover what labels are available, then --info or --diff to dig deeper.
Note
For debug logs tied to a registered run, use the debug CLI in registry mode:
# READ-ONLY snapshot exported from registry
# Run: abc123def456
# Editing this file has no effect. To change parameters,
# edit your source .jshc file and re-run.
maxGrowth = 5 meters
fireYear = 75 count
Or use view_config() to get the content as a string without writing a file:
from joshpy.inspect import view_configcontent = view_config(registry, "high_growth")print(content)
maxGrowth = 15 meters
fireYear = 75 count
Diffing Two Configs
Export both configs and compare them side by side:
# READ-ONLY snapshot exported from registry
# Run: abc123def456
# Editing this file has no effect. To change parameters,
# edit your source .jshc file and re-run.
maxGrowth = 5 meters
fireYear = 75 count
print(f"--- {path2.name} ---")
--- high_growth.jshc ---
print(path2.read_text())
# READ-ONLY snapshot exported from registry
# Run: fed987cba654
# Editing this file has no effect. To change parameters,
# edit your source .jshc file and re-run.
maxGrowth = 15 meters
fireYear = 75 count
To open an interactive diff in VS Code or Cursor:
# Opens side-by-side diff in VS Coderegistry.compare_configs("low_growth", "high_growth")# Or with Cursorregistry.compare_configs("low_growth", "high_growth", ide="cursor")
Viewing Josh Sources
The same workflow applies to the stored josh simulation source. This is especially useful when the original .josh file was rendered from a .josh.j2 template – the temp file is deleted after the sweep, but the content lives on in the registry.
from joshpy.inspect import view_joshsource = view_josh(registry, "low_growth")print(source[:200], "...")
# Opens side-by-side diff of josh sources in VS Coderegistry.compare_josh("low_growth", "high_growth")
Note
If both runs used the same josh source (common when only config parameters vary), the diff will show identical files. This confirms that only the config changed between runs.
Command-Line Interface
The python -m joshpy.inspect CLI provides the same functionality from the terminal, without writing Python.