# How OpenLogi Isolates Development and Production Configurations

> Discover how OpenLogi isolates development and production configurations using a profile-based system. Learn how distinct environments ensure complete runtime separation for your applications.

- Repository: [Xuan Zhang/OpenLogi](https://github.com/AprilNEA/OpenLogi)
- Tags: internals
- Published: 2026-08-21

---

**TLDR:** OpenLogi separates development and production instances using a **profile-based isolation system** where the `OPENLOGI_PROFILE` environment variable or binary name determines distinct configuration directories, IPC sockets, and data paths, ensuring complete runtime separation between environments.

OpenLogi employs a robust profile architecture to prevent configuration collisions between development and production builds. By deriving a profile identifier from the binary name or environment variables, the application directs all file system operations—configs, caches, and IPC sockets—to isolated subdirectories. This design allows developers to run unstable dev builds alongside stable production releases without interference.

## Profile Selection at Runtime

The isolation mechanism begins at process startup. According to the build scripts in [`xtask/src/commands/macos/dev_bundle.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/xtask/src/commands/macos/dev_bundle.rs), OpenLogi determines the active profile through the `Profile` struct, which inspects the binary name or the `OPENLOGI_PROFILE` environment variable.

- **Production profile**: Defaults to `"openlogi"`
- **Development profile**: Uses `"openlogi-dev"` when running the dev bundle

The profile resolution logic appears in the dev bundle builder:

```rust
let profile = Profile::of(&args.binary)?; // determines "openlogi" or "openlogi-dev"
let config_dir = profile.config_dir();    // e.g., ~/.config/openlogi-dev/

```

Once determined, the profile propagates through the `openlogi_core::paths` module, influencing every path resolution across the application.

## Configuration Directory Isolation

In [`crates/openlogi-core/src/paths.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/paths.rs), the `config_dir()` function resolves paths by appending the active profile to the base configuration directory. This ensures production configurations live in `~/.config/openlogi/` while development instances use `~/.config/openlogi-dev/`.

The agent overlay implementation in [`crates/openlogi-agent/src/overlay.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-agent/src/overlay.rs) demonstrates this resolution with strict error handling:

```rust
let Ok(directory) = openlogi_core::paths::config_dir() else {
    // Fallback: abort if the profile cannot be resolved
    return Err(...);
};
// All agent state (profiles, lighting config) is read from `directory`

```

All UI-related configuration files—including [`config.toml`](https://github.com/AprilNEA/OpenLogi/blob/main/config.toml), per-app profiles, and camera snapshots—reside under this profile-scoped directory.

## IPC Socket Path Segregation

Inter-process communication sockets are strictly isolated by profile. The `agent_socket_path()` function in [`crates/openlogi-ipc/src/transport.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-ipc/src/transport.rs) incorporates the profile into the socket path, preventing cross-environment communication.

```rust
let socket_path = openlogi_core::paths::agent_socket_path()?;

```

This resolves to:
- **Production**: `~/.config/openlogi/agent.sock`
- **Development**: `~/.config/openlogi-dev/agent.sock`

This guarantees that a development agent cannot accidentally bind to or claim the production socket, eliminating the risk of cross-environment interference or permission conflicts.

## Data and Cache Isolation

The same profile prefix applies to data and cache directories via `data_dir()` and `cache_dir()` functions in `openlogi_core::paths`. All generated assets, logs, and temporary files remain scoped to their respective profiles, ensuring that development artifacts never corrupt production state or consume production storage quotas.

## macOS Bundle-Level Segregation

For macOS distributions, the dev build embeds the profile directly into the bundle metadata. The [`xtask/src/commands/macos/bundle/identity.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/xtask/src/commands/macos/bundle/identity.rs) logic sets distinct bundle identifiers based on the active profile. This ensures that macOS TCC (Transparency, Consent, and Control) permissions, camera access approvals, and other sandboxed resources are keyed specifically to either the production or development profile, preventing permission leakage between environments.

## Summary

- **Profile-driven paths**: All file system operations in `openlogi_core::paths` prefix the active profile to config, data, cache, and socket locations
- **Environment-based detection**: The profile derives from `OPENLOGI_PROFILE` or the binary name (e.g., `openlogi` vs `openlogi-dev`)
- **Socket isolation**: IPC endpoints use profile-specific paths to prevent cross-environment communication
- **macOS integration**: Bundle identifiers and sandbox permissions are profile-scoped via `xtask` build scripts in [`dev_bundle.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/dev_bundle.rs) and [`identity.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/identity.rs)

## Frequently Asked Questions

### What environment variable controls the OpenLogi profile?

The `OPENLOGI_PROFILE` environment variable determines the active configuration profile. When unset, the system derives the profile from the binary name—`"openlogi"` for production builds and `"openlogi-dev"` for development bundles—as implemented in the `Profile::of` logic within [`xtask/src/commands/macos/dev_bundle.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/xtask/src/commands/macos/dev_bundle.rs).

### Where does OpenLogi store configuration files for development builds?

Development configurations reside in `$XDG_CONFIG_HOME/openlogi-dev/` (typically `~/.config/openlogi-dev/` on Linux/macOS). The `config_dir()` function in [`crates/openlogi-core/src/paths.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/paths.rs) automatically appends the profile name to the base configuration path, ensuring complete directory isolation.

### How does OpenLogi prevent development and production agents from conflicting?

The IPC transport layer uses profile-specific socket paths via `agent_socket_path()` in [`crates/openlogi-ipc/src/transport.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-ipc/src/transport.rs). Production agents bind to `~/.config/openlogi/agent.sock` while development agents use `~/.config/openlogi-dev/agent.sock`, ensuring complete socket isolation and preventing one instance from intercepting another's messages.

### Can I run development and production instances simultaneously?

Yes. Because OpenLogi isolates configuration directories, IPC sockets, and cache paths by profile, you can run both instances concurrently without risk of configuration corruption or socket contention. The macOS bundle system further ensures distinct sandbox identities for each profile via [`xtask/src/commands/macos/bundle/identity.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/xtask/src/commands/macos/bundle/identity.rs).