# How OpenLogi Uses `-dev` Identifiers to Isolate the Development Bundle from Production

> Learn how OpenLogi uses the -dev identifier to keep development bundles separate from production configurations, ensuring distinct bundle IDs, socket paths, and Launch Service registrations.

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

---

**OpenLogi isolates its development bundle from production by hard-coding the `Channel::Dev` identifier throughout the build process, ensuring separate bundle IDs, socket paths, and Launch Service registrations.**

The AprilNEA/OpenLogi repository maintains two distinct macOS application bundles: a production release (`OpenLogi.app`) and a sandboxed development version (`OpenLogi-dev.app`). By systematically applying `-dev` identifiers across the build pipeline in [`xtask/src/commands/macos/dev_bundle.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/xtask/src/commands/macos/dev_bundle.rs), the development bundle achieves complete runtime isolation, preventing configuration leakage and socket conflicts with production instances.

## Channel-Based Isolation Architecture

The isolation mechanism centers on the `Channel` enum, with the development bundle explicitly selecting `Channel::Dev` to propagate dev-specific metadata through every build stage.

### Hard-Coded Dev Channel Selection

In [`xtask/src/commands/macos/dev_bundle.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/xtask/src/commands/macos/dev_bundle.rs), the `macos::dev_bundle` command explicitly instantiates the channel as `Channel::Dev` at lines 34-36. This constant propagates through all subsequent build steps, ensuring that the main application, embedded agents, and overlay helpers receive consistent dev-specific stamping.

### Bundle Identifier Stamping

The `identity::stamp(&app, CHANNEL, components)` function (lines 102-105 of [`dev_bundle.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/dev_bundle.rs)) writes the final bundle identifier into each component’s `Info.plist`. When `CHANNEL` is `Dev`, the resulting identifier becomes `org.openlogi.openlogi-dev` rather than the production `org.openlogi.openlogi`, creating distinct macOS application identities that the system treats as separate entities.

## File System and Socket Isolation

Physical separation on disk prevents accidental data sharing between environments by using dedicated directory constants.

### Dedicated Development Directory

The core crate defines `DEV_APP_DIR` as `"openlogi-dev"` in [`crates/openlogi-core/src/paths.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/paths.rs) (lines 40-42). This constant serves as the root directory for all development-specific configuration, distinct from the standard `"openlogi"` directory used in production XDG config paths.

### Separate IPC Socket Paths

The dev agent writes its Unix socket to `…/openlogi-dev/agent.sock`, while production uses `…/openlogi/agent.sock`. As noted in [`crates/openlogi-ipc/src/transport.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-ipc/src/transport.rs) (lines 25-27), this path divergence ensures that local macOS dev bundles use the sibling `openlogi-dev` profile, preventing development agents from occupying or interfering with production sockets even when both bundles run concurrently.

## macOS Bundle Configuration

macOS-specific metadata and system registrations maintain the boundary between builds through dedicated resource files and selective registration.

### Development Info.plist

The dev bundle utilizes a dedicated plist template located at `crates/openlogi-desktop/bundle/desktop-dev/Info.plist`. During the build, the `APP_PLIST` constant in [`dev_bundle.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/dev_bundle.rs) (lines 37-42) references this template, ensuring the final `OpenLogi-dev.app` contains dev-specific bundle metadata rather than the production configuration generated by `cargo-bundle`.

### Launch Services Registration

After construction, the `register_with_launch_services` function (lines 50-55 of [`dev_bundle.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/dev_bundle.rs)) executes `lsregister` to associate the `openlogi://` URL scheme with the dev bundle. Because the dev bundle identifier (`org.openlogi.openlogi-dev`) differs from production, this registration affects only the current session without overwriting the installed production bundle's URL handlers.

## Helper and Agent Isolation

Embedded components inherit the dev channel's isolation properties to prevent cross-environment process communication.

### Embedded Helper Components

When `OPENLOGI_DEV_AGENT` is not set to `0`, the dev bundle builds and embeds agent and overlay helpers under the `openlogi-dev` profile (lines 72-98 of [`dev_bundle.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/dev_bundle.rs)). These helpers use the dev socket path and inherit the `-dev` identifiers, preventing accidental connections to a production agent running on the standard socket.

### Transport Layer Boundaries

The IPC transport layer explicitly recognizes the `openlogi-dev` profile as a sibling configuration. This architectural boundary ensures that even at the network transport level, development bundles route messages exclusively to dev sockets, maintaining strict separation from production IPC endpoints.

## Building the Development Bundle

To generate an isolated development build, invoke the `xtask` command from the repository root:

```bash
cargo xtask macos dev-bundle --binary target/debug/openlogi-desktop

```

This command orchestrates the isolation logic, producing `OpenLogi-dev.app` with all `-dev` identifiers stamped throughout the bundle structure, sockets, and Launch Services metadata.

## Summary

- **Channel-based isolation**: The `Channel::Dev` constant hard-coded in [`dev_bundle.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/dev_bundle.rs) drives all dev-specific stamping logic via `identity::stamp`.
- **Separate file paths**: `DEV_APP_DIR` ("openlogi-dev") in [`paths.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/paths.rs) ensures distinct XDG config directories and socket locations.
- **Unique bundle identifiers**: The stamp function applies `org.openlogi.openlogi-dev` to all components, preventing macOS from conflating the apps.
- **Dedicated plist templates**: `desktop-dev/Info.plist` provides dev-specific macOS metadata separate from production.
- **Launch Service isolation**: Separate bundle IDs prevent URL scheme conflicts, with `lsregister` targeting only the dev bundle.
- **Helper embedding**: Dev helpers connect exclusively to `openlogi-dev/agent.sock`, avoiding production agent interference.

## Frequently Asked Questions

### What is the difference between OpenLogi.app and OpenLogi-dev.app?

OpenLogi.app represents the production bundle built via `cargo-bundle` using standard [`Cargo.toml`](https://github.com/AprilNEA/OpenLogi/blob/main/Cargo.toml) metadata. OpenLogi-dev.app is generated by the `macos::dev_bundle` xtask command, featuring the `-dev` suffix in its bundle identifier, dedicated socket paths at `…/openlogi-dev/agent.sock`, and isolated Launch Services registrations to prevent conflicts with the production version.

### How does the dev bundle prevent socket conflicts with production?

The dev bundle uses the `DEV_APP_DIR` constant ("openlogi-dev") defined in [`crates/openlogi-core/src/paths.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/paths.rs) to construct its socket path, whereas production uses the "openlogi" directory. This physical path separation, enforced by the IPC transport layer in [`transport.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/transport.rs), ensures development agents cannot bind to or communicate through production sockets.

### Can I run both production and dev bundles simultaneously?

Yes. Because the dev bundle carries the distinct identifier `org.openlogi.openlogi-dev` and registers separately with Launch Services via `lsregister`, macOS treats it as a separate application entity. The separate socket paths in the XDG config directories allow both agents to run concurrently without state interference or cross-communication.

### Where is the dev bundle build logic located?

The primary orchestration resides in [`xtask/src/commands/macos/dev_bundle.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/xtask/src/commands/macos/dev_bundle.rs), which coordinates channel selection, identity stamping via `identity::stamp`, helper embedding, and Launch Services registration. Path constants for the dev environment are defined in [`crates/openlogi-core/src/paths.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/paths.rs), while the identity stamping utilities live in [`xtask/src/commands/macos/bundle/identity.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/xtask/src/commands/macos/bundle/identity.rs).