Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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)

NameTypeInitRationale
MCP_UPDATE_SENDEROnceLock<mpsc::Sender<Vec<McpServerConfig>>>StartupCross-cutting MCP config change notifications
MCP_SERVICEOnceLock<McpService>StartupTool context has no UI handle; needs shared MCP client

Repository registry (chatty-core/src/lib.rs)

AccessorJSON / storagePurpose
provider_repository()providersLLM provider configs + API keys
general_settings_repository()general settingsTheme, font, UI prefs
models_repository()modelsPer-model capabilities
mcp_repository()MCP serversMCP service definitions
a2a_repository()A2A agentsWASM / remote agent registry
execution_settings_repository()executionWorkspace, approval mode, sandbox
search_settings_repository()searchWeb search provider keys
training_settings_repository()trainingFine-tuning prefs
user_secrets_repository()secretsUser-provided secret values
module_settings_repository()modulesWASM module settings
hive_settings_repository()hiveHive registry / billing
extensions_repository()extensionsBrowser extension config
token_tracking_repository()token trackingCompaction 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)

NameLocationTypePurpose
GLOBAL_WRITE_APPROVAL_MODEtools/filesystem_write_tool.rsOnceLock<Mutex<ApprovalMode>>Write-tool approval without coupling to UI
REGISTRYservices/browser/registry.rsLazyLock<Mutex<HashMap<String, Arc<BrowserManager>>>>conversation_id → BrowserManager so the transcript can dock a live browser panel
AZURE_TOKEN_CACHEfactories/agent_factory/provider_builder.rsOnceLock<Option<AzureTokenCache>>Azure OAuth token reuse
PLUGIN_ENGINEtools/plugin_tool.rsOnceLock<wasmtime::Engine>One Wasmtime engine for every spec plugin instance (PL-U2); limits are per store
LLM_CLIENTservices/http_client.rsLazyLock<reqwest::Client>Shared connection pool behind llm_client(), handed to every provider agent builder
MCP_WRITE_LOCKsettings/models/mcp_store.rsLazyLock<Mutex<()>>Serialize MCP JSON writes
WRITE_SLOTSsettings/repositories/generic_json_repository.rsLazyLock<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_AUGMENTEDauth/azure_auth.rsOnceLock<()>One-time PATH fix for Azure CLI
LIVE_SANDBOXESsandbox/manager.rsLazyLock<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
FONTSservices/math_renderer_service.rsLazyLock<(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.