silicon omni / reference

reference.

Everything omni exposes, what each provider does underneath, and the endpoint this site serves the dial from.

install.

$ pip install silicon-omni

Zero runtime dependencies. You bring the CLIs, and omni only offers the ones that are both installed and signed in.

provider
cli
how omni drives it
claude
Claude Code
claude -p
openai
Codex
codex app-server
google
Antigravity
agy
Inference.get_available_providers() # ['claude', 'google', 'openai']

inference.

The front door. The only object you need to import, besides the events.

from omni import Inference, Event PROVIDERS = Inference.get_available_providers() chat = Inference.load_or_create_session("session-id", PROVIDERS) Inference.claude.auth_status # authenticated | unauthenticated Inference.claude.installed # is the cli even here Inference.claude.limits # quota, without spending a token

Inference.claude, Inference.openai and Inference.google are the three account handles. They are resolved lazily, so touching one never imports the other two.

One live chat per session id. A second attempt raises SessionBusy; a lock whose owner has died is reclaimed, so a crash never wedges a session shut.

chat.

call
what it does
chat.start()
Bring a provider up and begin. Returns immediately.
chat.send(text)
Open a turn, or land inside the one already running.
chat.stop()
Shut the provider down and release the session id.
chat.status
idle before start, then busy / waiting, then stopped.
chat.idle
Waiting with nothing queued. What a polling loop should check.
chat.intelligence(n)
0-10 across every active provider. May change vendor.
chat.active_inference_providers([...])
Narrow which providers omni may route to.
chat.system_prompt(text)
Replace the provider's own session prompt.
chat.system_prompt_file(path)
The same, from a file.
chat.append_system_prompt(text)
Keep theirs and add to it.
chat.append_system_prompt_file(path)
The same, from a file.
chat.disable_subagents()
So only the workers you define get used.
chat.disable_mcp()
No MCP servers, no external connectors.
chat.cwd(path)
Where the provider runs its tools. Pinned to the session.
@chat.on_event
Decorator. Every event, as it happens.
@chat.logs
Decorator. Everything on_event sees, plus omni's bookkeeping.

Nothing changes mid turn

Every setter above is recorded when you call it and applied at the next turn boundary. Calling one again overwrites the last value. That is also how a new session is started: call load_or_create_session again.

Driving it

send never blocks and is safe from any thread, including from inside an event handler, so the loop is yours to choose.

# a plain loop chat.start() while chat.status in ("busy", "waiting"): message = fetch_new_messages() if message: chat.send(message) else: time.sleep(0.2) if should_stop() and last_event == Event.END: chat.stop()
# or a subscription async def on_msg(m): chat.send(m.data.decode()) # opens a turn, or lands mid-flight await m.ack() await nc.subscribe("agent.msgs", cb=on_msg)

events.

One dataclass for everything. Class attributes are the types, instance fields are the payload, and which fields are filled depends on the type.

field
meaning
type
which of the event types this is
session
the omni session id
provider
claude · openai · google
model
the model as the provider reported it
text
message content, for the types that carry it
tool / id / args
on TOOL.CALL
result / ok
on TOOL.RESULT
kind / error
on ERROR
at / seq
when it happened, and where in the session
extra
anything else the provider said

Event.ERROR carries a kind: auth, limit, unavailable or crash for the model and its CLI, plus stderr for CLI chatter, omni when the engine itself failed, and handler when one of your callbacks raised.

Logging

@chat.logs def log(event): write_somewhere(event.to_dict())

Everything on_event sees plus omni's own bookkeeping: every launch, model change, provider switch, new session, message in, tool call, error and stop. All of it the same type, so it is parsable without a second schema — and it is already on disk in the session file.

sessions.

path
what it holds
~/.omni/sessions/{id}.jsonl
the conversation, as an append-only event log
~/.omni/sessions/{id}.meta.json
each provider's own session, and how far it is synced
~/.omni/sessions/{id}.lock
the owning pid, reclaimed if that pid is gone
~/.omni/jails/{id}/codex
codex's stripped CODEX_HOME
~/.omni/cache/intelligence.json
the dial, per provider set, for an hour

How a switch works

auth.

Inference.claude.auth_status print(Inference.claude.start_auth()) # the url to open Inference.claude.finish_auth("code-or-redirect-url")

omni drives each CLI's own login rather than making you use the CLI: it starts the flow, hands you the URL and types the code back if one is wanted. Codex runs its own browser callback, so there finish_auth waits rather than types. If a CLI does something unexpected, whatever it printed comes back verbatim along with the command to run yourself.

Answers are remembered for a minute, because every probe means running a CLI. A no is only trusted for ten seconds, so a network blip cannot quietly drop a provider off your dial.

limits.

Inference.openai.limits # {'5h': {'used': 0.0, 'reset': 1787209867}, # '7d': {'used': 0.16, 'reset': 1787196805}}

used is a fraction, so 0.16 is 16%. Every provider is asked in a way that costs no tokens.

provider
how
worth knowing
claude
get_usage control request
some enterprise plans report no windows; used is then None
openai
account/rateLimits/read
read by window duration — primary is not always the 5h one
google
agy -p /usage
reports remaining per model group; omni reports used, worst first

providers.

Claude Code

One long-lived claude -p handles every turn over stdin. Seeding is a file write into ~/.claude/projects/<slug>/<uuid>.jsonl, where the slug is the working directory with every non-alphanumeric character turned into a dash — resolved through symlinks first, because on macOS /var is one. Resume is scoped to that directory, so a session pins its cwd. Model and effort change over the control channel and omni only believes it once the CLI acknowledges.

Codex

The app server, not exec. It always runs against a CODEX_HOME under ~/.omni/jails/ holding a symlink to your real auth.json — linked, not copied, so a token refresh is not lost — and a near-empty config. Skills live outside that folder, so disable_subagents() switches them off one at a time over the protocol. A mid-turn message becomes a turn/steer, falling back to a new turn if the old one finished first.

Antigravity

The most restricted, and the one with the sharpest edges. Cold start is around ten seconds per launch. An unrecognised conversation id makes agy silently start a new one, so omni checks the id it gets back and re-seeds from the top if it is not the one it asked for. --print takes a value and will swallow the next flag if it is not passed last. Any failed turn kills the process outright.

the registry.

This site serves the dial. omni asks for the one matching the providers it has and keeps the answer under ~/.omni/cache for an hour.

$ curl 'https://omni.teamofsilicons.com/intelligence.json?providers=claude+google' { "providers": "claude+google", "ladder": { "10": {"provider": "claude", "model": "claude-opus-5", "effort": "max", …}, "0": {…} }, "ladders": { every other combination } }

Point omni somewhere else with OMNI_REGISTRY. If the registry cannot be reached, omni prefers a dial it fetched before — even a stale one — over the copy packaged with the release, and backs off for five minutes rather than retrying on every call.

Changing what it serves

There is no database behind this. The models live in models-gdpval.json in a public repo, and the site reads that file over raw.githubusercontent at request time. Edit it, commit, and every install picks the change up within the hour — no release, no redeploy, and git keeps the history a database would have thrown away.