Process-global singleton inventory
When to read this: Find where shared state lives before adding a new global, repository, or OnceLock.
Canonical comment block: crates/chatty-core/src/lib.rs (top of file). This page expands it with accessors and rationale. Hand-maintained; CI checks that every OnceLock/LazyLock static in chatty-core (regex and font caches excepted) has a row (make docs-check-reference).
Service singletons (chatty-core/src/lib.rs)
| Name | Type | Init | Rationale |
|---|---|---|---|
MCP_UPDATE_SENDER | OnceLock<mpsc::Sender<Vec<McpServerConfig>>> | Startup | Cross-cutting MCP config change notifications |
MCP_SERVICE | OnceLock<McpService> | Startup | Tool context has no UI handle; needs shared MCP client |
Repository registry (chatty-core/src/lib.rs)
| Accessor | JSON / storage | Purpose |
|---|---|---|
provider_repository() | providers | LLM provider configs + API keys |
general_settings_repository() | general settings | Theme, font, UI prefs |
models_repository() | models | Per-model capabilities |
mcp_repository() | MCP servers | MCP service definitions |
a2a_repository() | A2A agents | WASM / remote agent registry |
execution_settings_repository() | execution | Workspace, approval mode, sandbox |
search_settings_repository() | search | Web search provider keys |
training_settings_repository() | training | Fine-tuning prefs |
user_secrets_repository() | secrets | User-provided secret values |
module_settings_repository() | modules | WASM module settings |
hive_settings_repository() | hive | Hive registry / billing |
extensions_repository() | extensions | Browser extension config |
token_tracking_repository() | token tracking | Compaction share / context-window thresholds (ADR-0007) |
All repositories initialize via init_repositories() once at startup. Use accessor functions — never read REPOSITORY_REGISTRY directly.
Domain-local singletons (near usage)
| Name | Location | Type | Purpose |
|---|---|---|---|
GLOBAL_WRITE_APPROVAL_MODE | tools/filesystem_write_tool.rs | OnceLock<Mutex<ApprovalMode>> | Write-tool approval without coupling to UI |
REGISTRY | services/browser/registry.rs | LazyLock<Mutex<HashMap<String, Arc<BrowserManager>>>> | conversation_id → BrowserManager so the transcript can dock a live browser panel |
AZURE_TOKEN_CACHE | factories/agent_factory/provider_builder.rs | OnceLock<Option<AzureTokenCache>> | Azure OAuth token reuse |
PLUGIN_ENGINE | tools/plugin_tool.rs | OnceLock<wasmtime::Engine> | One Wasmtime engine for every spec plugin instance (PL-U2); limits are per store |
LLM_CLIENT | services/http_client.rs | LazyLock<reqwest::Client> | Shared connection pool behind llm_client(), handed to every provider agent builder |
MCP_WRITE_LOCK | settings/models/mcp_store.rs | LazyLock<Mutex<()>> | Serialize MCP JSON writes |
WRITE_SLOTS | settings/repositories/generic_json_repository.rs | LazyLock<Mutex<HashMap<PathBuf, WriteSlot>>> | Per settings file, the last save written behind an async lock, so overlapping saves of one file never interleave and an older save never lands over a newer one (AGE-562) |
PATH_AUGMENTED | auth/azure_auth.rs | OnceLock<()> | One-time PATH fix for Azure CLI |
LIVE_SANDBOXES | sandbox/manager.rs | LazyLock<Mutex<HashMap<u64, SandboxMap>>> | Holds every live SandboxManager’s container map so shutdown_all() can destroy them at process exit — a manager’s Drop can only spawn a detached task, which dies with the runtime |
FONTS | services/math_renderer_service.rs | LazyLock<(Vec<Font>, FontBook)> | Typst’s embedded fonts parsed once per process; every math compile used to re-parse all of them in MathWorld::new (AGE-394) |
Design rule: service and repository singletons stay centralized in lib.rs; domain-local OnceLocks stay in the module that owns the behavior to avoid coupling unrelated code.
GPUI globals (chatty-core + gpui-globals feature)
UI frontends store WeakEntity<T> handles in types implementing gpui::Global (see chatty-core/src/gpui_globals.rs). Examples: ConversationsStore, ModelsModel, GlobalStreamManager, GlobalChattyApp. Prefer weak refs in globals to prevent circular ownership.
Not singletons (avoid confusing with globals)
Module-level LazyLock<Regex> and tokenizer caches (token_budget/counter.rs, renderer services) are immutable process caches, not application state. They do not require init_*() and are safe to lazy-init on first use.