# StoredRun, LocalExperiment, and LocalProject Types in orx: A Complete Guide

> Explore StoredRun LocalExperiment and LocalProject types in orx for efficient local research artifact management. Understand their roles in persistence and organization.

- Repository: [alphaXiv/OpenResearch](https://github.com/alphaXiv/OpenResearch)
- Tags: how-to-guide
- Published: 2026-09-13

---

**The `orx` CLI relies on three distinct Rust types—`StoredRun` for SQLite persistence, `LocalExperiment` for runtime experiment metadata, and `LocalProject` for workspace organization—to manage research artefacts locally without requiring remote services.**

The `alphaXiv/OpenResearch` repository provides a local-first research execution framework where `StoredRun`, `LocalExperiment`, and `LocalProject` types form the backbone of state management. These structs separate persisted database records from in-memory workspace representations, enabling the CLI to query, create, and manipulate experiments consistently across local and synced environments.

## StoredRun: The SQLite Persistence Layer

### Definition and Location

The `StoredRun` struct is defined in [`src/store.rs`](https://github.com/alphaXiv/OpenResearch/blob/main/src/store.rs) at approximately line 202 and serves as the canonical database representation of an experiment execution. This type maps directly to SQLite rows and contains all fields necessary to reconstruct a run's state across CLI sessions.

### Core Fields

According to the source analysis, `StoredRun` includes the following fields:

```rust
pub struct StoredRun {
    pub id: String,
    pub experiment_id: String,
    pub project_id: String,
    pub status: String,
    pub start_ms: i64,
    pub end_ms: Option<i64>,
    pub backend_json: Option<String>,
    // ... additional optional fields
}

```

### Database Row Conversion

When fetching data from the SQLite store, `orx` uses the `row_to_run` helper function located around line 2960 in [`src/store.rs`](https://github.com/alphaXiv/OpenResearch/blob/main/src/store.rs). This function transforms database rows into `StoredRun` instances, handling the conversion of SQL types to Rust `String` and `i64` primitives. The store module also provides `upsert_run`, `get_run`, and `list_runs` methods for database operations.

## LocalExperiment: Lightweight In-Memory Views

### Purpose and Structure

`LocalExperiment` (commonly aliased as `Experiment` in the codebase) lives in [`src/local/mod.rs`](https://github.com/alphaXiv/OpenResearch/blob/main/src/local/mod.rs) and provides a lightweight, in-memory view of experiment metadata tailored for CLI operations. Unlike `StoredRun`, which focuses on execution state, `LocalExperiment` focuses on experiment configuration and metadata.

### Conversion from Persisted State

The bridge between the database layer and the local workspace is implemented through conversion traits. The `impl From<&StoredRun> for Run` (approximately line 16 in [`src/local/mod.rs`](https://github.com/alphaXiv/OpenResearch/blob/main/src/local/mod.rs)) extracts relevant fields from a `StoredRun` to populate the local `Run` struct. A similar pattern exists for experiments, allowing the CLI to enrich workspace file data with persisted execution history from the store.

## LocalProject: Workspace Project Organization

### Project Structure Definition

`LocalProject` (aliased as `Project`) is defined in [`src/local/projects.rs`](https://github.com/alphaXiv/OpenResearch/blob/main/src/local/projects.rs) and represents a project that groups related experiments and runs. In local mode, `orx` reads project definitions from workspace files (such as [`project.toml`](https://github.com/alphaXiv/OpenResearch/blob/main/project.toml)) and instantiates `LocalProject` structs to organize the CLI's view of the research workspace.

### Key Utility Functions

The [`src/local/projects.rs`](https://github.com/alphaXiv/OpenResearch/blob/main/src/local/projects.rs) module exposes several critical functions for project management:

- **`list_projects`** – Enumerates all projects in the local workspace
- **`resolve_project`** – Locates a specific project by identifier
- **`run_duration_secs`** – Computes execution durations using the `start_ms` and `end_ms` fields from associated runs

## Type Relationships and Data Flow

Understanding how these types interact requires examining the conversion pipeline implemented across the codebase:

1. **Persistence Layer** – `StoredRun`, `StoredExperiment`, and `StoredProject` reside in the SQLite database ([`src/store.rs`](https://github.com/alphaXiv/OpenResearch/blob/main/src/store.rs)) and serve as the source of truth for execution history
2. **Local Layer** – Conversion helpers in [`src/local/mod.rs`](https://github.com/alphaXiv/OpenResearch/blob/main/src/local/mod.rs) transform `&StoredRun` references into `Run` instances (public API types), while [`src/local/projects.rs`](https://github.com/alphaXiv/OpenResearch/blob/main/src/local/projects.rs) handles analogous transformations for projects
3. **API Layer** – The `impl From<&StoredRun> for ApiRun` conversion located around line 800 in [`src/commands/up.rs`](https://github.com/alphaXiv/OpenResearch/blob/main/src/commands/up.rs) prepares data for serialization, with [`src/plane.rs`](https://github.com/alphaXiv/OpenResearch/blob/main/src/plane.rs) containing the `Run` struct that bridges stored and API representations

## Practical Usage Examples

### Creating and Storing a New Run

```rust
use orx::store::Store;

let store = Store::open()?;
let new_run = StoredRun {
    id: uuid::Uuid::new_v4().to_string(),
    experiment_id: "exp-42".into(),
    project_id: "proj-alpha".into(),
    status: "pending".into(),
    start_ms: chrono::Utc::now().timestamp_millis(),
    end_ms: None,
    backend_json: None,
    // ... other optional fields
};
store.upsert_run(&new_run)?;

```

### Resolving Local Workspace Entities

```rust
// Resolve a specific run from the local workspace
let run_handle = orx::local::resolve::resolve_run(&store, "run-123")?;
println!("Run {} has status {} ", run_handle.id, run_handle.status);

// List all projects with their experiment counts
let projects = orx::local::projects::list_projects(&store)?;
for project in projects {
    println!("Project {} contains {} experiments", 
             project.name, 
             project.experiments.len());
}

```

### Command-Line Interface Operations

```bash

# Display run details (triggers StoredRun → Run conversion)

orx runs show <run-id>

# List experiments within a specific project

orx exp list --project <project-id>

# Create a new run (internally constructs StoredRun)

orx run create --experiment <exp-id> --backend docker

```

## Summary

- **`StoredRun`** is the authoritative database representation in [`src/store.rs`](https://github.com/alphaXiv/OpenResearch/blob/main/src/store.rs), containing execution state, timestamps, and backend configuration JSON for SQLite persistence
- **`LocalExperiment`** provides lightweight, in-memory experiment metadata in [`src/local/mod.rs`](https://github.com/alphaXiv/OpenResearch/blob/main/src/local/mod.rs), built from workspace files and enriched with stored execution data via `From` trait implementations
- **`LocalProject`** organizes experiments and runs in [`src/local/projects.rs`](https://github.com/alphaXiv/OpenResearch/blob/main/src/local/projects.rs), offering workspace-aware project resolution and duration calculations
- **Conversion helpers** in [`src/local/mod.rs`](https://github.com/alphaXiv/OpenResearch/blob/main/src/local/mod.rs) (line 16) and [`src/commands/up.rs`](https://github.com/alphaXiv/OpenResearch/blob/main/src/commands/up.rs) (line 800) bridge the gap between SQLite storage and API serialization

## Frequently Asked Questions

### What is the difference between StoredRun and LocalExperiment?

`StoredRun` represents a single execution instance persisted in SQLite with fields like `status`, `start_ms`, and `backend_json`, while `LocalExperiment` represents the experiment definition itself—containing metadata such as name and description—typically loaded from workspace configuration files and held in memory during CLI operations.

### Where does orx store the LocalProject configuration?

`LocalProject` configuration originates from workspace definition files (such as [`project.toml`](https://github.com/alphaXiv/OpenResearch/blob/main/project.toml)) in the user's working directory, then gets enriched with execution data from the SQLite store via the resolution functions in [`src/local/projects.rs`](https://github.com/alphaXiv/OpenResearch/blob/main/src/local/projects.rs).

### How does orx convert database rows into runtime types?

The `row_to_run` helper function in [`src/store.rs`](https://github.com/alphaXiv/OpenResearch/blob/main/src/store.rs) (around line 2960) converts SQLite rows into `StoredRun` structs, while conversion traits like `impl From<&StoredRun> for Run` in [`src/local/mod.rs`](https://github.com/alphaXiv/OpenResearch/blob/main/src/local/mod.rs) transform these stored types into local workspace representations used by the CLI.

### Can I access StoredRun directly without using the local type wrappers?

Yes, you can interact directly with `StoredRun` through the store module's public methods such as `upsert_run`, `get_run`, and `list_runs` defined in [`src/store.rs`](https://github.com/alphaXiv/OpenResearch/blob/main/src/store.rs), though the CLI typically prefers the `LocalExperiment` and `LocalProject` wrappers for workspace-aware operations that combine file-based configuration with database state.