OCI contexts for humans, scripts, and agents.
oci-context gives OCI the same day-to-day ergonomics that kubectl config use-context gives Kubernetes: switch profile, tenancy, compartment, region, and
auth state once, then let tools read the current context safely.
- stores named OCI contexts in YAML or JSON
- switches the current OCI profile, region, tenancy, and compartment
- validates and refreshes OCI auth
- exposes script-safe JSON/YAML/text output
- provides a daemon socket for local tools
- powers higher-level tools such as
bastion-sessionandoci-bassh
Homebrew is the preferred install path:
brew tap adrianmross/tap
brew install oci-contextThe Homebrew binaries are installed at:
/opt/homebrew/bin/oci-context
/opt/homebrew/bin/oci-contextdSource install:
curl -sSL https://raw.githubusercontent.com/adrianmross/oci-context/main/install.sh | bashInstall the daemon binary instead:
TOOL=oci-contextd curl -sSL https://raw.githubusercontent.com/adrianmross/oci-context/main/install.sh | bashBy default the installer writes to /usr/local/bin. Override it with PREFIX:
PREFIX="$HOME/.local" curl -sSL https://raw.githubusercontent.com/adrianmross/oci-context/main/install.sh | bashInstall a specific release:
VERSION=v0.14.0 curl -sSL https://raw.githubusercontent.com/adrianmross/oci-context/main/install.sh | bashCreate or update local config:
oci-context init
oci-context create dev \
--compartment ocid1.compartment.oc1..bbbb \
--region us-phoenix-1
oci-context use devcreate inherits the tenancy, user, and API-key profile from
options.default_profile (or the OCI DEFAULT profile), so only the new
context name and target compartment/region are needed. Use --profile to
choose another OCI CLI profile. add remains an alias.
Check the active context:
oci-context current
oci-context statusMake sure auth is ready before automation:
oci-context auth ensure --output jsonEmit an OBP/OABCS token for another command without persisting it in that tool's config:
oci-context auth token --service obp --format rawTools such as ochain can use that as a credential-command bridge:
{
"auth": {
"tokenCommand": "oci-context auth token --service obp --format raw"
}
}Token services are generic OAuth definitions. The shipped obp service reads
the OChain-provided target metadata and uses flow: auto: Authorization Code is
preferred when the issuer advertises an authorization endpoint, and Device Code
is used only when that is the available interactive flow. Define additional
services in config when another tool should use a different issuer, client,
scope, redirect URL, or flow:
current_service: obp
token_services:
- name: obp
type: oauth
flow: authorization-code
issuer_envs:
- OCHAIN_OBP_AUTH_ISSUER
- OBP_OAUTH2_ISSUER
client_id: obp
client_secret_env: OCHAIN_OBP_AUTH_CLIENT_SECRET
scope_envs:
- OCHAIN_OBP_AUTH_SCOPE
- OCHAIN_OBP_PLATFORM
authorization_endpoint_env: OCHAIN_OBP_AUTH_AUTHORIZATION_ENDPOINT
token_endpoint_env: OCHAIN_OBP_AUTH_TOKEN_ENDPOINT
redirect_url_env: OCHAIN_OBP_AUTH_REDIRECT_URLWith current_service set in a global or project-local .oci-context.yml,
interactive service login does not need stdin or flags:
oci-context auth login
oci-context auth token --no-login --format rawSet offline_access: true on a token service, or pass --offline-access, when
both the OAuth client and resource app permit refresh tokens. oci-context
then requests the standard offline_access scope, caches the rotating refresh
token, and uses it for --no-login after access-token expiry. OBPCS-generated
resource apps can reject offline access; leave it disabled for those services
unless their resource configuration has been updated.
For downstream CLIs that accept environment handoff payloads, tool setup
prints the current token-service bridge without storing secrets in the
downstream tool:
oci-context tool setup ochain
oci-context tool setup ochain -o shellThe JSON payload includes environment entries such as OCHAIN_TOKEN_COMMAND
and an authProfiles snippet with separate cached-token and interactive-login
commands suitable for OChain's XDG user config at
${XDG_CONFIG_HOME:-$HOME/.config}/ochain/config.json. Add --include-token
for one-shot consumers that need an OCHAIN_TOKEN value in the payload:
oci-context tool setup ochain --include-tokenoci-idm materializes oci-context-token-services.yml and
oci-context.handoff.json files for planned Identity Domains apps. Import
either handoff shape directly:
oci-context service add \
--file ./idm-artifacts/oci-context-token-services.yml \
--set-current
oci-context service list
oci-context service getservice get [name] defaults to current_service and emits JSON by default.
The document contains redacted OAuth metadata plus a structured credential
command (command and args) that downstream tools can store without copying
an access token. Interactive flows also include interactiveCredential, which
lets a downstream tool start login while discarding token stdout. For example:
oci-context service get | brute auth apply -f -oci-context auth service import --file ... remains available for older
scripts. The top-level service add command also reads stdin, which makes the
auth-target handoff a plain JSON/YAML pipe:
oci-idm clone app --flow authorization-code --name hebe-obp-user |
oci-context service add --set-current
oci-context auth loginoci-idm get defaults can also pipe the current target metadata directly into
oci-context auth login. oci-context consumes the service name, issuer, and
scope from stdin, merges those non-secret values into the named token service,
then runs the interactive OAuth login and caches the resulting token:
oci-idm get defaults --service obp |
oci-context auth login
oci-context auth token --service obp --no-login --format rawFor the common Red Wiz OABCS target, select the OCI context for oabcs1 in the
default domain and configure the chaincode deploy environment for
pmdemo/adrian/did on channel testnet. The token command reads
OCHAIN_OBP_AUTH_ISSUER, OCHAIN_OBP_AUTH_CLIENT_ID, and
OCHAIN_OBP_AUTH_SCOPE from the caller environment, so OChain can resolve the
target and oci-context can own the browser login.
For Oracle Identity Cloud Service domains that do not expose a Device Code endpoint, configure a CLI-capable IDCS application with Authorization Code and a loopback redirect URL, then either pipe target defaults into login or force the lower-level token flow locally:
export OCHAIN_OBP_AUTH_REDIRECT_URL=http://127.0.0.1:8180/callback
oci-idm get defaults --service obp |
oci-context auth login
oci-context auth token \
--service obp \
--flow authorization-code \
--redirect-url "$OCHAIN_OBP_AUTH_REDIRECT_URL" \
--format rawRegister the same redirect URL on the IDCS confidential application. If the
client requires a secret, provide it through OCHAIN_OBP_AUTH_CLIENT_SECRET or
service config rather than storing it in the downstream tool. stdout contains
the bearer token and must be treated as secret material; browser instructions
are written to stderr.
The default OBPCS cloud-service application is normally a CloudGate web
application. Its redirect is service-owned, for example
https://<hostid>/cloudgate/v1/oauth2/callback. That callback is correct for
browser access to the OBPCS service, but it is not a CLI callback:
CloudGate receives and consumes the authorization code, so oci-context cannot
exchange it for a bearer token. For command handoff, use a separate IDCS OAuth
client that is allowed to request the OBP REST proxy scope and has a registered
loopback redirect such as http://127.0.0.1:8180/callback, or use a trusted
non-interactive flow such as client credentials or JWT assertion when that is
the intended identity.
Non-interactive OAuth flows are first-class and can run under --no-login.
Use jwt-client-credentials for service accounts whose IDCS app trusts a
client assertion:
oci-context auth token \
--service obp \
--flow jwt-client-credentials \
--token-endpoint "$OCHAIN_OBP_AUTH_TOKEN_ENDPOINT" \
--client-id "$OCHAIN_OBP_AUTH_CLIENT_ID" \
--scope "$OCHAIN_OBP_AUTH_SCOPE" \
--client-assertion-command ./mint-client-assertion.sh \
--no-login \
--format rawWhen the client assertion should be signed locally, provide a PEM private key and optional key id instead of a command:
oci-context auth token \
--service obp \
--flow jwt-client-credentials \
--token-endpoint "$OCHAIN_OBP_AUTH_TOKEN_ENDPOINT" \
--client-id "$OCHAIN_OBP_AUTH_CLIENT_ID" \
--scope "$OCHAIN_OBP_AUTH_SCOPE" \
--private-key-file ./idcs-client.key \
--key-id "$OCHAIN_OBP_AUTH_KEY_ID" \
--no-login \
--format rawFor OCI Identity Domains, locally signed client assertions normally use
https://identity.oraclecloud.com/ as the assertion audience. oci-context
uses the token endpoint by default for generic OAuth servers, but if an OCI
Identity Domains token endpoint rejects that default with an invalid assertion
audience error, it retries once with the OCI audience. You can make that
explicit with --jwt-audience https://identity.oraclecloud.com/.
Use jwt-bearer when a trusted issuer can assert a user or subject that the
identity domain maps to a service-authorized identity:
oci-context auth token \
--service obp \
--flow jwt-bearer \
--token-endpoint "$OCHAIN_OBP_AUTH_TOKEN_ENDPOINT" \
--client-id "$OCHAIN_OBP_AUTH_CLIENT_ID" \
--scope "$OCHAIN_OBP_AUTH_SCOPE" \
--assertion-command ./mint-user-assertion.sh \
--no-login \
--format rawUse token-exchange for federated workload identity, such as a GitHub Actions
OIDC token, Kubernetes projected service account token, or another external
workload JWT:
oci-context auth token \
--service obp \
--flow token-exchange \
--token-endpoint "$OCHAIN_OBP_AUTH_TOKEN_ENDPOINT" \
--client-id "$OCHAIN_OBP_AUTH_CLIENT_ID" \
--scope "$OCHAIN_OBP_AUTH_SCOPE" \
--subject-token-command ./mint-workload-token.sh \
--requested-token-type urn:ietf:params:oauth:token-type:access_token \
--no-login \
--format rawOAuth tokens are cached by service and are reused under --no-login when still
valid. Use --no-cache to force a fresh token request and avoid updating the
cached token, for example when validating a new IDCS app, role grant, or signing
key without disturbing a known-good cached token.
Inspect local metadata without calling OCI:
oci-context version -o json
oci-context paths -o json
oci-context status --cached -o jsonGlobal config:
~/.oci-context/config.yml
Project-local config is auto-detected when --config and --global are not
set. First match wins:
./.oci-context.yml
./.oci-context.json
./.oci-context/config.yml
./.oci-context/config.json
./oci-context.yml
./oci-context.json
./oci-context/config.yml
./oci-context/config.json
Selection rules:
--config <path>always wins--globalforces~/.oci-context/config.yml- otherwise the first project-local file wins
- if no project-local file exists, global config is used
When the selected config path ends in .json, writes preserve JSON encoding.
Other config paths are written as YAML. Config writes are protected by a file
lock and atomic rename.
Use oci-context paths -o json to see the selected path, selection source,
project candidates, configured OCI config path, socket path, and any nonfatal
config load error.
Example config:
options:
oci_config_path: ~/.oci/config
socket_path: ~/.oci-context/daemon.sock
default_profile: ""
daemon_contexts: []
contexts:
- name: dev
profile: DEFAULT
tenancy_ocid: ocid1.tenancy.oc1..aaaa
compartment_ocid: ocid1.compartment.oc1..bbbb
region: us-phoenix-1
user: alice@example.com
notes: dev tenancy
current_context: devoci-context --version
oci-context version -o text|json|yaml
oci-context paths -o text|json|yaml
oci-context init
oci-context list
oci-context current
oci-context use <name>
oci-context create [name]
oci-context set <name> --field value
oci-context delete <name>
oci-context status --cached -o json
oci-context doctor --output json
oci-context oci -- <oci args...>
oci-context auth methods|show|set|set-user|login|refresh|ensure|validate|setup|notify
oci-context daemon serve
oci-context daemon up
oci-context daemon repair --all --monitor dev
oci-context daemon doctor
oci-context setup daemon --all --monitor dev
oci-context tuiUse auth ensure before OCI-dependent automation. It validates the selected
context, refreshes security_token auth when possible, and returns a clear
structured result:
oci-context auth ensure --output json
oci-context auth show --output json
oci-context auth methods --output json
oci-context doctor --output jsonStructured auth results include both detailed booleans and a small decision surface for wrappers:
readyaction_requiredaction(none,login, orcheck_auth)severity(okorerror)
If validation and refresh cannot recover a security token, the command reports
login_required: true. To allow an interactive browser login as part of the
same command:
oci-context auth ensure --loginFor non-interactive automation:
oci-context --no-interactive auth ensure --login --output jsonInstall or refresh all macOS daemon integrations and monitor a context:
oci-context setup daemon --all --monitor devEquivalent daemon-focused form:
oci-context daemon repair --all --monitor devFor a lightweight post-wake or pre-work check:
oci-context daemon auth-status
oci-context auth ensure --no-interactivedaemon auth-status includes a daemon-specific readiness contract:
ready: validation currently proves auth is usable.action_required: something needs operator or automation action.action:none,nudge,login, orcheck_auth.severity:ok,warning, orerror.reason: human-readable explanation for the decision.
For security_token contexts, a failed refresh is not by itself an action when
validation still succeeds. This avoids wake notifications for healthy sessions
that were not freshly refreshed.
Use structured daemon diagnostics for automation:
oci-context daemon doctor --output json
oci-context daemon nudge --output json
oci-context daemon recover --output jsonTo run plain oci ... commands without repeatedly passing profile, region, and
compartment, load managed OCI CLI defaults once per shell:
eval "$(oci-context export -f oci-env)"This sets:
OCI_CLI_RC_FILEto a managed rc file updated from your current contextOCI_CLI_CONFIG_FILEto your configured OCI config path
After that, oci-context use ... and TUI saves refresh the managed OCI CLI
defaults automatically.
/starts filteringEnterapplies the filtered list and stages in-region selectionsSpacestages or highlights the current rowCtrl+SorqsavesEscorCtrl+Cquits without savingbackspacegoes backnopens a name prompt to create a clone from the selected context and any staged region, compartment, auth, tenancy, or user values- main menu hotkeys are lowercase:
r,c,t - submenu hotkeys are uppercase:
R,C,T,P
Stable automation output is JSON. Agents should prefer --output json,
-o json, or --format json for supported commands such as status, paths,
version, export, auth ensure, auth show, and daemon status commands.
Use status --cached -o json, auth show --output json, and
auth ensure --output json for ordinary inspection. Use export only when the
task is explicitly to export shell environment settings or hand a context to
another process.
The daemon serves framed JSON over a Unix socket.
Example requests:
{ "method": "get_current" }
{ "method": "use_context", "name": "dev" }
{ "method": "list" }
{ "method": "export", "format": "env" }
{ "method": "auth_status", "name": "dev" }Responses use:
{ "ok": true, "data": {} }or:
{ "ok": false, "error": "..." }