diff --git a/docs/configuration.md b/docs/configuration.md
index 9d4c0c491..338991a33 100644
--- a/docs/configuration.md
+++ b/docs/configuration.md
@@ -80,6 +80,7 @@ IMAP_PASSWORD=your-password-here
| `longcat` | LLM (LongCat) | [longcat.chat](https://longcat.chat/platform/docs/zh/) |
| `ollama` | LLM (local, Ollama) | — |
| `lm_studio` | LLM (local, LM Studio) | — |
+| `atomic_chat` | LLM (local, [Atomic Chat](https://atomic.chat/)) | — |
| `mistral` | LLM | [docs.mistral.ai](https://docs.mistral.ai/) |
| `stepfun` | LLM (Step Fun/阶跃星辰) | [platform.stepfun.com](https://platform.stepfun.com) |
| `ovms` | LLM (local, OpenVINO Model Server) | [docs.openvino.ai](https://docs.openvino.ai/2026/model-server/ovms_docs_llm_quickstart.html) |
@@ -502,6 +503,36 @@ ollama run llama3.2
+
+Atomic Chat (local)
+
+[Atomic Chat](https://atomic.chat/) is a local-first desktop app that exposes an **OpenAI-compatible** HTTP API (default `http://localhost:1337/v1`). Start Atomic Chat and enable the local API server, then point nanobot at it.
+
+**1. Add to config** (partial — merge into `~/.nanobot/config.json`):
+
+```json
+{
+ "providers": {
+ "atomic_chat": {
+ "apiKey": null,
+ "apiBase": "http://localhost:1337/v1"
+ }
+ },
+ "agents": {
+ "defaults": {
+ "provider": "atomic_chat",
+ "model": "your-model-id-from-atomic-chat"
+ }
+ }
+}
+```
+
+> **Note:** Set `apiKey` to `null` if your Atomic Chat server does not require a key. If it does, set `apiKey` (or the `ATOMIC_CHAT_API_KEY` environment variable) to the value Atomic Chat expects. The `model` string must match the model id Atomic Chat exposes on its OpenAI-compatible endpoint.
+
+> `provider: "auto"` also works when `providers.atomic_chat.apiBase` is configured, but setting `"provider": "atomic_chat"` is the clearest option.
+
+
+
OpenVINO Model Server (local / OpenAI-compatible)
diff --git a/nanobot/config/schema.py b/nanobot/config/schema.py
index c8556ec9f..96f9014a9 100644
--- a/nanobot/config/schema.py
+++ b/nanobot/config/schema.py
@@ -197,6 +197,7 @@ class ProvidersConfig(Base):
vllm: ProviderConfig = Field(default_factory=ProviderConfig)
ollama: ProviderConfig = Field(default_factory=ProviderConfig) # Ollama local models
lm_studio: ProviderConfig = Field(default_factory=ProviderConfig) # LM Studio local models
+ atomic_chat: ProviderConfig = Field(default_factory=ProviderConfig) # Atomic Chat local models
ovms: ProviderConfig = Field(default_factory=ProviderConfig) # OpenVINO Model Server (OVMS)
gemini: ProviderConfig = Field(default_factory=ProviderConfig)
moonshot: ProviderConfig = Field(default_factory=ProviderConfig)
diff --git a/nanobot/providers/registry.py b/nanobot/providers/registry.py
index 3eda6c5a4..4dba0c46d 100644
--- a/nanobot/providers/registry.py
+++ b/nanobot/providers/registry.py
@@ -422,6 +422,17 @@ PROVIDERS: tuple[ProviderSpec, ...] = (
detect_by_base_keyword="1234",
default_api_base="http://localhost:1234/v1",
),
+ # Atomic Chat (local, OpenAI-compatible) — https://atomic.chat/
+ ProviderSpec(
+ name="atomic_chat",
+ keywords=("atomic-chat", "atomic_chat", "atomicchat"),
+ env_key="ATOMIC_CHAT_API_KEY",
+ display_name="Atomic Chat",
+ backend="openai_compat",
+ is_local=True,
+ detect_by_base_keyword="1337",
+ default_api_base="http://localhost:1337/v1",
+ ),
# === OpenVINO Model Server (direct, local, OpenAI-compatible at /v3) ===
ProviderSpec(
name="ovms",
diff --git a/tests/cli/test_commands.py b/tests/cli/test_commands.py
index b0c3c43ee..90c2ce877 100644
--- a/tests/cli/test_commands.py
+++ b/tests/cli/test_commands.py
@@ -371,6 +371,28 @@ def test_config_accepts_lm_studio_without_api_key_and_uses_default_localhost_api
assert config.get_api_base() == "http://localhost:1234/v1"
+def test_config_accepts_atomic_chat_without_api_key_and_uses_default_localhost_api_base():
+ config = Config.model_validate(
+ {
+ "agents": {
+ "defaults": {
+ "provider": "atomic_chat",
+ "model": "local-model",
+ }
+ },
+ "providers": {
+ "atomicChat": {
+ "apiKey": None,
+ }
+ },
+ }
+ )
+
+ assert config.get_provider_name() == "atomic_chat"
+ assert config.get_api_key() is None
+ assert config.get_api_base() == "http://localhost:1337/v1"
+
+
def test_find_by_name_accepts_camel_case_and_hyphen_aliases():
assert find_by_name("volcengineCodingPlan") is not None
assert find_by_name("volcengineCodingPlan").name == "volcengine_coding_plan"
@@ -378,6 +400,8 @@ def test_find_by_name_accepts_camel_case_and_hyphen_aliases():
assert find_by_name("github-copilot").name == "github_copilot"
assert find_by_name("longcat") is not None
assert find_by_name("longcat").name == "longcat"
+ assert find_by_name("atomic-chat") is not None
+ assert find_by_name("atomic-chat").name == "atomic_chat"
def test_config_explicit_longcat_provider_resolves_provider_name():