Deployment Models
Read this if you are choosing how to run ocli — one-off embedded, a reusable local daemon, or a remote runtime — and need to understand runtime resolution order, instance isolation, and what happens when a registry entry goes stale.
The current repo supports three practical ways to run the system, and .cli.json can now choose between them through runtime.mode.
1. Embedded mode
Best for:
- one-off CLI use
- CI jobs
- local debugging when you do not want a background daemon
Command pattern:
./bin/ocli --embedded --config ./.cli.json catalog list --format pretty
Characteristics:
- no separate
oclirdprocess - cache and audit paths still come from instance resolution
- behavior matches the runtime server implementation closely
- no
runtime.jsonregistry entry is written
2. One reusable local daemon
Best for:
- interactive local development
- agents that will run many commands against the same config
- sharing a warmed cache across many
ocliinvocations
Start the daemon:
./bin/oclird --config ./.cli.json --addr 127.0.0.1:8765
Then call it:
./bin/ocli --runtime http://127.0.0.1:8765 --config ./.cli.json catalog list
You can also select local-daemon behavior from config:
{
"runtime": {
"mode": "local"
}
}
With runtime.mode: "auto", ocli now promotes to local-daemon mode automatically when the effective config contains local MCP stdio sources. If no live runtime is registered for that instance, it starts a managed local oclird.
3. Remote runtime
Best for:
- centralized runtime hosting
- agent environments that should not run local MCP processes
- deployments where runtime access is controlled separately from the local workstation
Example:
{
"runtime": {
"mode": "remote",
"remote": {
"url": "https://runtime.example.com",
"oauth": {
"mode": "providedToken",
"tokenRef": "env:OAS_REMOTE_TOKEN"
}
}
}
}
Current remote auth support:
providedTokenforwards a caller-supplied bearer tokenoauthClientacquires a client-credentials token before runtime requestsbrowserLoginfetches runtime-hosted browser metadata and completes an authorization-code + PKCE flow
Brokered deployments typically pair those client modes with runtime.server.auth.validationProfile: "oidc_jwks" so the daemon can validate broker-issued runtime tokens locally.
This repo now ships one official worked example:
That page documents the broker-neutral contract, the automated oauthClient proof, and the manual Entra-federated browser proof.
4. Multiple isolated instances
Best for:
- different configs that should not share cache, audit, or runtime registry state
- concurrent long-running daemons
- operator-managed environments
Example:
./bin/oclird --config /srv/team-a/.cli.json --instance-id team-a
./bin/oclird --config /srv/team-b/.cli.json --instance-id team-b
Each instance gets its own:
- state directory
runtime.json- audit log
- cache directory
Runtime resolution order in ocli
When --embedded is not set, ocli resolves the runtime in this order:
- explicit runtime deployment choice from config when present
--runtimeOCLI_RUNTIME_URL- instance registry (
runtime.json) for the selected instance - local managed-runtime startup when config selects local mode and no live registry exists
- fallback to
http://127.0.0.1:8765
For explicit lifecycle control and discovery, the daemon now also exposes GET /v1/runtime/info and POST /v1/runtime/stop.
The instance selection itself can come from:
--instance-idOCLI_INSTANCE_ID- derived ID from the config path
default
If you pass --state-dir (or OCLI_STATE_DIR), ocli also derives the cache root under that state directory.
Stale runtime registry fallback
If runtime.json points at a daemon whose recorded PID is no longer alive, or at a runtime URL that no longer answers TCP connections, ocli:
- terminates any recorded managed MCP child processes for that dead daemon
- removes the stale registry file
- ignores that URL
- either restarts the managed local runtime or falls back to the default runtime URL, depending on deployment mode
Managed oclird also removes its own runtime.json on shutdown so normal stop/close flows do not leave behind stale registry entries.
What it does not do:
- it does not search for another daemon automatically
- it does not persist a new URL unless a daemon writes a fresh
runtime.json
Security note for remote bindings
oclird is safe-by-default for local development because it binds to loopback by default, but it does have an optional built-in runtime auth layer when you enable runtime.server.auth.
If you bind beyond localhost:
- enable
runtime.server.authso the daemon validates runtime bearer tokens and filters the catalog by runtime scopes - keep network controls in place as a second boundary, such as a reverse proxy, firewall policy, or SSH tunnel
See Runtime Overview for the runtime-auth handshake surface and Authentik reference proof for the worked brokered example.
If you are trying to…
| Goal | Go to |
|---|---|
| Configure client auth for a remote runtime | Runtime overview |
| Enable runtime bearer token validation on the daemon | Security overview |
| Isolate multiple teams with separate state and audit logs | Tracing and instances |
| See the full brokered deployment worked example | Authentik reference proof |
| Evaluate enterprise readiness as an operator | Enterprise readiness |
For the evaluator-focused path that ties those pages together with fleet proof and operations, continue to Enterprise readiness.