# Ollama Client Full Documentation

Source: https://www.ollamaclient.in

Privacy-first browser extension for local LLM chat with Ollama, LM Studio, llama.cpp, and OpenAI-compatible servers.

# Ollama quick start in Chrome or Firefox

Source: https://www.ollamaclient.in/guides/quick-start/
Markdown: https://www.ollamaclient.in/guides/quick-start.md
Description: Connect Ollama Client to Ollama, LM Studio, or llama.cpp and send your first local AI chat from the browser side panel.

Ollama Client lets you chat with a local LLM from the browser side panel. The
fastest path is: start a local provider, install the extension, choose a model,
and send your first message.

## 1. Start a local provider

Use any supported local or OpenAI-compatible server.

### Ollama

```bash
ollama serve
ollama pull llama3.2
```

Default URL: `http://localhost:11434`

### LM Studio

Open LM Studio, start the local server, and load a model.

Default URL: `http://localhost:1234/v1`

### llama.cpp server

```bash
llama-server -m ~/Library/Caches/llama.cpp/model.gguf --port 8000 --host 0.0.0.0
```

Default URL: `http://localhost:8000/v1`

## 2. Install Ollama Client

Install the extension, open the side panel, and go to **Setup** if the provider
connection is not detected automatically.

Use [Provider Setup](/guides/provider-setup/) for full provider-specific
configuration.

## 3. Pick a model

Open the model selector and choose a model from your provider. If a model list is
empty, check that the provider is running and that the base URL matches the
server.

## 4. Send your first message

Ask a normal question. Ollama Client streams the answer into the side panel and
stores the chat locally.

## 5. Add page context or files

After the first chat works, enable the context controls you need:

- **Page & tabs** for current-page and tab context.
- **Knowledge & web** for uploaded files, local RAG, and optional web search.
- **Privacy & permissions** for browser permissions and model-callable tools.

## Common first-run problems

### The provider says 403 or CORS

Firefox and strict local servers may reject browser-extension origins. For
Ollama, choose either setup; installing olc is optional.

**Automatic setup with olc:**

```bash
curl -fsSL https://ollamaclient.in/olc.sh | sh  # macOS / Linux
olc
olc --check --json
```

On Windows PowerShell, install with `irm https://ollamaclient.in/olc.ps1 | iex`,
then run the same olc commands.

These installers pipe a remote script into your shell. To pin the release and verify it first, see [installing without piping to a shell](/developers/#install-without-piping-to-a-shell).

**Manual setup without olc:** stop the current Ollama app/server, set
`OLLAMA_ORIGINS`, and start it again:

```bash
# macOS / Linux shell
OLLAMA_ORIGINS="chrome-extension://*,moz-extension://*" ollama serve
```

```powershell
# Windows PowerShell
$env:OLLAMA_ORIGINS="chrome-extension://*,moz-extension://*"
ollama serve
```

For persistent Ollama app and system-service configuration, see
[Fix Ollama CORS errors](/guides/troubleshooting/ollama-cors-error/).

### The model list is empty

Confirm the provider is running, the base URL is correct, and at least one model
is available locally.

### Chat works but tools do not

Tool calling depends on model capability plus the enabled tool family settings.
Check **Privacy & permissions** for the live tool inventory.

## FAQ

### Does this require OpenAI?

No. Ollama Client works with local and self-hosted providers. OpenAI-compatible
means the server speaks the OpenAI API shape; it does not require OpenAI.

### Does chat history stay local?

Yes. Chat history is stored locally in browser extension storage.

### Can I use this as an Open WebUI alternative?

Yes, if you want a browser extension and side panel instead of a self-hosted web
app.

---

# Provider Setup

Source: https://www.ollamaclient.in/guides/provider-setup/
Markdown: https://www.ollamaclient.in/guides/provider-setup.md
Description: Configure Ollama, LM Studio, llama.cpp, OpenAI, OpenRouter, Anthropic, Chinese frontier APIs, or compatible servers.

Verified built-ins are Ollama, LM Studio, and llama.cpp. Add vLLM, LocalAI, KoboldCPP, or another compatible endpoint through **Add provider**. The OpenRouter preset uses its OpenAI-compatible Chat Completions API. Anthropic uses the native Messages API, while the generic Anthropic-compatible option also supports keyless local or LAN endpoints.

Web search is configured separately in the Context tab. Use SearXNG for local/self-hosted search, or Brave Search/Tavily when you want an API-backed provider.

## 1. Install the extension

Install [Ollama Client](https://chromewebstore.google.com/detail/ollama-client-chat-with-l/bfaoaaogfcgomkjfbmfepbiijmciinjl) from the Chrome Web Store.

## 2. Pick a provider

| Provider | Default endpoint | Notes |
|---|---|---|
| Ollama | `http://localhost:11434` | Recommended baseline. Tool calling plus fullest model-management support. |
| LM Studio | `http://localhost:1234/v1` | OpenAI-compatible chat, embeddings, tool calling, and LM Studio model discovery. |
| llama.cpp server | `http://localhost:8000/v1` | OpenAI-compatible. Run with `llama-server`. |
| OpenAI-compatible | User configured | Add vLLM, LocalAI, KoboldCPP, or another compatible endpoint. |
| OpenAI | `https://api.openai.com/v1` | Hosted OpenAI API; API key required. Uses streamed usage and the modern completion-token field. |
| Anthropic | `https://api.anthropic.com/v1` | Remote Claude Messages API; API key required. |
| Anthropic-compatible | User configured | Native Messages wire; API key is optional for compatible self-hosted endpoints. |
| OpenRouter | `https://openrouter.ai/api/v1` | OpenAI-compatible hosted gateway; API key required. Model IDs keep their provider prefix. |

### Contract-tested hosted compatibility endpoints

The following hosted providers use **OpenAI-compatible** in the Add provider
dialog. The listed URLs are editable examples, not client-side restrictions;
regional endpoints, enterprise gateways, and reverse proxies are supported.
Their request and streaming-response shapes are covered by fixture-based
contract tests sourced from the vendors' current API documentation. These tests
do not spend API credits or assert that every model supports every capability;
they protect endpoint joining, Bearer authentication, model IDs, streamed text
and reasoning, usage, and standard function tool calls from client regressions.

| Provider | Base URL | Wire contract |
|---|---|---|
| DeepSeek | `https://api.deepseek.com` | OpenAI Chat Completions, including `reasoning_content` and tools. |
| Qwen / Alibaba Model Studio | `https://dashscope.aliyuncs.com/compatible-mode/v1` | DashScope's OpenAI-compatible Chat Completions endpoint. Use the endpoint for your account region when it differs. |
| Kimi / Moonshot | `https://api.moonshot.ai/v1` | OpenAI-compatible Chat Completions, including streamed tool-call fragments. |
| Z.AI / GLM | `https://api.z.ai/api/paas/v4` | OpenAI-compatible Chat Completions. China accounts may use the BigModel endpoint instead. |

The provider's own model documentation remains authoritative for vision,
reasoning, tools, context limits, and regional availability. A passing client
contract test means Ollama Client preserves the documented wire shape; it is
not a live service-health check.

## 3. Configure and start Ollama

Ollama Client does not require olc. Choose the automatic CLI setup or configure
Ollama's environment yourself.

### Option A: automatic setup with olc

Install Ollama from [ollama.com](https://ollama.com), then install the **olc CLI**:

```bash
# macOS / Linux
curl -fsSL https://ollamaclient.in/olc.sh | sh
```

```powershell
# Windows PowerShell
irm https://ollamaclient.in/olc.ps1 | iex
```

These installers pipe a remote script into your shell. To pin the release and verify it first, see [installing without piping to a shell](/developers/#install-without-piping-to-a-shell).

Start or reuse native Ollama with extension origins enabled:

```bash
olc
olc --check --json   # optional read-only verification
```

Use `olc --lan` only for trusted-network access; Ollama's native API has no
authentication. Use `olc --debug` for foreground diagnostics. The CLI is detached
by default and refuses to replace an unrelated listener. It never writes global,
user, app, or service environment: `OLLAMA_*` exists only on a standalone Ollama
process started by olc. Compatible managed servers are reused unchanged; stop or
manually configure an incompatible service. On macOS, olc can gracefully quit an
incompatible Ollama app and replace it with a process-scoped standalone server.
See [OLC installation and platform behavior](/developers/).

### Option B: manual setup without olc

Fully stop the existing Ollama app or server first so the restarted process
inherits the new environment.

For a macOS or Linux shell-run server:

```bash
OLLAMA_ORIGINS="chrome-extension://*,moz-extension://*" \
OLLAMA_HOST="127.0.0.1:11434" \
ollama serve
```

For the macOS Ollama app, set its launch-session environment and restart it:

```bash
launchctl setenv OLLAMA_ORIGINS "chrome-extension://*,moz-extension://*"
osascript -e 'quit app "Ollama"'
open -a Ollama
```

The `launchctl` value lasts until logout. Remove it with
`launchctl unsetenv OLLAMA_ORIGINS`.

For a Linux systemd service:

```bash
sudo systemctl edit ollama
```

Add this override, then save the editor:

```ini
[Service]
Environment="OLLAMA_ORIGINS=chrome-extension://*,moz-extension://*"
```

```bash
sudo systemctl daemon-reload
sudo systemctl restart ollama
```

For the current Windows PowerShell session:

```powershell
$env:OLLAMA_ORIGINS="chrome-extension://*,moz-extension://*"
ollama serve
```

To persist it for the current Windows user, set the user variable and then
fully quit and reopen Ollama:

```powershell
[Environment]::SetEnvironmentVariable(
  "OLLAMA_ORIGINS",
  "chrome-extension://*,moz-extension://*",
  "User"
)
```

These examples keep Ollama on loopback port `11434`. For LAN access, set
`OLLAMA_HOST=0.0.0.0:11434` only on a trusted network; Ollama has no native API
authentication. See [CORS troubleshooting](/guides/troubleshooting/ollama-cors-error/)
for verification and platform details.

Pull at least one chat model:

```bash
ollama pull qwen2.5:3b
```

To use hosted `:cloud` models through the same local Ollama provider, see [Use Ollama Cloud models](/guides/ollama-cloud/). Recent Ollama versions let Ollama Client add recommended cloud models to the normal model menu automatically.

For tool calling and image input, choose a model that actually supports those capabilities. The extension detects reported capabilities where providers expose them, and lets you override them from the model menu when a provider cannot report them.

Pull one embeddings model for RAG:

```bash
ollama pull all-minilm:latest
```

You need at least one chat model and one embeddings model installed for the full experience.

:::note[Optional Bash helper]
From a repository clone, `tools/setup/ollama-env.sh` automates the same manual
environment setup for existing Bash workflows. You can use it without installing
olc. The olc path adds stricter process ownership checks and readiness reporting.
:::

## 4. Configure the extension

1. Open the extension's options page.
2. Go to the **Providers** tab.
3. Enable the providers you want.
4. Set the base URL and run a connection test.
5. Pick a model from the chat model menu.

### Endpoints that do not list models

Some hosted gateways implement `/chat/completions` and nothing else. The connection test reports those as reached but without a model list, and no model can be discovered from them.

Add the model IDs you want under **Model IDs** on the provider card (or in the Add provider dialog). Those IDs go into the chat model menu exactly like discovered ones, and they survive a failed or missing `/models` request — so a provider that publishes no catalog is still fully usable. Removing an ID only removes it from the menu; it never deletes anything on the server.

The answer is remembered per provider, so such an endpoint is asked once rather than on every refresh. It is re-checked after a day, whenever you change the base URL, wire, or preset, and whenever you press **Test**.

A wrong base URL answers the model-list request exactly the way a chat-only gateway does, so **Test** settles it by asking the chat endpoint to generate a single token with the first model ID you added. If that answers, the provider is reported as working; if nothing is there either, the test tells you to check the base URL — hosted providers usually need the version suffix, such as `/v1`. That one-token request is only sent when you press Test, never by the background connection check.

### Image-generation models

Generated images use the same chat history and preview UI regardless of provider. Ollama image models use the Ollama generation stream. OpenAI-compatible providers use their Images endpoint, with a fallback for compatible servers that return inline image parts from Chat Completions.

When a model catalog reports image output, the extension enables it automatically. For providers whose catalog does not report output modalities, open the model's capability sheet and enable **Image generation**. This flag is separate from **Vision**: vision accepts an image as input, while image generation produces an image as the assistant response.

Provider output is normalized to validated PNG, JPEG, or WebP data and saved with the assistant message. The extension requests base64 image data and does not follow provider-returned image URLs.

## 5. Verify endpoints

```bash
# Ollama
curl http://localhost:11434/api/tags

# LM Studio
curl http://localhost:1234/v1/models

# llama.cpp
curl http://localhost:8000/v1/models
```

## 6. Reality checks

- Chat generation is fully provider-agnostic.
- Image input is model-dependent. If the selected model is not vision-capable, the composer blocks image attach instead of sending unsupported input.
- Image output is provider- and model-dependent. It is routed through a shared generated-image stream rather than inferred from the provider's brand.
- Tool calling is model-dependent. Ollama and LM Studio both expose tool-calling APIs, but the selected model still needs tool-use support. Tool-capable models can inspect browser context through local extension tools; non-tool models keep the old plain chat path.
- Web search is off by default and model-visible only as `web_search`. Backend choice is a user setting, not a model prompt detail.
- Model-management actions depend on provider capabilities. Ollama has the fullest support; LM Studio adds pull/unload support.
- Embedding generation uses the configured provider when supported, then falls back through the shared embedding path and Ollama for reliability.

## 7. Optional local web search with SearXNG

The repo includes a local SearXNG compose stack for private web-search testing.

```bash
cd searxng
docker compose up -d
```

Then open Settings -> Context -> Web Search:

1. Enable web search.
2. Pick `SearXNG`.
3. Set endpoint to `http://localhost:8080`.
4. Run **Test search**.

SearXNG supports `pageno`, not an API-side result-count parameter. Ollama Client can fetch 1-3 pages, de-dupe URLs, then apply the configured result-count cap before returning results to the model.

## 8. Search provider API references

- [SearXNG Search API](https://docs.searxng.org/dev/search_api.html)
- [Brave Search API](https://api-dashboard.search.brave.com/app/documentation/web-search/responses)
- [Tavily Search API](https://docs.tavily.com/documentation/api-reference/endpoint/search)

## 9. CORS and browser notes

Chrome-based browsers route extension requests through Declarative Net Request (DNR). Firefox uses a different extension API model.

:::caution[Firefox + Ollama]
On Firefox or strict environments, you may need to set `OLLAMA_ORIGINS` to allow the extension origin. Either run olc as shown above or use the manual environment instructions; both configure Ollama itself, and the extension works the same way afterward.
:::

## 10. Troubleshooting

- Confirm the provider process is actually running.
- Confirm the endpoint URL matches the runtime URL exactly (port, scheme, `/v1` suffix).
- Use the **Test connection** button in Providers settings before debugging model behavior.
- For web search, use **Test search** in Context settings and verify your SearXNG endpoint or API key.
- Check the background console (`chrome://extensions` → service worker) for streaming or provider errors.

## Related

- [Architecture](/concepts/architecture/)
- [Context, Images, and Tools](/guides/context-and-tools/)
- [Ollama Cloud models](/guides/ollama-cloud/)
- [Privacy policy](/legal/privacy-policy/)
- [GitHub repository](https://github.com/Shishir435/ollama-client)

---

# Use Ollama Cloud models

Source: https://www.ollamaclient.in/guides/ollama-cloud/
Markdown: https://www.ollamaclient.in/guides/ollama-cloud.md
Description: Sign in to Ollama, discover hosted models automatically, and use :cloud models without downloading them.

Ollama Cloud models run on Ollama's hosted infrastructure while you keep using the local Ollama API at `http://localhost:11434`. You do not need a separate provider, base URL, or API key in Ollama Client.

:::caution[Cloud is not local]
Prompts, chat context, attached images, page content, tool results, and any other input sent to a `:cloud` model leave your device and are processed by Ollama's cloud service. Use a local model when the conversation must remain on your hardware.
:::

## Set up Ollama Cloud

1. Install or update [Ollama](https://ollama.com/download).
2. Sign in through the Ollama app, or run:

   ```bash
   ollama signin
   ```

3. Confirm that a cloud model works through Ollama itself:

   ```bash
   ollama run minimax-m3:cloud
   ```

4. Open Ollama Client and refresh the model menu.
5. Select a model carrying the **Cloud** badge and start chatting.

The model is served through your normal Ollama provider. Nothing large is downloaded to your computer.

## Automatic discovery

Recent Ollama versions expose hosted recommendations through the local daemon. Ollama Client combines those `:cloud` recommendations with the locally installed models returned by `/api/tags`, so both appear in the same model menu.

The Cloud badge shows the required plan when Ollama reports one. Hover it to see Ollama's model description. The response is cached briefly to avoid repeatedly polling the experimental endpoint.

Older Ollama versions may not provide cloud recommendations. That does not break local discovery: Ollama Client silently keeps the ordinary local model list.

## If a cloud model does not appear

First update Ollama and make sure you are signed in. Then verify the model in a terminal:

```bash
ollama run minimax-m3:cloud
```

If the model works there but is still absent from Ollama Client:

1. Open **Settings → Providers → Ollama**.
2. Add the exact model name, such as `minimax-m3:cloud`, under **Model IDs**.
3. Refresh the model menu and select it.

This manual entry is only a compatibility fallback. It does not download or delete a model.

## Output-token setting

Leave **Maximum Tokens** on **Auto (recommended)**. Ollama Client omits the wire-level output limit in Auto mode so the daemon can choose a valid value for either a local or hosted model.

Older releases sent their internal `-1` sentinel to Ollama. Some cloud models reject that value with HTTP 400. You should no longer need to replace it with a large positive number manually.

## Troubleshooting

### HTTP 401 or sign-in error

Open the Ollama app or run `ollama signin`, then retry the same model with `ollama run <model>:cloud`.

### HTTP 400 while generating

Reset **Maximum Tokens** to Auto. Also start a new text-only chat if the selected cloud model does not support images or other input from the current conversation.

### Model requires another plan

The Cloud badge may include `free`, `pro`, or another plan reported by Ollama. Availability and usage limits are controlled by your Ollama account. See [Ollama Cloud](https://docs.ollama.com/cloud) for current account and usage details.

### Local models work but cloud models do not

That confirms the local daemon is reachable, but not that it is authenticated for cloud inference. Test the exact `:cloud` model with the Ollama CLI; its error is usually the clearest sign-in or plan diagnostic.

## Related

- [Provider Setup](/guides/provider-setup/)
- [Privacy](/concepts/privacy/)
- [Ollama Cloud documentation](https://docs.ollama.com/cloud)
- [MiniMax M3 on Ollama](https://ollama.com/library/minimax-m3%3Acloud)

---

# Context, Images, and Tools

Source: https://www.ollamaclient.in/guides/context-and-tools/
Markdown: https://www.ollamaclient.in/guides/context-and-tools.md
Description: How Ollama Client adds files, images, tabs, selected text, and local tool calls to a chat turn.

Ollama Client has two ways to add context to a chat turn.

- **Explicit context**: you attach files or images, select tabs, or capture selected text before sending.
- **Tool-called context**: a tool-capable model asks the extension for context or web results while it is generating an answer.

Both paths run through the extension. What leaves the device depends on the provider endpoint you selected.

## Manual context

Manual context is best when you know exactly what the model should use.

| Context | How it is added | Notes |
|---|---|---|
| Files | Composer attachment button or drag/drop | Text is extracted, chunked, embedded, and available to RAG/file search. |
| Images | Composer attachment button, drag/drop, or paste | Enabled only for vision-capable models. PNG, JPEG, and WebP are supported. |
| Current tabs | Context tray in the composer | Selected tab text is injected into the prompt up to your configured context limit. |
| Selected text | Selection overlay or browser selection capture | Useful for short page snippets that should stay visible in the prompt. |

Manual context remains useful even with tool calling. It gives the user direct control and works with models that do not support tools.

## Tool-called context

When the selected model supports tool calling, the background worker can offer a small set of local tools. The model can call them when the prompt asks about browser or local context.

Examples:

- "What is this page about?"
- "Summarize the YouTube video I am watching."
- "Compare the open docs tabs."
- "Find where we discussed embedding limits."
- "Answer from my uploaded files."
- "Search the web for the latest release notes."

Page selections use an explicit handoff: highlight text and choose **Ask Local LLM** from the context menu to place it in the sidebar composer. The temporary handoff is cleared after insertion; it is not a model-callable tool or a history of page selections.

Current internal tools:

| Tool | Reads |
|---|---|
| `current_tab` | The active tab's extracted text, including supported video transcripts. |
| `list_tabs` | Current readable tab ids, titles, and URLs. |
| `read_tab` | A specific readable tab by id or title/URL query. |
| `file_search` | Uploaded/indexed files. |
| `rag_search` | Local chat memory and indexed conversation context. |
| `web_search` | Current web results through the configured search provider. |

The tool loop is provider-agnostic. Ollama receives native tool definitions, while OpenAI-compatible providers receive OpenAI-style tool definitions.

## Web search

When configured and active, tool-capable models see one tool: `web_search({ query, count? })`. The selected backend remains a settings/runtime concern, so adding or removing a provider does not change the model-visible interface.

Supported search providers:

| Provider | Endpoint | Limit behavior |
|---|---|---|
| SearXNG | User-configured self-hosted endpoint, usually `http://localhost:8080` | Uses `pageno`; the extension can fetch 1-3 pages, de-dupe URLs, then cap results before returning them to the model. |
| Brave Search | `https://api.search.brave.com/res/v1/web/search` | Uses Brave's `count` query parameter. |
| Tavily | `https://api.tavily.com/search` | Uses Tavily's `max_results` request field. |

Search provider API references:

- [SearXNG Search API](https://docs.searxng.org/dev/search_api.html)
- [Brave Search API](https://api-dashboard.search.brave.com/app/documentation/web-search/responses)
- [Tavily Search API](https://docs.tavily.com/documentation/api-reference/endpoint/search)

The system guidance tells models to use web search for current/time-sensitive facts and cite returned URLs. Result titles and snippets are treated as untrusted text, capped, and shown in the reasoning trace.

## What the user sees

Tool runs appear in the reasoning trace. The trace shows:

- which tool ran,
- whether it is running, done, or failed,
- the arguments the model passed,
- sources or a short output preview,
- whether a long result was trimmed before being sent back to the model.

Recovered errors stay in the expanded trace instead of being pinned as the active status. For example, if a model uses an old tab id, `read_tab` refreshes the tab list and can fall back to the currently active readable tab.

## Images

Image input is gated by the selected model's resolved `vision` capability.

- Vision-capable model: the composer accepts supported images and sends them with the chat message.
- Non-vision model: the composer blocks image attach and points to the model capability override.

Images are stored locally with the conversation so the message can be reopened with previews. Provider adapters translate the attachment into each provider's wire format:

- Ollama: base64 image payloads through the native image field.
- OpenAI-compatible providers: `image_url` content parts.

## Limits and privacy

Tool and image data are not sent anywhere until a chat turn is sent to a provider.

- With a local provider, context stays on your machine or local network.
- With a remote provider, prompts, extracted context, tool results, files snippets, and images included in that turn are sent to that endpoint.
- Tool results are trimmed before being returned to the model so a long page or transcript does not dominate the prompt.
- Web search provider config is device-local. API keys are masked in settings and should not appear in logs.
- Browser tab access can be disabled from settings or the composer context tray.
- Chat-memory indexing is off on new profiles until you explicitly enable it.
- URL exclusions still apply to tab tools and manual tab context.

Tool calls do not create separate chat-history rows. The persisted conversation keeps the final answer and trace metadata.

## Model support

Tool calling and image input depend on the selected model and provider.

- If a provider reports model capabilities, Ollama Client uses that metadata.
- If it cannot, provider defaults are conservative.
- You can override a model's capabilities from the model menu.

For tool use, prefer models that reliably call tools when asked. If a model says it cannot access the browser instead of using tools, check that its tool capability is enabled and try a stronger tool-calling model.

---

# Fix Ollama CORS errors in browser extensions

Source: https://www.ollamaclient.in/guides/troubleshooting/ollama-cors-error/
Markdown: https://www.ollamaclient.in/guides/troubleshooting/ollama-cors-error.md
Description: Resolve 403 Forbidden and CORS errors when Ollama Client connects to a local Ollama server from Chrome or Firefox.

A `403 Forbidden` or CORS error usually means Ollama rejected the browser
extension origin. This is most common in Firefox, where extensions cannot use the
same declarative network request CORS workaround that Chromium supports.

## Choose a setup method

olc is optional. It automates the same Ollama environment configuration shown
in the manual instructions below.

### Automatic setup with olc

Install **olc**, then let it add and verify the browser-extension origins:

```bash
# macOS / Linux
curl -fsSL https://ollamaclient.in/olc.sh | sh
olc
olc --check --json
```

```powershell
# Windows PowerShell
irm https://ollamaclient.in/olc.ps1 | iex
olc
olc --check --json
```

These installers pipe a remote script into your shell. To pin the release and verify it first, see [installing without piping to a shell](/developers/#install-without-piping-to-a-shell).

Ollama itself must already be installed. `olc --debug` provides foreground
diagnostics. Use `olc --lan` only when trusted-network access is intended;
Ollama has no native API authentication. olc passes `OLLAMA_*` only to a
standalone Ollama child; the values disappear when that process stops and olc
does not write them to the system or user environment.

On macOS, if the running Ollama app lacks the required origins, olc gracefully
quits it and starts a standalone Ollama process. Stop that standalone process
before reopening the app; the app's own configuration remains unchanged.

If olc reports that an app, tray process, or protected service must be configured
through its owner, use the matching manual setup below.

### Manual setup without olc

#### macOS Ollama app

Set the launch-session environment, fully quit Ollama, and reopen it:

```bash
launchctl setenv OLLAMA_ORIGINS "chrome-extension://*,moz-extension://*"
osascript -e 'quit app "Ollama"'
open -a Ollama
```

This value lasts until logout. Remove it with
`launchctl unsetenv OLLAMA_ORIGINS`.

#### macOS or Linux shell server

Stop the existing server, then start a shell-owned server with the variable:

```bash
export OLLAMA_ORIGINS="chrome-extension://*,moz-extension://*"
ollama serve
```

#### Linux systemd service

Create or edit an Ollama service override:

```bash
sudo systemctl edit ollama
```

Add:

```ini
[Service]
Environment="OLLAMA_ORIGINS=chrome-extension://*,moz-extension://*"
```

Reload and restart:

```bash
sudo systemctl daemon-reload
sudo systemctl restart ollama
```

#### Windows PowerShell

Set the environment variable before starting Ollama:

```powershell
$env:OLLAMA_ORIGINS="chrome-extension://*,moz-extension://*"
ollama serve
```

For a persistent user variable:

```powershell
[Environment]::SetEnvironmentVariable("OLLAMA_ORIGINS", "chrome-extension://*,moz-extension://*", "User")
```

Restart Ollama after changing the value.

### Verify the manual setup

Confirm that Ollama answers a request carrying an extension origin:

```bash
curl -i -H 'Origin: moz-extension://cors-probe' \
  http://127.0.0.1:11434/api/version
```

An HTTP `200` response means Ollama accepted the origin. A `403` means the
running process did not inherit `OLLAMA_ORIGINS`; fully stop it and repeat the
matching platform steps.

## Chrome vs Firefox

Chromium browsers can use extension-side CORS rules in more cases. Firefox is
stricter, so the Ollama server often needs the explicit `OLLAMA_ORIGINS` value.

## OpenAI-compatible local servers

LM Studio, llama.cpp, vLLM, LocalAI, and KoboldCPP may have their own
CORS/origin settings. If you see a local `401` or `403` from one of these
servers, check that its API server accepts browser-extension origins and that
the base URL in Ollama Client points to the local OpenAI-compatible endpoint.

## FAQ

### Is this an API key problem?

Usually no for local providers. A local `403` often means origin/CORS rejection,
not bad credentials.

### Do I need both Chrome and Firefox origins?

Using both is convenient if you test the extension in multiple browsers.

### Is `OLLAMA_ORIGINS="*"` safe?

Prefer the narrower browser-extension origins shown above. Use broader origins
only if you understand the local network exposure.

---

# Understand error reports

Source: https://www.ollamaclient.in/guides/troubleshooting/error-reports/
Markdown: https://www.ollamaclient.in/guides/troubleshooting/error-reports.md
Description: Read Ollama Client error codes, incident IDs, failure phases, and privacy-safe diagnostic details.

Ollama Client error reports are designed to give users a direct recovery step
and give maintainers enough technical context to reproduce a bug without
collecting telemetry.

## Error code versus incident ID

An **error code** identifies the failure category. For example,
`OLC-PROVIDER-DISABLED` always means the selected provider is disabled.
Maintainers can use the code to find the relevant recovery path and code branch.

An **incident ID**, such as `INC-1F9F2263`, is a short random correlation token
created locally for one error. It is not an encoded error message, account ID,
server log ID, or tracking identifier. There is no remote database where an
incident ID can be looked up.

The incident ID is useful when a local diagnostic event was recorded with the
same support code. It lets a maintainer match the failed chat message and issue
draft to the corresponding event in a support bundle, and distinguish two
otherwise identical failures. Local diagnostic events expire after seven days.

## How to triage a report

Read these fields in order:

1. **Error code** identifies the stable failure category.
2. **Suggested recovery** shows the action offered to the user.
3. **Provider, model, base URL, status, and failure phase** locate the failing
   request stage. Credentials, query parameters, and URL fragments are removed.
4. **Automatic checks** show whether the provider was enabled, reachable, and
   advertising the selected model when **Open an issue** was clicked.
5. **Incident ID** can be matched to the `supportCode` in an attached support
   bundle.
6. **Extension, browser/version, and OS family** help isolate release-specific
   and browser-specific behavior.

The support bundle is available under **Help → Diagnostics & support**. Users
can select **Preview support bundle**, review its contents, then
**Download bundle** and drag the JSON file into the GitHub issue. Attaching it
is optional, but its safe event sequence often makes diagnosis faster. Nothing
is uploaded automatically, and GitHub does not allow the extension to attach a
local file silently. Chat errors run privacy-safe diagnostics locally and
include a **Copy diagnostics** button beside **Open an issue**. Paste the copied
support-bundle JSON into a new issue if you prefer to create it manually. The
inline copy includes only privacy-safe events correlated with the current chat
session; the prefilled issue contains a concise summary and matching event
highlights. The full retained event history remains available from the
Diagnostics & support settings card.

## Error-code reference

| Code | Meaning | First check |
| --- | --- | --- |
| `OLC-PROVIDER-DISABLED` | Selected provider is disabled | Enable it in Model behavior |
| `OLC-PROVIDER-UNREACHABLE` | Endpoint could not be reached | Provider process and base URL |
| `OLC-PROVIDER-HTTP` | Provider returned an unclassified HTTP error | Status and provider logs |
| `OLC-MODEL-NOT-FOUND` | Requested model does not exist | Selected model name |
| `OLC-RESOURCE-NOT-FOUND` | Provider endpoint or resource is missing | Base URL and API path |
| `OLC-MODEL-NOT-LOADED` | Model exists but is not loaded | Load the model in the provider |
| `OLC-CORS-BLOCKED` | Browser origin was rejected | Provider CORS/origin settings |
| `OLC-AUTH-FAILED` | Remote provider rejected credentials | API key and endpoint |
| `OLC-PAYMENT-REQUIRED` | Hosted provider requires credits | Provider account balance |
| `OLC-CONTEXT-TOO-LARGE` | Input exceeds the context window | Reduce chat/context size |
| `OLC-INPUT-UNSUPPORTED` | Model cannot handle the input type | Model capabilities |
| `OLC-OUT-OF-MEMORY` | Provider could not allocate enough memory | Smaller model or more memory |
| `OLC-MODEL-LOADING` | Model is still loading | Wait, then retry |
| `OLC-RATE-LIMITED` | Provider is throttling requests | Retry timing |
| `OLC-PROVIDER-OVERLOADED` | Provider is temporarily overloaded | Wait, then retry |
| `OLC-PROVIDER-TIMEOUT` | Request exceeded its time limit | Provider health and model speed |
| `OLC-STREAM-DROPPED` | Connection ended during response streaming | Provider logs and network |
| `OLC-UNKNOWN` | Failure did not match a safe known category | Phase, status, and reproduction |

## Privacy boundaries

Issue drafts are generated locally and opened for review. They do not include
prompts, responses, page or file content, file names, API keys, credentials,
raw provider response bodies, or console logs. Browser detection is best effort
because Chromium-based browsers may deliberately identify as Chrome; users
should edit the browser field if it is wrong.

---

# Local-first privacy in Ollama Client

Source: https://www.ollamaclient.in/concepts/privacy/
Markdown: https://www.ollamaclient.in/concepts/privacy.md
Description: How Ollama Client stores chats, files, settings, permissions, and model requests for private local AI workflows.

Ollama Client is designed around local-first AI chat. The extension stores user
data in browser storage and sends prompts only to the provider endpoint you
configure.

## What stays on your device?

These data types are stored locally by the extension:

- Chat sessions and messages
- Uploaded-file metadata and local retrieval indexes
- Knowledge sets and embeddings
- Provider settings and model mappings
- Provider-opaque continuation blocks needed to resume signed or encrypted reasoning
- Web-search configuration
- Browser permission state and feature settings
- A bounded, seven-day local diagnostic event buffer containing technical codes and timing only

Chat history uses SQLite-in-WASM persisted to IndexedDB. Vector storage and
knowledge sets use local IndexedDB storage.

Some reasoning-capable remote providers return signed or encrypted continuation
blocks that must be echoed back unchanged during tool use. This is part of the
[Anthropic extended-thinking](https://platform.claude.com/docs/en/build-with-claude/extended-thinking)
and [OpenRouter reasoning](https://openrouter.ai/docs/guides/best-practices/reasoning-tokens)
protocols. Ollama Client stores those opaque blocks locally with the related
assistant message, separately from the reasoning text shown in the UI. They are
never rendered or written to diagnostic logs. Because they are part of chat
continuity, they are included in chat-history backups alongside the messages
they belong to.

## What can leave your device?

Prompt data leaves your device only when needed for the provider you choose.

If your provider is local, such as Ollama at `http://localhost:11434` or LM
Studio at `http://localhost:1234/v1`, requests stay on your machine. If you
configure a remote OpenAI-compatible server, prompts and selected context are
sent to that remote server.

The OpenRouter preset uses its OpenAI-compatible endpoint and adds only static
Ollama Client application-attribution headers. It does not send the URL of the
page you are viewing as attribution. OpenRouter can route requests to other
model providers, so their retention and processing policies also apply.

Optional web search can contact the backend you configure, such as SearXNG,
Brave Search, or Tavily.

## Browser permissions are explicit

Browser features such as tab access, recently closed sessions, screenshots, and
downloads are controlled through extension permissions and visible settings. The
model-tools inventory in **Privacy & permissions** shows which tools are
available and why.

## Page and tab context are scoped

Ollama Client can read current-page or tab context only when the related setting
and browser access allow it. Excluded and unreadable URLs are filtered before
content is used for chat or model-callable tools.

## Uploaded files and local RAG

Uploaded files are processed locally for retrieval. The extension can store
chunks and embeddings in browser storage so future chats can retrieve relevant
context.

## Web search is optional

Web search is off unless configured. When enabled, the model can use the selected
web-search backend through the tool system. API keys are stored locally and are
not logged by the extension.

## Diagnostics stay local

The extension records up to 200 content-free diagnostic events for seven days,
with a hard serialized-data ceiling of about 128 KiB. Events are batched before
device-local browser storage writes to avoid write amplification. The pending
in-memory batch is separately capped at 50 events and about 32 KiB serialized.
Events can include an operation name, request ID, status, duration, retry state,
and support code. They cannot include prompts, responses, file or page content,
credentials, headers, full endpoints, cookies, or browser history.

In **Help → Diagnostics & support**, you can run local self-tests and preview
the complete support bundle before copying or downloading it. Nothing is
uploaded automatically. Clearing diagnostic history removes the local event
buffer.

## Reset and backup

The Data & backup settings let you export or reset local data. Reset maps include
provider configuration and API keys so a provider reset removes stored secrets.

## FAQ

### Is Ollama Client private by default?

It is local-first by default. Privacy still depends on the provider endpoint and
optional features you enable.

### Does Ollama Client index browser history automatically?

Browser knowledge features are optional and permission-gated. Keep them disabled
if you do not want browser history or bookmarks available for local retrieval.

### Where should I check permissions?

Open **Privacy & permissions** in settings. It shows browser permissions, tool
families, and per-model tool availability.

---

# Architecture

Source: https://www.ollamaclient.in/concepts/architecture/
Markdown: https://www.ollamaclient.in/concepts/architecture.md
Description: Implementation details, tradeoffs, and constraints for Ollama Client.

This document describes the current implementation and highlights tradeoffs, assumptions, and known constraints.

## Entry points

WXT auto-discovers entry points under `src/entrypoints/`. Each entry is a thin shell that delegates to a feature module elsewhere in `src/`, so the WXT-facing surface stays small and the actual logic lives where the rest of the code can import it.

| WXT entry point | Output type | Delegates to |
|---|---|---|
| `src/entrypoints/background.ts` | service worker | `src/background/index.ts` |
| `src/entrypoints/sidepanel/index.tsx` | extension page | `src/sidepanel/index.tsx` (React root) |
| `src/entrypoints/options/index.tsx` | extension page | `src/options/index.tsx` (React root) |
| `src/entrypoints/print/main.ts` | extension page | self-contained (print-to-PDF helper) |
| `src/entrypoints/content.ts` | runtime content script | `src/contents/index.ts` (injected only when page content is requested) |
| `src/entrypoints/selection-button.content.tsx` | manifest content script | tiny selection detector; asks the background to inject the UI |
| `src/entrypoints/selection-overlay.content.tsx` | runtime content script | shadow-DOM selection UI, injected into the requesting frame |

The WXT shells are intentionally minimal — `background.ts` is a 4-line import, `content.ts` is a 6-line lazy-import. Real work lives in the feature modules:

- `src/background/` — handler dispatch, provider streaming orchestration, `onInstalled` migrations
- `src/sidepanel/` — chat surface React app, opens the runtime port
- `src/options/` — settings React app
- `src/contents/` — selection capture, page extraction helpers, URL filtering

### Content-script loading boundary

Only `selection-button.js` is registered in the production manifest. It watches
for a valid selection without mounting React, loading translations, or injecting
styles. The first valid selection sends the allowlisted
`LOAD_SELECTION_OVERLAY` event; the background injects
`selection-overlay.js` into that exact tab frame.

The injected overlay has its own Tailwind source boundary and a generated
`selection_button`-only i18n asset for each supported locale. It fetches only
the active locale after injection, falls back to English, and treats a missing
locale asset as non-fatal. It does not carry the full application stylesheet or
translation trees.

Injection is a two-part handshake. The background acknowledges a versioned
request containing request, tab, frame, and document identity; the injected UI
then emits a ready event only after its configuration, locale, mount, and first
render complete. A failed injection or missing ready event releases the
bootstrap latch after three seconds, so a later selection can retry instead of
disabling the feature for the rest of the frame's lifetime.

The overlay also defers provider-model discovery until the user opens the
expanded panel. Showing the initial toolbar does not fetch the model catalog.

The page extractor is runtime-only. `requestPageContentWithRecovery()` first
tries the existing receiver, injects `content.js` when none exists, then retries.
This keeps Defuddle, Readability, transcript extraction, and enhanced extraction
logic off ordinary page startup.

Keep manifest content scripts small. They must not import the app UI system,
full locale tables, content parsers, provider implementations, or persistence
code.

### Bundle budgets

`pnpm bundle:report` measures the Chrome production build. `pnpm bundle:check`
and `pnpm bundle:check:firefox` enforce target-specific budgets after packaging.
CI packages and checks both browsers.

The enforced surface includes:

- unpacked and ZIP size;
- manifest content scripts and the selection bootstrap;
- the lazy selection overlay and background;
- initial sidepanel and options assets;
- the largest generated JavaScript chunk;
- byte-identical duplicate image, font, and WASM assets.

Current production measurements are approximately 9.12 MB unpacked / 3.11 MB
ZIP for Chrome and 11.43 MB unpacked / 4.14 MB ZIP for Firefox. The 5.6 kB
selection bootstrap is the only script registered on ordinary pages; the
649.7 kB overlay is runtime-only. These are regression baselines, not targets
to fill.

Firefox is larger mainly because its MV2 persistence owner ships the
`sqlite3-worker1` and `chat-db-worker` assets as roughly 1.3–1.4 MB files,
whereas the Chromium MV3 owner produces roughly 208–224 kB worker assets. The
shared application chunks are nearly the same size. Removing shared features
would therefore not fix most of the browser delta.

Translations load as one locale chunk at a time through
`src/i18n/locale-loader.ts`; extension-store metadata under `public/_locales`
continues to be generated from the same locale source files.

The options shell keeps the default General tab eager and lazy-loads the
inactive settings tabs. Backup/restore loads its ZIP implementation only when
an import or export starts. These boundaries keep inactive settings and export
code out of the initial options-page graph without delaying the first tab.

Store icons are emitted at their requested 16, 32, 48, 64, and 128 pixel sizes
instead of packaging one oversized source icon. PDF.js and its approximately
1.3 MB worker remain intentional: PDF extraction still needs them, and the
worker is already isolated from ordinary page startup. Official sqlite-wasm is
the only SQLite engine in store builds. `sql.js` is a development-only fixture
writer for measurement pages that are stripped from production builds.

## System responsibilities

**Sidepanel**

- Chat interaction UX
- Session display and branch navigation
- Streaming state updates
- Local chat actions (edit, fork, delete, export)

**Options**

- Provider configuration
- Model parameters
- Embedding / RAG configuration
- Feature toggles and diagnostics

**Background worker**

- Provider resolution and streaming orchestration
- Tool-loop execution, approval gating, and loop checkpointing
- RPC server for provider configuration, connection tests, and diagnostics
- Model management handlers
- Embedding generation handlers for file chunks
- Browser-level APIs (DNR / CORS rules, context menu, alarms)

**Content scripts**

- Selected-text capture
- Page extraction entrypoints for browser-context workflows

### Startup recovery supervision

Database startup has an explicit dependency chain: application lifecycle flags
→ persistence-owner readiness → data-shape recovery → durable workflow
recovery. Owner readiness includes interrupted whole-database replacement, so
provider and embedding migration cannot start beside it. Portable backup-import
recovery, provider-storage migration, and embedding dimension migration then run
one at a time because each can rewrite state consumed by its successor. Only
after all three settle does workflow recovery begin, with a concurrency cap of
two for independent durable jobs.

Every startup task receives an `AbortSignal` and has a 120-second deadline. A
deadline aborts the task, but the supervisor does not start that worker's next
task until the aborted promise settles. Settlement is the cancellation
acknowledgment: an already-issued storage write may finish, but no successor can
read or mutate the same state beside it. Backup and migration loops check the
signal between mutation boundaries; active turn, ingestion, and model-pull
recovery also stop their provider/embedding work. Supervisor expiry leaves a
durable user job resumable on the next worker boot rather than recording a user
cancellation.

Timeout request and cancellation acknowledgment are recorded as bounded,
content-free diagnostic events (`STARTUP_RECOVERY_TIMEOUT` and
`STARTUP_RECOVERY_CANCELLED`). Task identifiers and elapsed time are included;
stored data, provider URLs, and errors are not.

### Message-subtree deletion

Deleting a message branch is one SQLite transaction. The repository discovers
all descendants while holding the transaction lease, repairs the session's
active-leaf pointer when needed, deletes attachment rows, and then deletes the
messages. A worker loss therefore cannot commit only part of the SQLite state,
and a concurrent append cannot escape descendant discovery.

Embedding vectors remain in Dexie and cannot participate in the SQLite commit.
The transaction returns the deleted message ids so the caller can perform that
derived-data cleanup afterward; vector deletion is idempotent and does not
change the canonical chat state.

## Data flow

1. User sends a prompt in the sidepanel.
2. UI opens a runtime port (`MESSAGE_KEYS.PROVIDER.STREAM_RESPONSE`) to the background.
3. Background receives `CHAT_WITH_MODEL` and resolves the provider using the model mapping.
4. Provider starts streaming tokens back to the background.
5. If the model requests a tool, the background runs the tool loop — gating on approval where the tool's risk requires it, checkpointing at each boundary — and continues the stream with the tool result appended.
6. Background relays chunks to the UI through port messages.
7. UI applies optimistic stream updates. The durable background turn owner
   persists assistant state and sends snapshots for reconnect/reconciliation.
8. Optional embedding pipelines index chat / file content for retrieval.

```mermaid
flowchart TD
    A["Sidepanel UI (React)"] --> B["Runtime Port (STREAM_RESPONSE)"]
    B --> C["Background Worker"]
    C --> D["ProviderFactory resolve by model mapping"]
    D --> E["Ollama"]
    D --> F["LM Studio"]
    D --> G["llama.cpp"]
    D --> N["OpenAI-compatible / Anthropic"]
    E --> H["Chunk Stream"]
    F --> H
    G --> H
    N --> H
    H --> T{"Tool call requested?"}
    T -->|yes| U["Tool loop: approval gate, execute, checkpoint"]
    U --> C
    T -->|no| I["UI Stream State Update"]
    C --> J["SQLite Chat Store (durable turn owner)"]
    C --> K["Optional RAG Pipeline"]
    K --> L["Embedding Strategy Chain"]
    L --> M["Vector store"]
```

Configuration traffic does not use this path — see [Provider RPC boundary](#provider-rpc-boundary).

## Provider RPC boundary

Token streaming uses runtime ports, but everything else that crosses the extension-page ↔ background boundary — reading provider configuration, testing a connection, listing models, running diagnostics — goes through versioned request/response contracts in `packages/contracts/src/` rather than ad-hoc message keys.

| File | Role |
|---|---|
| `packages/contracts/src/rpc.ts` | Protocol version, `RpcMethod` / `RpcErrorCode` enums, request and response envelopes |
| `packages/contracts/src/provider-rpc.ts` | Provider request/result schemas and the provider entries in the typed `RpcMap` |
| `packages/contracts/src/model-rpc.ts` | Model lifecycle, catalog, and embedding method schemas |
| `packages/contracts/src/diagnostics-rpc.ts` | Diagnostics method schemas |
| `src/protocol/rpc-registry.ts` | Per-method schema, sender policy, timeout, and operation metadata |
| `src/protocol/extension-client.ts` | Validated client used by extension pages |
| `src/background/rpc-server.ts` | Authorization, validation, dispatch, and safe error mapping |
| `src/lib/providers/provider-rpc-service.ts` | Background-owned implementation of the provider operations |
| `src/lib/providers/model-rpc-service.ts` | Background-owned implementation of model and embedding operations |

Why a separate boundary instead of more message keys:

- **Both ends validate.** A method is registered once with its schemas; neither side trusts the other's payload shape.
- **Errors are enumerated, not stringly typed.** `invalid_request`, `forbidden`, `not_found`, `provider_failed`, `timeout`, `internal`. Results carry i18n message keys plus safe fallback text, never raw provider errors that might embed a credential.
- **Queries have no write side effects.** Methods registered as queries must not persist anything, so a client timeout cannot commit stale state. Derived state is persisted only after the caller receives and accepts the result.
- **Cancellation is end-to-end.** A client timeout sends `app-rpc-cancel`; the server aborts the matching request and the provider's model-discovery `fetch` receives that `AbortSignal`.

The provider, model, embedding, and diagnostics request/response migration is
complete. New request/response work is added as an `RpcMethod`; it must not add
another runtime message key.

Model lifecycle RPC coordinates policy through an optional provider-owned
`modelLifecycle` port. Ollama owns `/api/ps`, keep-alive eviction, and no-op
generation warmup; LM Studio owns its loaded-model and unload routes. The RPC
service applies warmup settings and cooldowns but does not branch on provider
ids or construct vendor URLs. Providers without the corresponding operation
return an unsupported/no-op result instead of receiving an Ollama-shaped call.

Streaming ports, one-way browser/app events, and the content-script-reachable
`PROVIDER.GET_MODELS` read intentionally remain outside RPC. RPC envelopes are
extension-page-only, while the model read is needed by the selection overlay.
Every retained runtime message and port is classified by transport, operation,
and allowed source in `src/protocol/runtime-transport-registry.ts`. The two
remaining `OLLAMA.*` values are compatibility port names, not duplicate
request/response handlers.

## Model capabilities

Feature availability is resolved per selected model. The capability layer covers text chat, image input, tool calling, reasoning output, embeddings, and context length.

Resolution runs in four layers, highest priority first:

1. **User override** — what the user set by hand in the model menu. Always wins.
2. **Empirical probe** — `capability-probe.ts` sends one trivial tool-call request and records whether the model actually emitted a native tool call. This is evidence from the real server, so it beats static metadata, but never the user's word. It is how models on providers with no capability metadata (effectively everything OpenAI-compatible) get `toolCalling` detected without hand-toggling.
3. **Model metadata** — real tags where the provider reports them (Ollama `/api/show`), or partial inference (LM Studio model type).
4. **Provider default** — the model itself was not inspected.

Each resolved capability carries a confidence value (`high` / `medium` / `low`) alongside its source, so the UI can distinguish "this model reports vision" from "we assumed it."

This keeps capability-sensitive UI from guessing. For example:

- Image attach is enabled only for models that resolve `vision: true`.
- Internal tools are offered only to models that resolve `toolCalling: true`.
- Embedding models are kept out of normal chat-model selectors.

Users can override capabilities from the model menu when a provider cannot report them reliably.

## Tool calling architecture

Tool calling is handled in the background worker, between provider streaming and UI persistence.

1. The handler resolves the selected model and checks whether tool calling is enabled for that model.
2. Tool definitions are loaded from the `ToolRegistry`.
3. The provider receives the chat request with native tool definitions.
4. If the model requests a tool, the stream loop executes it locally and appends a tool result to the working provider history.
5. The loop continues until the model returns a normal answer or hits the iteration cap.

Models that cannot emit native tool calls are handled by a text protocol in `src/lib/tools/non-native/`, which parses tool invocations out of the model's prose. The two loops (`stream-chat-with-tools.ts` and `stream-chat-with-non-native-tools.ts`) are separate implementations with the same lifecycle, approval, and checkpoint contract.

Tool results are trimmed before they are fed back to the model. The durable turn
owner persists the final assistant answer and trace metadata, not intermediate
provider tool messages. The UI folds validated events into ephemeral Zustand
state; it does not persist durable stream rows.

### Internal tools

Tools are registered in `src/lib/tools/internal/internal-tool-source.ts` — appending to that list is the whole registration step; the registry, adapters, loop, and trace UI need no change. Browser-dependent tools check both API support and the live optional permission before they are offered.

| Tool | Risk | Purpose |
|---|---|---|
| `rag_search` | low | Search local chat memory / indexed conversation context. |
| `file_search` | low | Search uploaded and indexed files. |
| `current_tab` | low | Read the active tab's extracted text, including supported video transcripts. |
| `list_tabs` | low | List readable open tabs with current ids, titles, and URLs. |
| `read_tab` | low | Read a specific open tab by id or title/URL query. Stale ids are refreshed and can fall back to the active readable tab. |
| `list_tab_groups` | low | List the browser's tab groups. |
| `read_tab_group` | low | Read the readable tabs inside one group. |
| `list_reminders` | low | List pending reminders. |
| `web_search` | medium | Search the live web through the configured search provider. |
| `get_recent_history` | medium | Query recent browsing history. |
| `search_bookmarks` | medium | Search saved bookmarks. |
| `list_recently_closed` | medium | List recently closed tabs and windows. |
| `list_synced_sessions` | medium | List tabs open on the user's other synced devices. |
| `restore_session` | medium | Reopen recently closed tabs or windows. Returns no page content, but it acts on the browser and leaves a visible trace. |
| `capture_screenshot` | medium | Capture the visible area of the active tab. |
| `save_artifact` | medium | Persist a generated artifact to the chat. |
| `schedule_reminder` | medium | Schedule a reminder via browser alarms. |
| `cancel_reminder` | high | Permanently remove a pending reminder. Destructive, so it is confirmed on every call. |

### Approval and risk policy

There is no single hardcoded confirmation flag. Each tool declares a risk level and the policy in `src/lib/tools/approval/` derives the prompt from it:

| Risk | Policy |
|---|---|
| `low` | Runs automatically; never prompts. |
| `medium` | Confirmed once per chat — an approval grants the rest of that chat. |
| `high` | Confirmed on every call, with "always allow" offered. |
| `critical` | Always confirmed; no grant of any scope is offered. |

Grants are keyed per **tool × origin**, not per tool, so an approval for one site never silently covers another. Only `http(s)` origins are grantable; internal pages (`chrome://`, `about:`, `moz-extension://`) are already blocked by the tab-access filters, and a grant for them would be meaningless — a missing or unparseable origin means "no grant applies", never a fallback to the wildcard. Persisted "always" grants live in `approval-grants.ts`; "this chat" grants live in a background session map that dies with the worker.

### Loop durability across worker restarts

MV3 can terminate the service worker mid-turn, including while a tool loop is waiting on the user. Active loops therefore checkpoint into the SQLite `tool_loop_runs` table at every model, tool, and approval boundary, and force-flush before awaiting an approval — the one point where the loop can sit idle long enough to be killed.

The sidepanel reconnects using the same request id after a restart and the loop resumes from its checkpoint. Completed runs delete their checkpoint; `startup.ts` prunes stale ones on boot. This checkpoint/reconnect pair is a contract — changing tool execution without preserving it turns a worker restart back into a lost turn.

### Web search adapter seam

Web search is intentionally provider-agnostic at the model boundary. The model sees only `web_search({ query, count? })`; the backend is resolved from device-local settings at runtime.

Implementation paths:

- `src/lib/tools/web-search/types.ts` defines `WebSearchBackend`, `WebSearchProviderConfig`, and normalized `WebSearchResult`.
- `src/lib/tools/web-search/backends/` contains provider adapters for SearXNG, Brave Search, and Tavily.
- `src/lib/tools/web-search/registry.ts` is the backend registry/factory seam.
- `src/lib/tools/web-search/web-search-tool-source.ts` exposes the tool only when enabled and valid.
- `src/features/web-search/` owns the settings UI and chat-toolbar toggle.

Provider behavior:

| Provider | Request shape | Result cap behavior |
|---|---|---|
| SearXNG | `GET /search?q=...&format=json&pageno=N&safesearch=...` | No API-side count; fetch configured pages, de-dupe, then slice locally. |
| Brave Search | `GET https://api.search.brave.com/res/v1/web/search` with `X-Subscription-Token` | Sends `count`. |
| Tavily | `POST https://api.tavily.com/search` with bearer auth | Sends `max_results`. |

References:

- [SearXNG Search API](https://docs.searxng.org/dev/search_api.html)
- [Brave Search API](https://api-dashboard.search.brave.com/app/documentation/web-search/responses)
- [Tavily Search API](https://docs.tavily.com/documentation/api-reference/endpoint/search)

Search titles and snippets are untrusted data. The tool strips HTML, caps snippets and total output, keeps API keys out of logs, and asks the model to cite returned URLs for current facts.

## Image input

Images are stored as chat attachments and routed only when the selected model supports vision. Provider adapters translate the same chat message into each provider's expected wire format:

- Ollama receives base64 image payloads through its native `images` field.
- OpenAI-compatible providers receive `image_url` content parts.
- Anthropic receives native image content blocks through the Messages API.

Images reuse the existing file metadata path for local persistence and preview display, so no separate image-history store is needed.

## Model selection and provider routing

- The selected model key is persisted under the provider key path (`STORAGE_KEYS.PROVIDER.SELECTED_MODEL`) with legacy reads.
- The model list is built by querying all enabled providers in `useProviderModels`.
- Provider CRUD and routing stay behind the stable `ProviderManager` facade.
  Locked configuration recovery, hydration, defaults, and legacy URL adoption
  live in `provider-config-repository.ts`; scoped model mappings live in
  `provider-mapping-repository.ts`; removed-beta remapping and duplicate
  retention live in `provider-compat-migration.ts`.
- Built-in profiles: Ollama, LM Studio, and llama.cpp. User-added configs keep wire protocol separate from service profile, so OpenRouter uses the OpenAI-compatible wire without being identified as OpenAI, and generic Anthropic-compatible endpoints avoid Anthropic-hosted credential/header assumptions.
- Per-model provider routing is stored via `ProviderStorageKey.MODEL_MAPPINGS`.
- Background routing is performed by `ProviderFactory.getProviderForModel(modelId)`.

### Credential separation

API keys are never stored inside the provider config record. `provider-secret-store.ts` splits each config on write: the public fields go to the normal provider config key, and `apiKey` is stripped into a separate device-local secret map under `STORAGE_KEYS.PROVIDER.SECRETS`. Keys are re-attached only when a provider instance is actually constructed.

Two consequences fall out of that split:

- Secrets stay on the device. Provider configuration can ride `chrome.storage.sync` without syncing credentials, and diagnostics or RPC results that serialize a provider config carry no key.
- The split write is journaled. Writing two storage keys is not atomic, so the store records a journal entry first and replays it on next boot if a crash lands between the two writes — otherwise an interrupted save could orphan a key or leave a config pointing at a secret that was never written.

## Streaming architecture

Streaming occurs over extension runtime ports:

- UI hook — `src/features/chat/hooks/use-chat-stream.ts`
- Background handler — `src/background/handlers/handle-chat-with-model.ts`
- Cancel handling — `abort-controller-registry`

Runtime ports support continuous chunk delivery better than one-shot messages, and cancellation is clean via `AbortController` scoped to active stream keys. Tradeoff: message keys are provider-named (`PROVIDER.*`) with legacy `OLLAMA.*` compatibility.

### Provider reasoning replay

Some providers require that reasoning produced in an earlier turn be handed back verbatim to continue a tool loop — Anthropic's signed thinking and redacted-thinking blocks, OpenRouter's `reasoning_details`. These are opaque, provider-owned values: they cannot be regenerated, reordered, or paraphrased without invalidating the continuation.

They are therefore kept apart from the reasoning text the UI displays. `ChatMessage.thinking` is display-only and safe to render or truncate. `ChatMessage.replayArtifact` is a versioned, size-capped, schema-validated record of the opaque blocks, stored in its own SQLite column and carried through tool-loop checkpoints in original block order.

Before replay, the artifact's `providerId` and `model` are checked against the current turn — a block signed by one provider is not valid input to another. An artifact that fails validation surfaces as a "retry this turn" error rather than being sent anyway. Opaque block contents are never rendered and never logged.

## Storage architecture

- **Chat / sessions / messages / files**: official sqlite-wasm behind one worker
  owned by the persistence host. The facade
  `src/lib/repositories/chat-history.ts` is the only application entry point.
- **Vectors / embeddings**: still on Dexie + IndexedDB via `src/lib/embeddings/storage.ts`. Not yet migrated to SQLite.
- **Settings / provider config**: `@plasmohq/storage` via the `plasmoGlobalStorage` wrapper. Sync-safe settings use `chrome.storage.sync`; device-local keys use `chrome.storage.local`.
- **Settings IA**: six intent tabs — General, Models, Knowledge, Browser, Privacy, and Help. Each tab owns its registry entries under `src/features/settings/registry/`; the public registry preserves stable search ranking and legacy deep links.
- **RAG splitting**: files, chat memory, and live page sources share `src/lib/embeddings/chunker.ts`; the retired parallel text-splitter tree must not be restored.
- **Session organization**: tags are JSON stored in the SQLite `sessions.tags` column and exposed through the chat-session store. Pinned state and per-chat system prompts live on the same table.
- **Tool-loop checkpoints**: the SQLite `tool_loop_runs` table, written at loop boundaries so an MV3 worker restart does not lose an in-flight turn.
- **Schema changes**: forward-only migrations under `src/lib/sqlite/migrations/`, applied by `migration-runner.ts`. Add a column with a migration rather than editing the base schema.
- **Export / restore**: ZIP bundles with versioned manifests; includes the chat SQLite blob plus Dexie dumps for vector embeddings and knowledge sets.

### Chat-history storage

The facade exposes one chat-history API while the implementation stays SQLite-only. Three guarantees follow:

1. **Durability**: on OPFS, a committed SQLite statement is already durable and
   `flushSave()` is a no-op. The compatibility legacy-blob backend debounces a
   full-image IndexedDB write by 1 second; reset, migration, export, and unload
   boundaries force it through `flushSave()`.
2. **Single source**: chat sessions, messages, branches, and file metadata read and write through one normalized SQLite schema.
3. **Export path**: full-data export includes the SQLite database blob, so chat history remains restorable without any Dexie chat dump.

See the [API reference](/reference/lib/repositories/chat-history/) for the full surface.

## RAG / embedding architecture

- Embeddings are generated via a browser-safe strategy chain.
- Content is chunked and indexed locally; chat history uses SQLite, while vector storage remains in IndexedDB via the embeddings storage layer.
- Query-time retrieval uses hybrid search with adaptive weighting.
- The pipeline includes diversity filtering and recency / feedback score hooks.
- Embeddings use a fallback chain: provider-native → shared model → background warmup → Ollama fallback.
- Background model preparation uses provider capabilities where available; Ollama remains the most complete management path.

### Reranking

Reranking is on by default and is a **cosine-similarity re-scorer**, not a cross-encoder. After hybrid search returns candidates, `src/lib/embeddings/reranker.ts` re-scores them by embedding cosine similarity against the query embedding, giving a semantic-only ordering independent of the keyword weight used in stage 1.

A real cross-encoder was attempted via transformers.js / ONNX Runtime and abandoned: MV3's CSP blocked the path it needed, and neither library is a dependency of this project. `config.ts` still accepts the legacy `transformers-js` and `onnxruntime-web` backend strings, purely as a migration shim that collapses them to `cosine`.

:::note[Constraint]
There is no OCR pipeline, and no cross-encoder reranking. Retrieval precision comes from chunking, hybrid weighting, and cosine re-scoring only.
:::

## Why a background worker

- Keeps provider network I/O and long-running operations off the UI thread.
- Centralizes extension APIs that are unavailable or unsafe in UI contexts.
- Simplifies cancellation and stream lifecycle tracking.

## Tradeoffs and decisions

**Legacy naming retained for compatibility**

- *Pro:* avoids migration breakage.
- *Con:* causes confusion in multi-provider code paths.

**SQLite-only chat history**

- *Pro:* one normalized chat store, smaller bundle surface, simpler boot path, and clearer export semantics.
- *Con:* rollback now depends on full-data export or browser-level IndexedDB recovery, not a live Dexie chat fallback.

**Provider-agnostic chat with provider-specific management features**

- *Pro:* fast rollout of multi-provider chat.
- *Con:* uneven feature parity — pull / delete / version are Ollama-centric.

**Local retrieval pipeline over extension constraints**

- *Pro:* privacy-preserving retrieval.
- *Con:* CSP / performance limits prevent full in-browser model / reranker parity.

## Assumptions and constraints

**Assumptions**

- The user can run at least one provider endpoint.
- Endpoint URLs are reachable from extension context.
- Local resources are sufficient for selected models.

**Constraints**

- Chrome extension CSP limits some WASM / worker ML paths.
- Firefox lacks Chrome DNR API behavior.
- Provider model-naming collisions can cause ambiguous mapping behavior.

## Known risks and technical debt

- Partial provider parity in model-management actions.
- Two storage engines: chat history is SQLite-only, but vectors and knowledge sets are still Dexie. The Dexie *chat* fallback is retired — this is a split by domain, not a migration in progress.
- Typed setting descriptors cover only part of structured extension storage;
  high-risk config should gain runtime schemas incrementally.
- The environment-independent context coordinator now lives in
  `@ollama-client/chat-runtime`, but its extension adapter still owns provider,
  retrieval, and storage access. Keep that environment coupling outside the
  package boundary.
- Retrieval quality depends on chunking / threshold tuning and model quality.

## Desktop design notes

These are non-implementation notes for a hypothetical desktop port.

- The provider abstraction (factory / manager / types) is intentionally runtime-agnostic and can be reused in a desktop app.
- Provider identity metadata (icons, display names) should remain shared via `src/lib/providers/registry.ts`.
- Browser-only APIs (DNR, extension messaging) are already isolated in background handlers and would map to Electron main-process equivalents.
- Storage keys are provider-agnostic with legacy shims; a desktop app can reuse the same keys to migrate settings.

## Near-term priorities

1. Preserve the contracts, runtime-core, and chat-runtime source boundaries as
   browser-agent work begins.
2. Build agent task, policy, approval, verification, and recovery kernels on
   those ports rather than importing extension adapters.
3. Improve retrieval observability and failure diagnostics.

---

# Provider Capability Matrix

Source: https://www.ollamaclient.in/concepts/provider-matrix/
Markdown: https://www.ollamaclient.in/concepts/provider-matrix.md
Description: Which features each provider supports. Generated from the extension's TypeScript source at build time.

This matrix is generated from `src/lib/providers/*.ts` on every `pnpm docs:build`. When a provider class changes a capability flag, the table here updates automatically the next time docs are rebuilt.

:::note
✓ = supported · — = not supported. "Supported" here means the provider class exposes a working implementation; it does not mean the underlying server is necessarily running on your machine.
:::

| Provider | Chat | Embeddings | Model discovery | Model details | Pull | Unload | Delete | Version | Tool calling |
|---|---|---|---|---|---|---|---|---|---|
| **Ollama** | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| **LM Studio** | ✓ | ✓ | ✓ | — | ✓ | ✓ | — | — | ✓ |
| **llama.cpp** | ✓ | ✓ | ✓ | — | — | — | — | — | — |
| **OpenAI-compatible (custom)** | ✓ | ✓ | ✓ | — | — | — | — | — | — |
| **Anthropic** | ✓ | — | ✓ | — | — | — | — | — | ✓ |

## Notes

- **Ollama** — Recommended baseline. Full feature parity including tool calling, pull / delete / unload.
- **LM Studio** — OpenAI-compatible. Supports tool calling and adds pull / unload over the OpenAI base.
- **llama.cpp** — Run with `llama-server`. Tool calling supported on recent llama.cpp.
- **OpenAI-compatible (custom)** — User-added vLLM, LocalAI, KoboldCPP, or another compatible endpoint.
- **Anthropic** — Optional remote provider using the native Claude Messages API.

## How this table is built

The generator at `tools/generate/generate-docs.ts` instantiates each provider class with a minimal config and reads its `capabilities: ProviderCapabilities` field. The same field is the runtime source of truth for the extension UI's capability-aware routing (chat menu, model-management actions, etc.), so any divergence here would already be a bug.

If you're adding a new provider, register it in:

1. `src/lib/providers/` (the class itself)
2. `src/lib/providers/factory.ts` (the factory map)
3. `src/lib/providers/manager.ts` (`DEFAULT_PROVIDERS`)
4. `tools/generate/generate-docs.ts` (this generator's `providers` array)

The first three are mandatory for the runtime; the fourth keeps the docs honest.

---

# Open WebUI vs Ollama Client

Source: https://www.ollamaclient.in/compare/open-webui-vs-ollama-client/
Markdown: https://www.ollamaclient.in/compare/open-webui-vs-ollama-client.md
Description: A factual comparison of Open WebUI and Ollama Client for local LLM chat — hosting model, privacy, page context, RAG, and when to choose each.

**Open WebUI and Ollama Client both give you a private chat interface for local
LLMs like Ollama, but they are shaped differently.** Open WebUI is a
self-hosted web application you run as a server; Ollama Client is a Chrome and
Firefox extension that needs no server and can reason over the page, tab, or
text you are currently looking at.

## Who each is for

- **Open WebUI** — you want a full multi-user chat *server* on your own machine
  or homelab, are comfortable running Docker, and want a ChatGPT-style web app
  with accounts, model management, and admin controls.
- **Ollama Client** — you want private AI *in the browser* with zero server
  setup, and you value page/tab context (summarize this page, chat with this
  PDF) more than a hosted multi-user app.

## Feature comparison

| | Open WebUI | Ollama Client |
|---|---|---|
| Form factor | Self-hosted web server (Docker/pip) | Browser extension (Chrome, Firefox) |
| Setup | Run a container/service | Install from the store |
| Providers | Ollama + OpenAI-compatible | Ollama, LM Studio, llama.cpp, vLLM, LocalAI, KoboldCPP, OpenAI-compatible |
| Page / tab context | No | Yes — selection, page, tabs |
| Local RAG over files | Yes | Yes |
| Web search | Yes | Yes (SearXNG, Brave, Tavily) |
| Tool calling | Yes | Yes (for tool-capable models) |
| Accounts / multi-user | Yes | No — single local user |
| Runs offline | Yes (self-hosted) | Yes (local providers) |
| Telemetry | Configurable | None |

## Privacy

Both keep model inference on hardware you control. The difference is the trust
surface: Open WebUI is a server with user accounts and its own storage, while
Ollama Client has no backend at all — no accounts, no analytics, and prompts are
sent only to the provider endpoint you configure. Chat history and file vectors
stay in [local browser storage](/concepts/privacy/).

## Setup complexity

Open WebUI expects you to run and maintain a service (commonly a Docker
container) and open its web app. Ollama Client is a store install; point it at
your provider URL and start chatting. See the [Quick Start](/guides/quick-start/)
and [Provider Setup](/guides/provider-setup/) guides.

## When to choose each

- Choose **Open WebUI** for a shared, always-on chat server with user
  management and admin features.
- Choose **Ollama Client** for zero-server, private, page-aware AI that lives
  where you browse — and for connecting several local providers from one place.

## FAQ

### Is Ollama Client an alternative to Open WebUI?

Yes. Both give you a private chat interface for Ollama and other local models.
Open WebUI is a self-hosted server you run (usually via Docker); Ollama Client
is a browser extension that needs no server and can read the page or tab you are
on.

### Do I need Docker for Ollama Client?

No. Ollama Client installs from the Chrome or Firefox store and talks directly
to your local provider endpoint (for example `http://localhost:11434` for
Ollama). There is no server or container to run.

### Which is more private, Open WebUI or Ollama Client?

Both keep inference local. Ollama Client is local-first by construction: it has
no backend, no accounts, and no telemetry — prompts go only to the provider
endpoint you configure, and history stays in browser storage.

### Can Open WebUI read the current browser tab?

No. Open WebUI is a standalone web app. Reading the page, tab, or selected text
you are viewing is the core wedge of Ollama Client, which runs inside the
browser.

---

# Page Assist vs Ollama Client

Source: https://www.ollamaclient.in/compare/page-assist-vs-ollama-client/
Markdown: https://www.ollamaclient.in/compare/page-assist-vs-ollama-client.md
Description: A factual comparison of Page Assist and Ollama Client — two browser extensions for Ollama and local LLMs, their grounding, providers, and privacy.

**Page Assist and Ollama Client are both browser extensions for chatting with
Ollama and other local models — no server required.** They overlap on the core
idea (private, in-browser AI) and differ mostly in breadth of grounding and
provider support. This page sticks to what each does; both are good tools.

## Who each is for

- **Page Assist** — you want a lightweight in-browser UI for Ollama and local
  models with page-chat.
- **Ollama Client** — you want the same in-browser convenience plus deeper
  grounding (files/RAG, tabs, web search, tools) and a wider set of local
  providers, with an explicitly no-telemetry design.

## Feature comparison

| | Page Assist | Ollama Client |
|---|---|---|
| Form factor | Browser extension | Browser extension (Chrome, Firefox) |
| Providers | Ollama + OpenAI-compatible | Ollama, LM Studio, llama.cpp, vLLM, LocalAI, KoboldCPP, OpenAI-compatible |
| Page / tab context | Page chat | Selection, page, and multi-tab context |
| Local RAG over files | Yes | Yes — hybrid keyword + vector search |
| Web search | Yes | Yes (SearXNG, Brave, Tavily) |
| Tool calling | Varies | Yes (for tool-capable models) |
| Text-selection actions | — | Summarize, translate, and custom actions on selected text |
| Telemetry | — | None |

## Privacy

Both run inference on your local provider and avoid the cloud by default.
Ollama Client adds no analytics and has no backend; prompts go only to the
endpoint you configure and history stays in [browser storage](/concepts/privacy/).

## When to choose each

- Choose **Page Assist** for a focused, lightweight Ollama-in-browser
  experience.
- Choose **Ollama Client** when you want richer grounding (files, tabs, web,
  tools), more local providers, and a no-telemetry stance in one extension.

## FAQ

### How is Ollama Client different from Page Assist?

Both are browser extensions for chatting with Ollama and local models. Ollama
Client focuses on deep grounding — page and tab context, uploaded-file RAG, web
search, and tool calling — across many providers, with a no-telemetry,
local-first design.

### Do both extensions work with Ollama?

Yes. Both connect to a local Ollama server. Ollama Client also supports LM
Studio, llama.cpp, vLLM, LocalAI, KoboldCPP, and other OpenAI-compatible
endpoints.

### Can these extensions chat with the current web page?

Yes — reading page content is a shared strength. Ollama Client extends this with
tab context, text selection actions, uploaded-file RAG, and optional
provider-backed web search.

---

# LM Studio vs Ollama Client

Source: https://www.ollamaclient.in/compare/lm-studio-vs-ollama-client/
Markdown: https://www.ollamaclient.in/compare/lm-studio-vs-ollama-client.md
Description: How LM Studio and Ollama Client relate — a desktop model runner versus a browser extension — and how to use them together for private local AI.

**LM Studio and Ollama Client are complementary, not competitors.** LM Studio is
a desktop application that discovers, downloads, and serves local models with a
built-in chat window. Ollama Client is a browser extension that connects to a
running model server — including LM Studio's — and adds browser-native grounding
like page context, file RAG, web search, and tool calling. Many users run both.

## Who each is for

- **LM Studio** — you want a polished desktop app to browse, download, quantize,
  and serve local models, with a local API server for other apps to use.
- **Ollama Client** — you want to use those models *while you browse*: summarize
  the current page, chat with a PDF, or search the web, without leaving the tab.

## Feature comparison

| | LM Studio | Ollama Client |
|---|---|---|
| Form factor | Desktop app + local server | Browser extension (Chrome, Firefox) |
| Primary job | Download & serve local models | Chat with a running provider in-browser |
| Model management | Yes — browse/download/quantize | Uses models exposed by your provider |
| Page / tab context | No | Yes — selection, page, tabs |
| Local RAG over files | Basic | Yes — hybrid keyword + vector search |
| Web search | — | Yes (SearXNG, Brave, Tavily) |
| Other providers | Serves its own | Ollama, llama.cpp, vLLM, LocalAI, KoboldCPP, OpenAI-compatible |
| Telemetry | Configurable | None |

## Using them together

1. In LM Studio, load a model and start the local server.
2. In Ollama Client, add LM Studio as a provider and set its endpoint (commonly
   `http://localhost:1234`). See [Provider Setup](/guides/provider-setup/).
3. Chat with LM Studio models from any tab, with page context and files.

## When to choose each

- Choose **LM Studio** to manage and serve local models on your desktop.
- Choose **Ollama Client** to put those models to work in the browser — and to
  connect several providers from one private, no-telemetry extension.

## FAQ

### Is Ollama Client a replacement for LM Studio?

Not exactly — they solve different halves. LM Studio is a desktop app that
downloads and serves local models; Ollama Client is a browser extension that
connects to a running server (including LM Studio's) and adds page context, RAG,
web search, and tools.

### Can Ollama Client connect to LM Studio?

Yes. Enable LM Studio's local server and point Ollama Client at its
OpenAI-compatible endpoint (for example `http://localhost:1234`). You can then
chat with LM Studio models from any browser tab.

### Do I still need Ollama to use Ollama Client?

No. Despite the name, Ollama Client works with any supported local provider — LM
Studio, llama.cpp, vLLM, LocalAI, KoboldCPP, or any OpenAI-compatible server —
not just Ollama.

---

# Ollama Client developer portal

Source: https://www.ollamaclient.in/developers/
Markdown: https://www.ollamaclient.in/developers.md
Description: Integrate with Ollama Client's local olc OpenAI-compatible proxy, including setup, authentication, endpoints, errors, tools, and its OpenAPI specification.

Ollama Client is a browser extension, not a hosted inference service. The website at `ollamaclient.in` publishes documentation and machine-readable resources; it does not accept prompts or expose users' models.

The project includes **olc**, a local CLI. Bare `olc` starts or reuses native Ollama on port `11434` with extension access. With `-b codex` or `-b opencode`, it runs a proxy that exposes an agent runtime through an OpenAI-compatible HTTP API. Use it when an OpenAI-compatible client needs to reach an OpenCode-backed agent and preserve client-owned function calls. The published [OpenAPI 3.1 specification](/openapi.json) describes this local API and deliberately lists loopback servers.

## Quickstart

**olc** is the project's official command-line tool. It is distributed as a
checksum-verified archive attached to each [GitHub release](https://github.com/Shishir435/ollama-client/releases),
fetched by the two installer wrappers below. There is no npm, PyPI, or Homebrew
package yet; do not install a similarly named package from a public registry
expecting this one.

olc requires Node.js 22.12 or newer plus the selected runtime on `PATH`:
Ollama for native mode, OpenCode, or Codex CLI with an existing `codex login`.
macOS/Linux native mode also requires `lsof` for process inspection.

Install the published release bundle directly:

```powershell
# Windows PowerShell
irm https://ollamaclient.in/olc.ps1 | iex
```

```bash
# macOS / Linux
curl -fsSL https://ollamaclient.in/olc.sh | sh
```

Both installers download checksum-verified archives from the GitHub release.
Pin version `0.13.2` with the shell-specific commands below:

```bash
export OLC_VERSION=0.13.2
curl -fsSL https://ollamaclient.in/olc.sh | sh
```

```powershell
$env:OLC_VERSION = "0.13.2"
irm https://ollamaclient.in/olc.ps1 | iex
```

### Install without piping to a shell

`ollamaclient.in/olc.sh` and `olc.ps1` are convenience wrappers served from a
mutable URL. Both verify the archive they download against its published
`sha256`, but the one-line commands fetch and execute the wrapper in a single
step, so there is nothing to check or read before it runs with your privileges.

Every release publishes both wrappers alongside the archives, each with its own
`sha256`. Pin one to a tag, verify it, read it, and only then run it:

```bash
tag=0.13.3
base="https://github.com/Shishir435/ollama-client/releases/download/$tag"
curl -fsSL "$base/olc.sh" -o olc.sh &&
  curl -fsSL "$base/olc.sh.sha256" -o olc.sh.sha256 &&
  { if command -v sha256sum >/dev/null
    then sha256sum -c olc.sh.sha256
    else shasum -a 256 -c olc.sh.sha256
    fi
  } &&
  less olc.sh &&
  OLC_VERSION="$tag" sh olc.sh
```

```powershell
$tag = "0.13.3"
try {
  $base = "https://github.com/Shishir435/ollama-client/releases/download/$tag"
  $dir = (New-Item -ItemType Directory -Path (Join-Path $env:TEMP "olc-$tag-$(Get-Random)")).FullName
  irm "$base/olc.ps1" -OutFile "$dir\olc.ps1" -ErrorAction Stop
  irm "$base/olc.ps1.sha256" -OutFile "$dir\olc.ps1.sha256" -ErrorAction Stop
  $expected = (Get-Content "$dir\olc.ps1.sha256").Split(" ")[0]
  if ((Get-FileHash "$dir\olc.ps1" -Algorithm SHA256).Hash -ne $expected) { throw "checksum mismatch" }
  Get-Content "$dir\olc.ps1"
  $env:OLC_VERSION = $tag
  Unblock-File "$dir\olc.ps1"
  powershell -ExecutionPolicy Bypass -File "$dir\olc.ps1"
} catch {
  Write-Error "olc install stopped: $_"
}
```

Each block is a single guarded unit rather than a list of independent commands:
the Unix steps are chained with `&&`, and the PowerShell steps sit inside one
`try`/`catch` that downloads into a fresh directory. A failed download or a
mismatched checksum ends the block. Without that, the next pasted line runs
regardless — on Windows it would hash and execute whatever `olc.ps1` happened to
be sitting in the working directory.

A file downloaded rather than piped carries the mark of the web, so PowerShell
blocks it until `Unblock-File` clears the mark; the explicit policy on that one
invocation avoids changing the machine's default.

Or skip the wrapper and take the release archive for a chosen tag directly. This
is the same artifact the wrapper would install, and nothing but `tar` runs:

```bash
tag=0.13.3
base="https://github.com/Shishir435/ollama-client/releases/download/$tag"
curl -fsSL "$base/olc.tar.gz" -o olc.tar.gz &&
  curl -fsSL "$base/olc.tar.gz.sha256" -o olc.tar.gz.sha256 &&
  { if command -v sha256sum >/dev/null
    then sha256sum -c olc.tar.gz.sha256
    else shasum -a 256 -c olc.tar.gz.sha256
    fi
  } &&
  tar -xzf olc.tar.gz &&
  node olc/dist/olc.mjs --help
```

```powershell
$tag = "0.13.3"
try {
  $base = "https://github.com/Shishir435/ollama-client/releases/download/$tag"
  irm "$base/olc.tar.gz" -OutFile olc.tar.gz -ErrorAction Stop
  irm "$base/olc.tar.gz.sha256" -OutFile olc.tar.gz.sha256 -ErrorAction Stop
  $expected = (Get-Content olc.tar.gz.sha256).Split(" ")[0]
  if ((Get-FileHash olc.tar.gz -Algorithm SHA256).Hash -ne $expected) { throw "checksum mismatch" }
  tar -xzf olc.tar.gz
  node olc/dist/olc.mjs --help
} catch {
  Write-Error "olc download stopped: $_"
}
```

Each checksum is published beside the file it covers on the same release, so it
shows the download arrived intact — not that the file behind a tag is still the
one you reviewed. The release workflow never overwrites a published asset (a
re-run on a moved tag uploads only what is missing), but release assets can still
be changed by hand, and a checksum served from the same place as its file is not
an independent signature. For a pin that does not depend on any of that, record
the hash of a release you have checked and compare against it on later installs.

Move the extracted `olc` directory wherever you keep tools and put `olc.mjs`
on `PATH` under whatever name you prefer; the wrapper's only extra job is
choosing those locations for you.

```bash
# Source checkout alternative
git clone https://github.com/Shishir435/ollama-client.git
cd ollama-client
pnpm install
pnpm proxy:opencode --api-key "replace-with-a-long-random-token"
# or, after `codex login`:
pnpm proxy:codex --api-key "replace-with-a-long-random-token"
```

After upgrading to the release containing native mode (older bundles default to
OpenCode), use the same command format for each backend:

```bash
olc                        # native Ollama: 127.0.0.1:11434
olc --lan                  # native Ollama: 0.0.0.0:11434
olc --local                # explicitly restore loopback
olc --check --json         # read-only native readiness for scripts/agents
olc -b codex               # Codex proxy: 127.0.0.1:8083
olc --backend opencode     # OpenCode proxy: 127.0.0.1:8084
olc -b codex --debug       # foreground, with verbose diagnostics
olc -b opencode --foreground # foreground, normal logging
```

All modes detach by default. Use `--foreground` to stay attached, or `--debug`
for foreground diagnostics; `--detached` makes the default explicit. Detached
proxies report a ready URL, PID, and private log file under `~/.olc/logs/`
(`OLC_LOG_DIR` overrides it). Startup failures return a nonzero exit code.
Use `--foreground` with process supervisors and containers. Existing/app-managed
Ollama stays under its original owner: foreground mode monitors it, and Ctrl-C
exits only the monitor. A new standalone foreground server stops with the session.

Native mode uses the built-in Ollama provider and keeps Ollama's own API.
Existing compatible access is preserved by bare `olc`; restarting an owned
standalone process interrupts active work. Ollama has no native API-key
protection, so use LAN only on a trusted network. olc never changes launchctl,
systemd, Windows user/machine variables, shell profiles, or Ollama configuration.
It passes `OLLAMA_*` only to a standalone process it starts. An incompatible
macOS app is gracefully quit and replaced with that standalone child, without
reconfiguring or relaunching the app. Other incompatible services remain
untouched and must be stopped for a standalone olc session or configured
manually. See the [operator guide](https://github.com/Shishir435/ollama-client/tree/main/packages/olc#native-ollama)
for platform behavior and configuration.

The following API documentation applies to **Codex/OpenCode proxy modes**. Codex defaults to `http://127.0.0.1:8083`; OpenCode defaults to `http://127.0.0.1:8084`. Configure Ollama Client with a custom OpenAI-compatible provider using the matching `/v1` base URL, then select a model returned by the catalog. The examples below use the Codex default; substitute port `8084` for OpenCode.

Use `pnpm proxy:opencode:debug` or `pnpm proxy:codex:debug` for verbose proxy
logging in the foreground. The existing `pnpm proxy` and `pnpm proxy:debug` commands remain
OpenCode aliases.

The CLI is distributed as release archives, not through npm, PyPI, or Homebrew.
Do not tell users to install an `olc` package from a public registry.

## Authentication and browser access

Pass `--api-key` or set `OLC_API_KEY`; API routes then require `Authorization: Bearer <token>`. Health routes stay unauthenticated. The proxy binds to `127.0.0.1` by default—keep that loopback default unless you have a specific network design and authentication in place.

Browser origins are checked separately. The defaults allow Chrome, Firefox, and Safari extension schemes. Add a web application's exact origin with `--allowed-origins http://localhost:3000`. Avoid `--allowed-origins "*"`, especially without an API key, because the proxy can run an agent and spend inference.

## Endpoints

| Method and path | operationId | Purpose |
| --- | --- | --- |
| `GET /` | `getServiceInfo` | Identify olc, the active backend, and tool-bridge state. |
| `GET /health` | `getHealth` | Check process liveness. |
| `GET /v1/models` | `listModels` | List backend models and capability metadata. |
| `GET /v1/models/{modelId}` | `getModel` | Read one model by full or unambiguous suffix id. |
| `POST /v1/chat/completions` | `createChatCompletion` | Generate a buffered JSON completion or an SSE stream. |
| `POST /v1/images/generations` | `createImageGeneration` | Generate one image through a capable backend. |

`POST /bridge/call` is an internal, per-run callback used by the OpenCode adapter. It is not a public integration endpoint and is intentionally excluded from the public OpenAPI surface.

## Minimal request

```bash
curl http://127.0.0.1:8083/v1/chat/completions \
  -H 'Authorization: Bearer replace-with-a-long-random-token' \
  -H 'Content-Type: application/json' \
  -d '{
    "model": "provider/model",
    "messages": [{"role": "user", "content": "Explain this repository"}],
    "stream": false
  }'
```

Discover model ids through `GET /v1/models`; do not invent one. Model rows also report input modalities, supported parameters, and function-calling, vision, and reasoning capabilities.

## Image generation

When the active Codex provider reports native image generation, olc publishes a dedicated `codex/image-generation` model with `"image"` in `output_modalities`. Generate one image with the standard Images request:

```bash
curl http://127.0.0.1:8083/v1/images/generations \
  -H 'Authorization: Bearer replace-with-a-long-random-token' \
  -H 'Content-Type: application/json' \
  -d '{
    "model": "codex/image-generation",
    "prompt": "A watercolor fox reading beside a window",
    "response_format": "b64_json"
  }'
```

The current contract produces one base64 image (`n=1`). A backend that does not advertise native image output returns `501`; olc never invents image capability from a model name.

## Function calling

Send OpenAI-shaped `tools` with unique function names, descriptions, and JSON Schema parameters. If the runtime calls a client tool, olc returns a completion with `finish_reason: "tool_calls"`. Execute the requested tools, append assistant and `tool` messages with the matching `tool_call_id` values, and send the conversation back to the same endpoint. The proxy resumes the parked turn.

Tool results belong to one live turn. An expired, cancelled, or foreign id returns `400` with type `StaleToolResults` and code `stale_tool_results`; remove those stale results and begin a new turn only after making that reset visible to the user.

## JSON errors

Non-streaming errors use an OpenAI-style JSON envelope:

```json
{
  "error": {
    "type": "BadRequest",
    "code": "optional_machine_code",
    "message": "Human-readable explanation and recovery hint"
  }
}
```

Common statuses are `400` for malformed requests or stale tool results, `401` for an invalid bearer token, `403` for a disallowed browser origin, `404` for an unknown route or model, `502` for a backend failure, `503` for a stalled request queue, and `504` for a timeout. A stream that fails after headers were sent reports a final proxy-error text delta because the HTTP status can no longer change.

## Versioning, rate limits, and deprecation

Both API surfaces are versioned in the URL path: the local proxy under `/v1`,
and the website's read-only discovery surface at [`/api`](/api) as version
`v1`. Every response carries `X-API-Version` with the major version of the
contract that produced it. Use the documented versioned routes; do not depend
on an undocumented path continuing to answer.

### Rate-limit headers

The proxy publishes the RFC RateLimit fields on every API response:

| Header | Meaning |
| --- | --- |
| `RateLimit-Policy` | The published budget, `"default";q=<limit>;w=<window seconds>`. The proxy default is 60 requests per 60 seconds. |
| `RateLimit` | The live window, `"default";r=<remaining>;t=<seconds to reset>`. |
| `RateLimit-Limit` | Requests allowed in one window. |
| `RateLimit-Remaining` | Requests left in the current window. |
| `RateLimit-Reset` | Seconds until the window resets. |
| `Retry-After` | On `429` only: seconds to wait. |

The bucket is the bearer token when one is configured, and the remote address
otherwise. When a client exceeds the window it receives `429` with
`Retry-After`; retry with exponential backoff and do not blindly replay a
non-idempotent generation.

The website endpoints publish the same fields with the same names. They serve
cached static JSON from a CDN and do not meter callers, so `RateLimit-Remaining`
there always reports a full window — an honest answer to "have I been
throttled", and a documented budget to pace against rather than guess at.

### Deprecation and sunset policy

No route on either surface is removed without advance notice. When a route is
deprecated:

1. Its responses carry the `Deprecation` header ([RFC 9745](https://www.rfc-editor.org/rfc/rfc9745.html))
   with the HTTP date the deprecation took effect.
2. They carry a `Sunset` HTTP date ([RFC 8594](https://www.rfc-editor.org/rfc/rfc8594.html))
   at least **30 days** in the future. The route keeps working until that date.
3. They carry a `Link` header pointing at the replacement route and at this
   policy, using the extension relation
   `https://www.ollamaclient.in/rel/deprecation-policy`.
4. The migration and the replacement route are documented here and in the
   OpenAPI specification *before* the headers appear, and the OpenAPI operation
   is marked `deprecated: true`.

No current route is deprecated, so neither header appears on any response
today. The machine-readable form of this policy lives in `info.x-api-lifecycle`
of the [OpenAPI document](/openapi.json) and in the `versioning` object of
[`/api`](/api).

## Website discovery API

The website publishes two read-only JSON endpoints so an agent can find the rest
of the surface without scraping HTML:

| Method and path | Purpose |
| --- | --- |
| `GET /api` | Service metadata, error format, content-negotiation rules, rate-limit and versioning policy, CLI install commands. |
| `GET /api/health` | Liveness response. |

Errors from these endpoints are JSON, never an HTML page:

```json
{
  "error": {
    "status": 404,
    "code": "route_not_found",
    "message": "No API route for GET /api/models.",
    "resolution": "This site publishes GET /api and GET /api/health. Inference endpoints live on the local olc proxy described by the OpenAPI document.",
    "documentation": "https://www.ollamaclient.in/developers/",
    "openapi": "https://www.ollamaclient.in/openapi.json",
    "agentMap": "https://www.ollamaclient.in/llms.txt"
  }
}
```

`404` is an unknown route, `405` is a method other than `GET`, `HEAD`, or
`OPTIONS` (the response names the allowed set in `Allow`), and `406` means no
representation matched the `Accept` header. Read `error.resolution` before
retrying.

Both endpoints advertise the rest of the surface through `Link` relations:
`service-desc` for the OpenAPI document, `service-doc` for this page, and
`api-catalog` for the [RFC 9727](https://www.rfc-editor.org/rfc/rfc9727.html)
linkset at [`/.well-known/api-catalog`](/.well-known/api-catalog).

## Markdown content negotiation

Every documentation page has a Markdown twin at the same URL. Send
`Accept: text/markdown` and the response body is Markdown with
`Content-Type: text/markdown; charset=utf-8`; send a browser's `Accept` and it
is the rendered HTML page. Responses `Vary: Accept, Accept-Encoding`, so a CDN
cannot hand one variant to a client that asked for the other.

```bash
curl -H 'Accept: text/markdown' https://www.ollamaclient.in/developers
```

Quality factors are honoured, and the most specific matching range decides a
type's quality, so `Accept: text/markdown;q=0.5, text/html` returns HTML and
`Accept: text/html;q=0, */*` returns Markdown. An `Accept` header that matches
no available representation returns `406` with a JSON explanation. The twins are
also addressable directly by appending `.md`, and `/index.md` is the twin of the
landing page.

Negotiation applies to documentation pages. `/api` and `/api/health` are JSON
only and ignore `Accept`, so a machine probing them always gets something it can
parse.

An unknown path returns a real `404`, with a short Markdown recovery map when
Markdown was requested and the [HTML 404 page](/404.md) otherwise. It never
returns `200` with an application shell, so an agent can trust the status.

## Agent integration guidance

Use olc when the caller already supports OpenAI chat completions and needs a local agent runtime, particularly when the caller—not the runtime—owns tool execution and approval. Inspect `/v1/models` before choosing modalities or tools. Prefer non-streaming responses when a simple function runner cannot parse server-sent events.

Do not use this interface as a substitute for the extension's internal RPC contracts, do not call the bridge endpoint, and do not send requests to `ollamaclient.in/v1`. For extension architecture and contribution boundaries, use the [architecture guide](/concepts/architecture/) and the generated [TypeScript reference](/reference/).

## Resources

- [OpenAPI 3.1 JSON](/openapi.json) — machine-readable schema for the local olc API
- [API catalog](/.well-known/api-catalog) — RFC 9727 linkset for both API surfaces
- [Website JSON API](/api) and [health](/api/health)
- [Agent map (llms.txt)](/llms.txt) and [full Markdown docs](/llms-full.txt)
- [olc source and full operator guide](https://github.com/Shishir435/ollama-client/tree/main/packages/olc)
- [Provider setup](/guides/provider-setup/)
- [Error reports](/guides/troubleshooting/error-reports/)
- [GitHub issues](https://github.com/Shishir435/ollama-client/issues)

There is no hosted sandbox or API-key dashboard because the API runs on the user's machine. Use a disposable local checkout and a non-sensitive model for integration tests.

---

# Frontend Design System

Source: https://www.ollamaclient.in/internal/frontend-design-system/
Markdown: https://www.ollamaclient.in/internal/frontend-design-system.md
Description: App-owned frontend primitives, shadcn ownership boundaries, token policy, and visual QA checklist.

This project treats shadcn/Base UI components as replaceable low-level primitives. Product behavior lives in app-owned wrappers so preset refreshes do not break settings persistence, density, or translated UI.

## Ownership

| Layer | Path | Owner | Rules |
|---|---|---|---|
| Generated primitives | `src/components/ui/` | shadcn/Base UI plus documented local overrides | Keep low-logic. Do not add provider, model, RAG, or React Hook Form behavior. |
| Form behavior | `src/components/forms/` | App | Own value parsing, React Hook Form integration, number/slider conversion, and behavior tests. |
| Layout rhythm | `src/components/layout/` | App | Own page width, stacks, grids, toolbars, and repeated spacing. |
| Settings composition | `src/components/settings/` | App | Own settings rows, fields, sections, action rows, diagnostics, and dangerous actions. |
| Feedback states | `src/components/feedback/` | App | Own empty, loading, error, progress, metric, health, and status UI. |
| Data display | `src/components/data-display/` | App | Own repeated provider, model, source, file, metadata, and info-list patterns. |
| Feature UI | `src/features/*` | Feature | Own domain copy, state, validation config, and feature-specific workflows only. |

## Form Rules

- Prefer `ControlledNumberInput`, `ControlledSlider`, `ControlledTextInput`, `ControlledTextarea`, `ControlledSelect`, and `ControlledSwitch` over wiring `src/components/ui/*` directly into React Hook Form.
- Use `SettingsFormField`, `SettingsSelectField`, or `SettingsSliderField` when the control needs label, description, value badge, or validation text.
- Keep parsing and conversion out of feature components. Feature components should pass values and handlers, not know Base UI event shapes.
- Any app-owned form primitive that transforms values needs tests.

## Layout Rules

- Use `PageStack` for top-level tab/page rhythm.
- Use `SectionStack` for grouped settings surfaces.
- Use `FieldStack` for stacked fields inside cards.
- Use `ControlStack` for label/control micro-layouts.
- Use `TwoColumnGrid`, `FormGrid`, and `DenseFormGrid` instead of repeating raw grid strings.
- Use `Toolbar`, `InlineActions`, and `SettingsActionRow` for action groups that must wrap on narrow widths.

## Token Rules

- Use semantic tokens: `bg-background`, `bg-card`, `text-muted-foreground`, `border-border`, `bg-status-success/10`, and `STATUS_STYLES`.
- Use `dark:*` only for primitive quirks or prose inversion where tokens cannot express the state.
- Keep raw `hsl(...)`, `oklch(...)`, and hex values inside token files unless the value belongs to syntax highlighting or external content.
- Use control density helpers when a component needs explicit height: `control-h-sm`, `control-h-md`, `control-h-lg`, plus matching `control-min-h-*` utilities.
- Use `icon-micro`, `icon-xs`, `icon-sm`, `icon-md`, `icon-lg`, `icon-xl`, `icon-2xl`, or `icon-3xl` on icons. Raw `size-*`, `h-*`, and `w-*` icon dimensions are not allowed.
- Use the named typography scale (`text-micro`, `text-2xs`, `text-xs`, `text-sm`, `text-base`) instead of arbitrary `text-[Npx]` values.
- Use `rounded-control` for controls and compact rows, `rounded-panel` for framed surfaces, `rounded-chip` for pills, and `rounded-message` for chat messages. Do not introduce raw `rounded-md` or `rounded-lg`.
- Use `TooltipActionButton` for icon-only actions. Trigger adapters may render a low-level `Button`, but the action still needs the shared tooltip wrapper.
- `src/components/__tests__/design-system-contract.test.ts` enforces typography, radius, icon-size, primitive SVG, and icon-button rules.

## i18n Rules

- Shared component props for `title`, `label`, `description`, `emptyText`, and actions should accept `React.ReactNode`.
- Do not concatenate translated sentence fragments.
- Long translated labels must wrap or truncate intentionally; never assume English-length text.
- Generated primitives in `src/components/ui/` should stay text-agnostic.

## Preset Update Checklist

1. Apply the shadcn preset or primitive update on a branch.
2. Review diffs under `src/components/ui/` and `src/globals.css` first.
3. Confirm no feature behavior moved into generated primitives.
4. Run `pnpm lint:check`, `pnpm typecheck`, and `pnpm test:run`.
5. Run targeted tests for number inputs, sliders, selects, switches, and any touched primitive.
6. Manually check model settings, embedding settings, provider settings, chat input, and narrow options width in both light and dark mode.

## Visual QA Checklist

- Options page: settings sidebar, mobile tabs, model settings, provider settings, embedding settings.
- Sidepanel: chat header, composer, message rendering, search dialog, empty states.
- Themes: light, dark, and system mode.
- Long text: use a language with longer labels and verify buttons, rows, cards, and badges do not overlap.
- Density: controls should remain compact without relying on raw per-file heights.

---

# Performance Audit

Source: https://www.ollamaclient.in/internal/performance-audit/
Markdown: https://www.ollamaclient.in/internal/performance-audit.md
Description: Evidence plan for streaming, search-cache retention, and embedding-batch latency.

This audit is evidence-first. The extension does not collect performance
telemetry. Measurements are local benchmark output or manually captured
browser traces that contain no prompt, response, page, file, or credential
data.

## Current scope

| Item | Question | Current decision |
| --- | --- | --- |
| PERF-07 | Does per-token stream reduction or session-state publication create measurable cost? | Keep reducer/session-state ownership unchanged; retain the benchmark evidence without an unsupported refactor. |
| PERF-02 | Can search results survive page/worker recreation without stale results? | Keep results in memory; retain them with bounded insertion order until a vector-generation invalidation contract exists. |
| PERF-10 | Does the fixed inter-batch wait materially delay ingestion or retrieval? | Yield between batches with no fixed wall-clock delay; provider adapters remain responsible for throttling. |

## Reproduce

Run:

```bash
pnpm benchmark:performance
```

The command reports reducer CPU timing, cache-pruning timing, and the modeled
inter-batch wait for representative batch sizes. It is a guard against making
claims from a single trace; compare repeated runs on the same browser/runtime
and corpus shape.

## Measurement rules

- PERF-07 must compare first-token latency, token-to-token cadence, dropped or
  stale events, and terminal publication latency. A session-state refactor is
  justified only if it improves a measured bottleneck without weakening the
  durable turn or reconnect contract.
- PERF-02 must measure hit rate, retained-entry count, stale-result risk, and
  rehydration cost. Persisting entries without a vector-generation or index
  revision would make a fast stale answer possible, so no persistence change is
  included yet.
- PERF-10 must record provider batch duration, inter-batch wait, total ingest
  duration, retrieval latency, and retrieval-quality checks. A zero-delay or
  adaptive policy needs cancellation, rate-limit, and provider-failure tests.

The benchmark is intentionally diagnostic rather than an automatic tuning
loop. Results should be attached to the performance PR or issue that proposes
the behavior change.

---

# Privacy Policy

Source: https://www.ollamaclient.in/legal/privacy-policy/
Markdown: https://www.ollamaclient.in/legal/privacy-policy.md
Description: What Ollama Client processes, where data is stored, and when it leaves your device.

Ollama Client is designed as a local-first extension. This policy explains what data is processed, where it is stored, and when it leaves your device.

*Effective date: February 7, 2026.*

## Scope

This policy applies to the Ollama Client browser extension and the documentation pages on this site.

## Data we collect

The extension does **not** run first-party analytics, ad trackers, or telemetry pipelines. The data that exists on your device while using the extension is:

- Chat prompts and model responses generated during use.
- Session metadata (titles, timestamps, branch state).
- Optional uploaded file content for local retrieval workflows.
- Optional images attached to chat messages.
- Optional page content, tab titles/URLs, and selected text when you use browser-context features or when a tool-capable model calls a browser-context tool.
- Settings and provider configuration values.
- A bounded local diagnostic event buffer containing technical status codes, request IDs, and timing data, but no prompt or response content.

## Where data is stored

- Local browser storage backed by official sqlite-wasm. Migrated chat history
  uses OPFS; retained legacy profiles use a compatibility blob in IndexedDB.
- Optional ZIP backups stored locally when you export.
- No default cloud sync from the extension itself.

## Network communication

The extension sends prompts to whichever provider endpoint you configure. Typical local endpoints:

- Ollama (`localhost:11434`)
- LM Studio (`localhost:1234`)
- llama.cpp server (`localhost:8000`)

LAN endpoints are supported when configured by the user. If you point the extension to a remote endpoint, your prompt data will be sent to that endpoint.

The OpenRouter preset sends two static application-attribution headers: the Ollama Client website and application name. It never substitutes the page you are viewing, a chat URL, or another user-specific value into those headers. Your API key remains device-local, but prompts and selected context are processed according to OpenRouter and its routed model provider's policies.

When browser-context tools or image input are used, the extracted context or image data becomes part of the provider request for that chat turn. Local providers receive it locally; remote providers receive it over the configured remote endpoint.

:::caution
Your privacy outcome depends on the provider endpoint you configure, not just the extension code. Review the privacy posture of any non-local endpoint before using it for sensitive prompts.
:::

## Permissions

The extension requests browser permissions for chat UX, optional page extraction, and provider connectivity:

- `storage` — settings and local state.
- `tabs` and content-extraction-related permissions.
- Network / host permissions to reach configured provider endpoints.

## Retention and user control

- You can delete chats and associated local artifacts from the UI.
- You can disable RAG and related indexing features.
- You can disable browser tab access from settings or the composer context controls.
- You can reset storage and configuration from the settings page.
- Diagnostic events expire after seven days, are capped at 200 records, and can be cleared from **Help → Diagnostics & support**.

Diagnostic support bundles are generated and previewed locally. They exclude chats, prompts, responses, uploaded files, page content, embeddings, API keys, headers, cookies, browser history, and full provider endpoints. The extension never uploads a support bundle automatically; you choose whether to copy, download, or share it.

## Security notes

- Do not expose provider APIs publicly without access controls.
- Treat LAN endpoints as sensitive infrastructure.
- Review provider privacy policies for any non-local endpoints.

## Policy changes

This policy may be updated as the architecture evolves. The latest version is always published at this URL.

## Contact

Questions: [shishirchaurasiya435@gmail.com](mailto:shishirchaurasiya435@gmail.com)

---

© 2026 Ollama Client. Local-first by design, with endpoint behavior controlled by the user.

---

# About Ollama Client

Source: https://www.ollamaclient.in/about/
Markdown: https://www.ollamaclient.in/about.md
Description: Learn what Ollama Client is, who maintains it, what local-first means, and how the open-source browser extension is developed and supported.

Ollama Client is an open-source browser extension for chatting with local and user-selected language-model providers from a Chrome or Firefox side panel. It supports verified Ollama, LM Studio, and llama.cpp profiles, user-added OpenAI-compatible servers, and Anthropic. Its purpose is to make model chat, page context, files, retrieval, optional web search, and permission-gated browser tools available without requiring a hosted Ollama Client account or a mandatory cloud API.

The project is maintained by [Shishir Chaurasiya](https://www.shishirchaurasiya.in/) and developed publicly in the [Ollama Client GitHub repository](https://github.com/Shishir435/ollama-client). Source code is available under the MIT license. Releases are distributed through browser extension stores, while this site publishes setup, architecture, privacy, troubleshooting, and developer documentation.

## Where Ollama Client is published

These are the only official listings. Anything else carrying the name is not
maintained by this project.

- Chrome, Edge, and Brave: [Ollama Client on the Chrome Web Store](https://chromewebstore.google.com/detail/ollama-client-chat-with-l/bfaoaaogfcgomkjfbmfepbiijmciinjl)
- Firefox: [Ollama Client on Firefox Add-ons](https://addons.mozilla.org/en-US/firefox/addon/ollama-client/)
- Source and releases: [github.com/Shishir435/ollama-client](https://github.com/Shishir435/ollama-client)
- Documentation and machine-readable resources: [www.ollamaclient.in](https://www.ollamaclient.in/)
- Command-line tool: [olc](https://github.com/Shishir435/ollama-client/tree/main/packages/olc), installed from the GitHub releases

## What local-first means here

Chat history, sessions, attachments, and most application state are stored by the extension in the user's browser profile. Model prompts go to the provider endpoint the user configures. A local provider can keep inference traffic on the device; a remote provider receives the data sent to it under that provider's terms. Optional web-search services likewise receive their search requests. “Local-first” describes the default ownership and architecture, not a claim that every possible configuration is offline.

Ollama Client has no hosted inference API at `ollamaclient.in`. The site is documentation. The separate olc developer proxy runs on the user's own machine and exposes a loopback OpenAI-compatible interface for local agent runtimes.

## Project principles

- Keep provider choice and endpoint configuration visible to the user.
- Ask for browser capabilities only when the requested feature needs them.
- Preserve chat data locally and make backup, restore, diagnostics, and deletion understandable.
- Document limitations and compatibility boundaries rather than guessing that an endpoint or model supports a feature.
- Keep development, issues, and architectural decisions inspectable in the public repository.

Questions and security-sensitive reports should use the channels on the [contact page](/contact/). Product setup questions are usually answered fastest by the [quick start](/guides/quick-start/), [provider setup](/guides/provider-setup/), and [FAQ](/about/faq/).

---

# Contact Ollama Client

Source: https://www.ollamaclient.in/contact/
Markdown: https://www.ollamaclient.in/contact.md
Description: Contact the Ollama Client maintainer, report bugs or security concerns, request features, and find the right support channel.

Ollama Client is maintained as an open-source project. Choose the channel that matches the information you need to share so questions remain searchable and sensitive reports do not become public by accident.

## Bug reports and feature requests

Use [GitHub Issues](https://github.com/Shishir435/ollama-client/issues) for reproducible bugs, compatibility reports, documentation corrections, and feature proposals. Before opening an issue, check the [provider setup guide](/guides/provider-setup/), [Ollama CORS troubleshooting](/guides/troubleshooting/ollama-cors-error/), [error report guide](/guides/troubleshooting/error-reports/), and existing issues. Include the extension version, browser and version, operating system, provider type, safe reproduction steps, and the exact visible error code when available.

Never post provider API keys, authorization headers, private prompts, file contents, full browser histories, or unreviewed diagnostic exports. Redact model endpoint hostnames if their disclosure would identify a private network.

## Security and private contact

For a suspected vulnerability or a matter that should not begin in a public issue, email [shishirchaurasiya435@gmail.com](mailto:shishirchaurasiya435@gmail.com). Use a clear subject such as “Ollama Client security report,” describe the affected version and impact, and provide the minimum reproduction material needed. Do not exploit other users, access data you do not own, or publish a working exploit before the maintainer has had a reasonable opportunity to investigate.

Email is also appropriate for store-listing, legal, or privacy inquiries that include personal information. The [privacy policy](/legal/privacy-policy/) explains data handling by the extension and this documentation site. General setup questions should remain on GitHub when possible, where answers can help other users.

## Project identity

- Product: Ollama Client
- Maintainer: [Shishir Chaurasiya](https://www.shishirchaurasiya.in/)
- Source: [github.com/Shishir435/ollama-client](https://github.com/Shishir435/ollama-client)
- Documentation: [www.ollamaclient.in](https://www.ollamaclient.in/)
- License: MIT

There is no sales team, hosted model service, API-key portal, or guaranteed support SLA. Response time depends on maintainer availability and the completeness of the report. Community contributions are welcome through the repository's normal issue and pull-request workflow.

---

# Ollama Client FAQ

Source: https://www.ollamaclient.in/about/faq/
Markdown: https://www.ollamaclient.in/about/faq.md
Description: Common questions about Ollama Client, local LLM providers, privacy, browser support, RAG, web search, and CORS setup.

Ollama Client is a local-first browser extension for chatting with local and
self-hosted AI models. It runs in Chrome and Firefox and connects to providers
you control: Ollama, LM Studio, llama.cpp, vLLM, LocalAI, KoboldCPP, or another
OpenAI-compatible server.

## Does Ollama Client send my data to a cloud service?

No cloud service is required by Ollama Client. Chat history, settings, uploaded
files, and knowledge indexes are stored locally in the browser extension. Model
requests go to the provider endpoint you configure.

If you configure a remote provider, the prompt data needed for that request goes
to that remote endpoint. If you configure a local provider such as Ollama or LM
Studio on `localhost`, requests stay on your machine.

## Which providers work with Ollama Client?

Ollama Client supports:

- Ollama
- LM Studio
- llama.cpp server
- vLLM
- LocalAI
- KoboldCPP
- Other OpenAI-compatible servers through the shared OpenAI-compatible adapter

See [Provider Setup](/guides/provider-setup/) for endpoints and setup steps.

## Is Ollama Client an Open WebUI alternative?

Yes, for users who want a browser extension instead of a self-hosted web
application. Open WebUI is a server-hosted interface. Ollama Client lives in the
browser side panel and focuses on page context, local storage, RAG, web search,
and browser-aware tools.

## Can I use files and RAG locally?

Yes. Ollama Client can process uploaded files and store local vector indexes for
retrieval-augmented generation. File retrieval is local-first: uploaded content
and embeddings are stored in browser storage, not in a hosted service.

## Can models search the web?

Yes, if you enable web search and configure a backend. Supported backends include
SearXNG, Brave Search, and Tavily. Web search is optional, and API keys stay in
local extension storage.

## How do I fix a 403 or CORS error?

For Ollama, set `OLLAMA_ORIGINS` so the local server accepts requests from
browser-extension origins:

```bash
OLLAMA_ORIGINS="chrome-extension://*,moz-extension://*" ollama serve
```

For persistent setup and platform-specific steps, see
[Fix Ollama CORS errors](/guides/troubleshooting/ollama-cors-error/).

---

# Changelog

Source: https://www.ollamaclient.in/about/changelog/
Markdown: https://www.ollamaclient.in/about/changelog.md
Description: Release history for Ollama Client.

All notable changes from Chrome Web Store releases are documented in this file.
GitHub-only release-candidate changes are consolidated into the next version
published on the Chrome Web Store.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/)
and this project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

## [0.13.3]

### Added

- Web search can route through the selected agent runtime's native search tool.
  Ollama Client still exposes one provider-neutral `web_search` tool and keeps
  configured SearXNG, Brave, and Tavily backends available as explicit choices.
- `olc` adds native Ollama lifecycle management with `--lan`, `--local`,
  `--check`, and `--json`, safe app/service ownership checks, process-scoped
  child environments, and strict option validation.

### Changed

- All olc backends now detach by default. `--debug` implies foreground; explicit
  `--foreground`/`--detached` control the session. Detached proxies report readiness,
  PID, private logs, and shutdown instructions.
- `olc` now defaults to native Ollama on port 11434. Use `olc -b codex`
  for the Codex proxy on port 8083 or `olc -b opencode` for the OpenCode proxy
  on port 8084; `-b` aliases `--backend`.
- Embedding requests use stricter cache identities, propagate cancellation
  through provider and storage boundaries, retry rate limits without discarding
  successful batches, and retain keyword context when dense embedding fails.
- Embedding batches and search-cache retention are tuned against reproducible
  performance benchmarks while preserving the extension bundle budgets.
- olc never persists app, service, user, or machine environment; an incompatible
  macOS app transitions to a standalone process safely.

### Fixed

- The macOS Ollama app now gets a full minute to finish quitting before olc
  gives up, and an exit during the final poll is treated as an exit rather than
  a timeout. Previously a slower-than-ten-second quit aborted the transition
  after the app had already been signalled, leaving no server running and no
  replacement started.

### Removed

- The model-callable `selected_text` reader is removed. Pending page selections
  remain an explicit, consumable composer handoff instead of silently becoming
  live tool state, so stale selections cannot be read during a later turn.

### Development

- Release metadata checks now reject a missing current-version changelog entry
  while workspace package versions continue to use the existing dynamic
  package-discovery contract.
- Packaged Chromium provider regression coverage now blocks on fragmented or
  malformed SSE handling plus HTTP and connection-failure propagation through
  durable turns, while custom provider base URLs remain fully configurable.
- Biome now enforces an initial cognitive-complexity ceiling so newly changed
  code cannot grow unchecked while the threshold is tightened incrementally.
- Verification scripts are organized by purpose and the release gate now builds
  each browser target once before reusing those artifacts for smoke, bundle,
  migration, recovery, and critical browser checks.
- Documentation articles remain centered on wide screens, terminal snippets use
  recognizable red/yellow/green window controls, and the README no longer
  advertises the removed selected-text tool.
- Every release now publishes the `olc.sh` and `olc.ps1` install wrappers with a
  `sha256` for each, alongside the archives they install. The READMEs lead with
  pinning a wrapper to a tag and verifying it before it runs; the one-line
  installer is documented below it as the unverified quick path, and every guide
  that shows it links to the verified one.
- Embedding generation from extension pages now crosses the validated,
  background-owned `embeddings.generate` RPC. The RPC preserves model/provider
  identity, forwards cancellation, and bounds stalled provider work with a
  generous 15-minute deadline. Background RAG and UI maintenance use application
  service seams instead of importing persistence adapters across ownership
  boundaries.

## [0.13.2]

### Added

- The `olc` local proxy now supports both OpenCode and Codex agent backends,
  including native tool-call round trips, provider-neutral generated images,
  installer scripts, and documented local run commands.
- Per-model reasoning effort can be configured and is translated to the native
  request shape supported by each provider.

### Fixed

- File RAG keyword search now indexes filenames, so questions referencing
  hyphenated filenames such as `ChatGPT-Memory.txt` retrieve their contents.

- RAG query reformulation now reuses the selected model's context, thread, GPU,
  batch, and keep-alive settings. Ollama no longer restarts the runner between a
  rewrite request using its default 4K context and a chat request using the
  configured context window.
- Embedding responses are validated before retrieval, cancellation reaches
  in-flight context and embedding work, and transient fallback vectors are not
  cached as if the primary route produced them.
- Query-rewrite history is bounded, expected rewrite timeouts fall back to the
  original query without a warning stack, and a real user cancellation remains
  distinct from that best-effort timeout.
- Imported or clock-skewed session trees recover to a structural leaf instead
  of attaching the next message to an internal timestamp-selected node.
- Generated-image requests through the Codex backend are routed to the image
  operation rather than falling through to text generation.

### Development

- Provider wire contracts now cover the built-in local providers plus major
  frontier, router, Anthropic, and Chinese frontier APIs while retaining fully
  configurable provider base URLs.
- Unit coverage runs in parallel shards with enforced thresholds. Packaged
  Chromium and Firefox regression gates exercise the extension-to-provider
  path, custom local-provider URLs, streaming text, malformed or partial SSE,
  HTTP and connection failures, and the Ollama model-reload regression.

## [0.13.1]

### Added

- Ollama cloud models are now discoverable. Local `/api/tags` discovery stays
  authoritative and hosted recommendations are appended only after a successful
  supplemental lookup, so malformed cloud metadata cannot invalidate the local
  catalog.

### Fixed

- The store listing name and description are restored. Both are generated from
  `src/locales/*/translation.json`, and the 0.12.7 store metadata was lost when
  0.13.0 reconciled its release ancestry — 0.13.0 shipped the pre-0.12.7 title
  in all nine locales.
- OpenAI-compatible model discovery now accepts both standard `{ data: [] }`
  catalogs and documented bare-array variants, normalizes common hosted
  context/capability fields, and keeps valid models when unrelated entries or
  optional metadata are malformed. A provider reporting an unknown context size
  is no longer rejected.
- Turns blocked by a disabled optional permission now surface the missing
  permission and resume after it is granted, instead of leaving the model to
  infer a capability it was never offered.
- Content hashing for embeddings sampled only the first 1000 characters of long
  text, so chunks sharing an opening collided and the cache returned another
  chunk's vector.
- A session whose stored leaf is absent from the message tree now falls back to
  the newest node instead of rendering an empty conversation over intact rows.
  An undecodable message tree raises rather than persisting a guessed parent.
- Loaded-model listing ignores stale responses, and an unload during an
  in-flight refresh no longer leaves the panel on a permanent spinner.

### Changed

- The BM25 keyword index no longer retains full embedding vectors, which
  duplicated what Dexie and the ANN backend already hold; hybrid search reads
  surviving candidates back by id before fusion.
- Markdown is parsed on a throttle during streaming instead of re-parsing the
  whole message per token, the parser is shared across bubbles, and session load
  reads a narrow projection rather than every message row.
- Page extraction runs on one refcounted sweep that pauses while the document is
  hidden, replacing one timer per mounted consumer and the concurrent
  extractions that came with it. The tab content cache is now bounded.
- Embedding configuration is memoized until `storage.onChanged` fires rather
  than re-read per chunk and per vector operation.

## [0.13.0]

### Added

- Ingestion and model-pull jobs now recover from MV3 background-worker
  suspension. Progress is checkpointed durably, interrupted work is reconciled
  on startup, and the UI can reconnect to the same job instead of silently
  losing it.
- Durable turns now resume through one background-owned lifecycle covering
  context building, generation, cancellation, completion, and failure. The UI
  reconnects to persisted snapshots after a worker restart rather than becoming
  a second writer of assistant state.

### Changed

- Native and prompt-based tool loops now share one checkpointed orchestration
  path for model calls, ordered tool batches, approvals, replay, and recovery.
  Approval boundaries are flushed before waiting, so a suspended worker can
  continue without repeating an already recorded effect.
- Chat history now ships with one SQLite implementation. The legacy database
  fallback runs on official sqlite-wasm instead of bundling sql.js as a second
  engine, while preserving the original migration source and read-only export
  recovery for damaged databases.
- Streaming events and durable tool-loop checkpoints are versioned and runtime
  validated before use. Invalid persisted state fails safely instead of being
  replayed as trusted data.
- Activity and retrieved-context labels persist translation keys with safe
  fallback text, so restored history follows the selected language instead of
  freezing generated labels in the language active when they were created.

### Fixed

- Requests that need disabled optional browser access now show a durable,
  localized recovery card in the conversation before model generation.
  Bookmarks, history, downloads, tab groups, browser sessions, and reminders
  can be enabled from the card and resume the original request automatically,
  or deep-link to their highlighted Privacy & permissions control. General
  discussion of topics such as world history does not trigger the prompt.
- Overlapping file submissions no longer replace each other's processing rows
  with stale UI state.
- Durable assistant messages can no longer be overwritten by a delayed UI
  persistence timer after the background has recorded a newer snapshot or
  terminal state. The separately characterized legacy stream path keeps its
  existing compatibility behavior.
- Malformed provider configuration, secret journals, and reset journals are
  rejected or recovered field-by-field without applying partial cleanup,
  exposing stored credentials, or discarding forward-compatible fields.

### Development

- Added environment-independent `@ollama-client/contracts`,
  `@ollama-client/runtime-core`, and `@ollama-client/chat-runtime` workspace
  packages. They own shared schemas, deterministic runtime primitives, and
  port-driven turn/context/tool-loop orchestration while browser, provider,
  persistence, and React adapters remain in the extension.
- Added architecture contracts for package dependencies, the single SQLite
  owner, repository access, background import direction, test placement, and
  JSDoc documentation comments.
- Release verification now covers independent package typechecks, 2,629 unit
  and integration tests, Chrome MV3 and Firefox MV2 packages, bundle budgets,
  generated resources, and packaged migration/restart fixtures.
- Dependency installation uses pnpm 11 with a seven-day minimum release age for
  newly selected packages.

## [0.12.8]

### Fixed

- Models you type in yourself now reach the model menu even when the provider
  has no model list to discover. A custom provider whose `/models` request
  failed had its manually added model IDs dropped along with the request, so the
  provider was absent from the menu entirely and nothing could be selected from
  it. The IDs are configuration, not discovery, and are now kept either way.
- Testing a provider that only implements chat — many hosted OpenAI-compatible
  routers do — no longer reports "Connection Failed". A server that answers the
  model-list request with "no such endpoint" is checked against the chat
  endpoint instead, using one of the model IDs you added and one token, and
  reported as working when a token comes back. A refused key, a rate limit, and
  a server error still fail as before. So do the two ways an address can answer
  without being a chat endpoint: one that takes the request and goes quiet is
  reported after twenty seconds, and one that replies without generating
  anything — what a proxy or a login page does — is reported as an address to
  check rather than counted as a reply.
- A mistyped base URL is now told apart from a provider that simply publishes
  no model list — both answer the same way — and reported as a base URL to
  check rather than as a working provider.
- A provider that returns HTTP 404 no longer reports "The provider
  configuration was not found", which described a different problem than the
  one you had. The provider's own message — which model or endpoint was missing,
  and what to check — is shown instead.
- The model menu now names providers that returned nothing, instead of leaving
  them silently absent from the list.
- Switching the theme in Firefox no longer leaves the extension sluggish. The
  saved preference was written back every time it arrived, and Firefox reports
  a write as a change whether or not anything moved, so one switch kept
  arriving and being rewritten for as long as the page stayed open. The
  preference is now applied only when it differs.

### Changed

- A provider with no model list is asked for one once, not on every refresh. A
  chat-only endpoint used to collect a failed request every few seconds — from
  the model menu and from the background connection check — for an answer that
  was never going to change. The answer is now remembered per provider on this
  device, and re-checked after a day, whenever the base URL, wire, or preset
  changes, and whenever you press Test.
- The background connection check runs once a minute instead of every ten
  seconds, and pauses while the settings page is in a hidden tab. Editing a
  provider still re-checks it immediately.
- A provider running on model IDs you declared is labelled as such rather than
  reported as a failed connection.
- Editing a provider's base URL no longer runs a connection test on every
  keystroke. Typing one URL fired one test per character — on a hosted
  provider, a real API call per keypress — and none of them told you anything,
  because the check reads saved configuration and you were still typing. The
  check now runs when a change is saved, and the status you see after saving
  describes the endpoint you just saved rather than the one before it.
- A support report no longer says "Provider reachable: no" for a provider that
  publishes no model list, and no longer says "yes" on the strength of a model
  list that the IDs you declared filled in on their own. It reports what was
  actually confirmed, and "not checked" when nothing was — a mistyped base URL
  and a working chat-only provider answer alike from there, and either guess
  sends whoever reads the report after the wrong thing.
- A provider that publishes no model list is marked "model IDs only" in both
  the provider grid and the panel header. Each read the model count on its own
  and showed a green connected dot for an endpoint the background check never
  contacted; the count comes from the IDs you declared. Testing the connection
  still reaches the endpoint and still reports what it found.

## [0.12.7]

### Changed

- The store listing now names the three verified providers in its title, so
  searching for LM Studio or llama.cpp can find the extension at all. The
  summary drops "Chrome extension" — which the store already knew, and which
  was wrong on Firefox, where the same text appears in the add-ons manager in
  every language — and names local RAG, web search, and page context instead.
- The README links the Firefox add-on. It has been published since 0.12.6 but
  the repository only offered a Chrome Web Store link.

No functional changes: this release is store metadata only.

## [0.12.6]

### Added

- The context sheet's tab list reports how many of the listed tabs are going
  into the prompt, and gains a select-all control scoped to whatever the search
  filter is showing — so a filtered selection never silently includes tabs you
  cannot see. Once every listed tab is selected, the same control clears them.

### Changed

- Model parameter sizes now come from whatever each server actually reports, and
  are shown on one scale. LM Studio models read their size from the model id,
  since no LM Studio endpoint reports a size of any kind; OpenAI-compatible
  servers (vLLM, LocalAI, KoboldCPP, llama-swap) do the same, so a self-hosted
  `Qwen3-8B` no longer shows a blank badge next to sizes from Ollama and
  llama.cpp. Ids that do not state a size unambiguously stay blank rather than
  having one guessed for them.
- Ollama models stored as safetensors or MLX now show their family, size, and
  quantization instead of blank fields. `/api/tags` omits those for non-GGUF
  models, so they are filled in from `/api/show` for exactly the models missing
  them, with the result cached per model file.
- LM Studio models that report tool support in their catalog entry now have tool
  calling detected from that report rather than inferred from a provider
  default.
- The capability sheet now describes what your provider reported for *this*
  model — everything, some of it, or nothing — instead of a fixed claim about
  the provider. **Detect** runs its checks one at a time, so a local server
  loading a model no longer spends the other checks' timeouts waiting behind it,
  and a check that could not finish is now named as unfinished instead of shown
  as an unsupported capability.
- Context sheet rows carry one stable label each ("Page & tab context", "Search
  uploaded files", "Web search"); the checkmark alone shows whether a row is on.
  Labels no longer change wording when you enable them.
- The context summary moved under the sheet's title, where it stays visible in
  every view, and screenshot capture joined the upload row — both stage an
  attachment for the next message. Permissions & privacy and Attachments now
  show a chevron, which is the sheet's only navigation affordance.
- Dense side-panel rows across the model menu and context sheet share one
  spacing scale. Leading edges had drifted to 8/16/18/26 pixels within a single
  sheet, the model menu reserved about 33 pixels of unusable space on the right
  of every row, and the tab list was capped at a height that clipped a row
  mid-way while leaving the rest of the sheet empty.
- Model icons are matched on name tokens. "dolphin-llama3" is no longer given
  the Phi icon because its name contains "phi", "codellama" reaches the code
  icon, and embedding models are recognized as embedding models before their
  family is considered. Added icons for starcoder, mixtral, qwen, and deepseek.
- Bumped package version to `0.12.6`.

### Fixed

- A reply that finishes without any answer now says so and offers a retry.
  Providers report a model unloaded mid-turn — or a conversation with no room
  left to answer in — as a successful, empty response, which used to leave a
  blank assistant bubble with nothing to read and no way to retry.
- Every message on the send path is now translated: the "no model selected" and
  provider-selection warnings, the failures for creating a chat and saving a
  message, the context-preparation failure, the grounded-only refusal, the
  context-trimmed notice, and the retrieval warning. All of these previously
  appeared in English regardless of the selected language.
- YouTube transcripts now come from the video you are watching. YouTube changes
  videos without reloading the page, so the transcript could be read from
  whichever video the tab opened on, with nothing to indicate the mismatch.
  Captions also prefer your browser's language when the video offers them, with
  English as the fallback; timestamps are still included on every line.
- A cancelled model-list request now reports the cancellation instead of
  returning a partial catalog assembled from whatever finished first.
- The capability sheet no longer credits a provider's catalog for a capability
  that was actually taken from the provider default.
- Reasoning support is no longer reported as definitively absent for LM Studio
  models. Their catalog does not describe reasoning at all, so a reasoning model
  could be marked as not supporting it; it is now left for a probe or your
  override to settle.
- Repeated model lists no longer re-request the same model details on every
  refresh.
- Staged images in the attachments view now fill the sheet's width instead of
  sitting as small fixed tiles in an otherwise empty panel.
- Restoring a backup made by version 0.6.3 or earlier now says that its chats are
  in a format the extension no longer reads, instead of reporting the archive as
  missing a database file. Its settings, embeddings, and knowledge sets still
  restore.

### Development

- Chat-database worker failures now report their cause — message and source
  location, including for a worker that fails to load — rather than "worker
  crashed", and a message the worker cannot clone no longer leaves its caller
  waiting forever. That reporting immediately identified a development-only
  failure where the dev server's origin was missing from `worker-src`, so
  durable chat history could never migrate to OPFS under `pnpm dev`. Packaged
  builds are byte-identical, and a test asserts a dev origin cannot reach a
  packaged manifest.
- The selection overlay reads its state from a context instead of forwarding 32
  props through five components, so adding a control is one edit rather than
  four.
- The chat context sheet is split by job: settings, tab-list reconciliation,
  summary composition, and views each own a module, leaving the sheet itself at
  about 205 lines.
- Icons are imported from `lucide-react` directly; the re-export barrel bought
  no bundle savings and enforced nothing, and it split the convention across 116
  files.
- Removed components with no caller outside their own layer, and fixed component
  name suffixes to describe what each one renders.
- Split the settings search/deep-link registry into one module per options tab
  while preserving its existing public API and ordering.
- Added a policy registry for retained runtime messages and ports, plus source
  contracts that keep chat history behind its repository facade, SQLite
  internals out of feature/UI code, and feature stores out of the root store
  directory.
- Extracted the tab-context picker from the chat context menu so tab browsing
  and preview behavior can evolve independently from attachment and model
  context controls.
- Stopped generating the obsolete all-languages TypeScript catalog. App
  translations remain source JSON files loaded as one lazy chunk per language;
  generation now produces only extension metadata and the small selection
  overlay catalogs.
- Resource generation no longer runs on `pnpm install`. Every build script
  already runs it, the committed extension locales do not depend on it, and CI
  keeps its own generated-drift and translation gates.
- Aligned local verification with CI's dead-code and translation-completeness
  gates, and extended browser smoke checks to enforce lazy locale packaging for
  both browser targets.

### Documentation

- `AGENTS.md` is organized around rules rather than history, and now documents
  capability detection, the per-server differences in what a model list reports,
  and the development-build facts that were previously only learned by
  rediscovering them.

## [0.12.5] - 2026-07-29

### Added

- Chrome and Firefox package budgets now cover unpacked size, ZIP size, the
  largest generated chunk, duplicate binary assets, and critical entry
  surfaces. Dead-code checks also run in CI.
- Two new diagnostic self-tests. **Local provider CORS rule** reports whether
  Chromium's request-header rule is installed and still matches the provider
  address you have configured — a rule left behind by an older address looks
  identical to an unreachable server otherwise, and those two are the most
  commonly reported failures. Firefox reports it as not applicable, since it
  asks you to configure the origin on the server instead.
- **Turn recovery checkpoints** self-test, which checks that an interrupted
  reply can still be recovered and that a turn waiting at a tool-approval
  prompt is not mistaken for an abandoned one.

### Changed

- Ordinary pages now load only a small selection detector. The React selection
  overlay, its active-locale catalog, page extraction, provider-model
  discovery, inactive settings tabs, and backup code load only when needed.
- Extension icons now use purpose-sized 16–128 pixel assets instead of shipping
  one oversized source image.
- Removed Mermaid runtime rendering and unused font subsets. Mermaid source can
  still be previewed as text, copied, and downloaded.
- Standardized typechecking on one TypeScript package.
- Release and documentation scripts now use the installed `tsx` executable
  instead of allowing `npx` to resolve or download a different version.
- Prompt templates are stored as individual database rows instead of one
  synced blob. Editing a template no longer rewrites the whole library, and a
  large collection can no longer fail to save because the sync-storage limit
  was reached. Existing templates move across on first use, import and export
  are unchanged, and anything that fails to convert is left in place rather
  than discarded.
- Settings now report an over-limit save with the setting that caused it,
  instead of the browser silently rejecting the write.
- Loaded-model details for LM Studio now show model family, size, and
  quantization instead of blank fields.
- Model information, loaded models, unload, warm-up, model-library search, and
  embedding-model checks all moved onto the internal typed request boundary
  introduced in 0.12.4, which validates both ends and keeps credentials and
  endpoints out of results.
- Bumped package version to `0.12.5`.

### Fixed

- Selection-overlay injection can recover from transient background injection,
  locale loading, and mount failures. The bootstrap waits for an explicit
  ready signal and releases its retry latch when startup does not complete.
- A duplicated provider entry is now collapsed to one, keeping whichever copy
  holds your API key or custom models. Previously both entries could persist,
  with the second invisible to everything that looked a provider up by name
  while still appearing in the provider list.
- Removed three provider actions that no code path could reach.

### Security

- Page, web-search, browser-history, selection, screenshot, and local-document
  tool results are marked as untrusted input. When one enters a turn, approval
  grants issued against earlier input no longer authorize later tool calls,
  and a tainted turn cannot create a persisted **Always allow** grant.

### Development

- CI now rejects generated-resource drift and incomplete translations
  explicitly, in addition to type, lint, dead-code, test, package, and bundle
  checks.
- Critical packaged-browser persistence tests cover Chromium owner restart,
  migration, rollback-blob integrity, and durability behavior.
- Added a machine-readable compatibility ledger with source-version,
  removal-gate, target-release, and recovery-path ownership for retained legacy
  behavior. The sql.js live fallback remains in `0.12.x`; removal is gated for
  `0.13.x`.

### Documentation

- Search engines are pointed at the 18 written guides rather than the 62
  auto-generated API reference pages, which had been outnumbering them more
  than three to one in the sitemap.
- Pages now publish a last-updated date, breadcrumb information, and a correct
  canonical address whether or not the address ends in a slash.
- Preview deployments of the documentation site now refuse indexing outright
  instead of relying on the hosting platform's default.
- The AI-entrypoint files (`llms.txt`, `ai.txt`) take their page order from the
  same source as the sidebar, so the two can no longer disagree, and a page
  missing a description fails the build instead of silently advertising the
  site's generic one.

## [0.12.4] - 2026-07-24

### Added

- Chat errors now carry a stable support code, an incident ID, and the failure
  phase, and a failed turn is styled as a failure rather than as model output.
- Recovery actions on the failed message itself: re-enable a switched-off
  provider and re-run the turn, wait out a rate limit, or jump straight to the
  setting involved.
- Failure details are saved with the message, so a report survives reopening the
  side panel or restarting the browser.
- **Copy diagnostics** beside **Open an issue**, with a matching empty code block
  in the draft to paste into. Generated locally; nothing is uploaded on its own.
- A reference for every error code the extension can show, under Docs → Guides →
  Troubleshooting → Error reports.
- A post-uninstall feedback page. It receives only the extension version and
  interface language — no identifier, no usage data, no chat content.

### Changed

- Reduced the packaged extension size by dropping a duplicate SQLite WASM binary
  and a redundant bundled PDF worker (Chrome package about 6.3 MB down to about
  4.3 MB), with no change to features or behavior.
- Selected the persistence owner for each browser at build time so a build ships
  only its own owner path — the Chromium offscreen document or the Firefox
  background page — instead of carrying both.
- Raised the minimum supported Chrome version to 116, the real floor for the
  OPFS SQLite persistence backend, so the requirement is stated honestly.
- Consolidated provider HTTP error handling into one shared path for consistent
  status codes, retry hints, and user-facing messages across providers.
- Every bug-report draft now carries the same environment details, paste block,
  privacy note, and length safeguards, wherever it was started from.
- One report action per failed turn instead of two with different detail.
- Recovery buttons stop being offered once a failure is over an hour old, so
  scrolling back cannot re-run an old turn or change a provider setting by
  accident. The link to the relevant setting stays.
- Diagnostic self-tests are shared briefly between requests, so viewing several
  failed messages no longer repeats the same provider checks. **Run self-tests**
  always measures fresh.
- Bumped package version to `0.12.4`.

### Fixed

- Provider errors now identify the provider, model, sanitized base URL, and HTTP
  status, while keeping credentials and raw upstream responses private.
- Disabled providers can no longer serve chat, selection-action, RAG
  reformulation, or model-warmup requests from a stale model selection.
- Provider adapters recognize missing or unloaded models, context limits,
  unsupported input, memory exhaustion, rate limits, overload, and interrupted
  streams without exposing raw responses. Filesystem-shaped model IDs redact
  local account names in drafts.
- Reports read the provider's on/off state instead of inferring it, and label a
  duration measured against an unreachable provider as time-to-failure.

## [0.12.3] - 2026-07-23

### Added

- Added OpenRouter support and normalized remote-provider handling, including
  durable replay of provider reasoning metadata across tool calls and restarts.
- Added a versioned, validated provider RPC boundary for configuration,
  connection tests, and model discovery, with authorization, safe errors,
  timeouts, and end-to-end cancellation.
- Added a provider-neutral onboarding flow and local diagnostics for connection,
  storage, permissions, and browser compatibility.
- Added a single-owner OPFS SQLite persistence backend with verified migration
  and packaged-browser persistence benchmarks for Chrome and Firefox.
- Added durable SQLite checkpoints for native and prompt-based tool loops, with
  same-request recovery after MV3 service-worker restarts.
- Added native Anthropic Messages API support for user-added providers,
  including streaming, images, tool calls, and manual model IDs.
- Added session tags, explicit message forks, and a local-data inventory with
  backup and wipe controls.

### Changed

- Rebuilt the settings and maintenance experience with intent-based navigation,
  searchable settings, consistent controls, improved responsive layouts, and
  clearer status and recovery feedback.
- Centralized provider capability detection and model routing so saved mappings
  and runtime evidence remain the source of truth.
- Marked custom provider setup as Beta to reflect its first public release and
  distinguish it from verified built-in providers.
- Limited verified built-in provider profiles to Ollama, LM Studio, and
  llama.cpp; other compatible endpoints now use the custom-provider flow.
- Unified composer context controls and RAG chunking, simplified message edits,
  and disabled chat-memory indexing by default for new profiles.
- Added Ollama model capability overrides and made model refresh invalidate
  cached capability details.
- Adopted the TypeScript 7 compiler and reduced build and test times.
- Bumped package version to `0.12.3`.

### Fixed

- Fixed provider state races involving saves, model refreshes, tool probes,
  provider switching, and stale RPC responses.
- Fixed provider removal confirmation remaining open and retargeting another
  provider after a successful removal.
- Fixed backup import and reset flows for encoded settings, open database
  handles, and loading-state recovery.
- Fixed interrupted chat persistence, atomic message saves, provider error
  attribution, alternating tool-result roles, and native llama.cpp tool loops.
- Fixed provider lifecycle requests using inconsistent base URLs, failed model
  details being cached as successful empty data, and invalid runtime payloads
  leaving message channels open.

### Security

- Upgraded PostCSS to `8.5.16`, removing the vulnerable docs-build dependency
  path reported in `GHSA-6g55-p6wh-862q`.
- Kept provider API keys and other private provider state in device-local
  storage and excluded them from backups.
- Redacted private values from diagnostics and restricted runtime messages to
  authorized extension surfaces.
- Sanitized print and PDF export content and bound sensitive browser-tool grants
  to their approved origin.

## [0.11.27] - 2026-07-01

### Added

- Unified chat search across session titles and message content, with localized
  empty and clear-search states.
- S4 vector durability smoke coverage: persist a chunk, reload the module graph,
  and verify similarity search still finds it.
- Competitor comparison pages for the documentation site.
- OpenAI-compatible provider round-trip smoke coverage:
  stream a response, persist the assistant reply, reload the SQLite facade, and
  assert the reply survives.
- SEO foundation docs: quick start, privacy, FAQ, and Ollama CORS troubleshooting
  pages, with FAQPage structured data and higher-signal homepage retrieval copy.
- An always-visible context-state pill and pre-send context preview covering page tabs, attached files, local knowledge, and web search.
- A live model-tools inventory in Privacy & permissions showing family and browser-permission availability.
- An in-panel provider setup flow for first-run connection failures and empty model lists.
- Optional, permission-gated tools for recently closed tabs/windows and synced-device sessions. Session reads honor unreadable and never-read URL exclusions.
- Automated 0.10.3 provider-storage upgrade contracts and a `verify:release` gate.
- A guarded `tabCapture`/offscreen feasibility contract documenting browser and product blockers before capture UI ships.
- Permissions & privacy panel (Options + chat popover) with optional, on-demand browser permissions and feature-flag gating.
- Global keyboard shortcut and omnibox (`olc`) quick-ask to open and send to the side panel.
- Notifications and reminders.
- Page screenshot into vision chats, with optional auto-attach for vision models.
- Browser knowledge: optional RAG over bookmarks/history that honors exclusion scope.
- Per-site content-extraction profiles and tab-group workflows.
- Artifact previews (canvas) with per-artifact downloads.
- Prompt template variables.
- Model-callable tools `save_artifact` (write generated text to disk) and `capture_screenshot`, plus a multimodal tool-result path.
- Per-model and per-family tool governance.
- Session count badge in the chat-sessions sheet header.

### Changed

- Updated shadcn tooling and added restrained scroll fades plus live-status
  shimmer to existing chat and settings surfaces.
- AI-readable docs now remove MDX `export const` data and SEO-only FAQ markup
  while preserving the rendered documentation prose.
- Polished the prompt sheet, options tab naming, sources icon, and compact
  scroll-to-bottom control.
- Bumped package version to `0.11.27`.
- Local OpenAI-compatible `401`/`403` failures now point users at CORS/origin
  setup instead of misleading API-key guidance when the provider URL is local.
- Docs site upgraded to Astro 7 and Starlight 0.41, with the Mermaid markdown
  hook moved to Astro's current markdown processor API.
- RAG, page/tab context, and web results now share one grouped Sources sheet per answer.
- Settings navigation is grouped by user intent while preserving existing tab ids, deep links, and persisted storage keys.
- Technical labels now use plain-language names such as Knowledge & web, Knowledge storage, Page & tabs, and Data & backup.
- Privacy is a first-class settings group with an explicit local-storage overview.
- Streaming follows output without restarting smooth-scroll animations, and returning to the bottom no longer waits 300 ms.
- Queued assistant replies use a stable message-shaped loading skeleton.
- Optional-permission switches now react immediately when access is granted or revoked from browser extension settings.
- Chrome-only manifest permissions are omitted from Firefox builds at generation time.
- Chat header, session selector, semantic search, provider status, embedding status, and export controls use a quieter compact icon treatment.
- The per-session export shortcut no longer occupies the chat header.
- Long-running model/embedding fetches now time out instead of hanging.
- RAG and background memory context capped to the configured character budget.
- Message-router payloads centrally parsed and validated.
- Alarms permission made optional; removed the unbuilt prompt-chaining flag.

### Fixed

- Selection Actions now preserve configured model system instructions and
  requested output language instead of biasing extraction results toward English.
- Message footers use explicit export and delete actions instead of ambiguous
  ellipsis menus, and chat-memory sources use a primary-colored user icon.
- Session titles now truncate through CSS without clipping focus rings, chat
  search resets cleanly, and the scroll-to-bottom button hides near the end.
- Browser smoke verification no longer calls the deleted Firefox manifest post-processing script.
- Browser automation now serializes TSX callbacks safely, waits for fonts before screenshots, and completes live Chromium/Firefox chat checks.
- Firefox builds declare no extension data collection and no longer emit the missing declaration warning.
- SQLite durability hardened: foreign keys on (cascade deletes) and an explicit flush path on unload/restart.
- HNSW vector index reloads on service-worker restart and tolerates duplicate ids; vector deletes reconciled across stores.
- "Reset" now wipes provider API keys and no longer skips string-keyed modules.
- Content extraction restores patched `fetch`/XHR instead of leaving the host page rewrapped.
- Streaming: error path keeps the message id, and abort is keyed per-stream so concurrent chats don't cancel each other.
- Scoped the per-token re-render storm to the active session.
- Message delete now asks for confirmation.

## [0.10.3] - 2026-06-20

### Added

- i18n-backed settings search index that searches translated labels, descriptions, and visible child strings instead of only hand-written headings.
- Ranked settings search with case/diacritic/punctuation normalization, partial-token matching, and typo-tolerant fuzzy matching for common misses like `provder`, `ollma`, and partial queries like `prese`.
- Search coverage for provider controls, prompt templates, keyboard shortcuts, guides, reset modules, reset danger zone, embedding storage stats, semantic search, cache, ANN, and advanced embedding search controls.
- Cmd/Ctrl+K shortcut on the options page to focus settings search, plus compact placeholder-based search hints for smaller screens.

### Changed

- Settings search results now show the matching translated child text with parent context, then deep-link to the owning tab and focus/highlight the concrete control where possible.
- `useChat` now delegates turn lifecycle work to `useChatTurnController`, keeping the public hook focused on wiring state into the chat UI.
- Chat composer attachment handling, file-upload pipeline work, and provider settings panels were split into smaller focused modules without changing storage keys or public behavior.

### Fixed

- Settings search now finds presets, browser settings, base URL/API key provider controls, prompt/shortcut/guide text, and embedding search internals that were previously missed.
- Search deep links no longer stop at the right tab for many controls; focus IDs were added across settings cards, fields, reset rows, guide rows, shortcut rows, and provider controls.
- Duplicate `search-limit-topk` focus targets between Context and Embeddings were separated so highlights land on the intended control.

## [0.10.2] - 2026-06-16

### Added

- Provider-agnostic web search tool (`web_search`) for tool-capable models, gated behind device-local settings and exposed as one model-visible tool regardless of backend. Initial backends are SearXNG, Brave Search, and Tavily.
- Local SearXNG Docker Compose setup under `searxng/` for private development/testing with JSON search enabled.
- Web search settings in the Context tab: enable toggle, provider selector, API key/endpoint fields, safe-search, result count, SearXNG page count, beta badge, provider base URL transparency, and test search.
- Chat composer globe toggle for enabling/disabling web search without leaving the chat.
- Settings registry, settings search, per-section reset, preset previews, and one-click presets for common configuration profiles.
- Lenient chat import salvage path that keeps recoverable sessions and reports per-session diagnostics instead of dropping whole imports.

### Changed

- Documentation domain moved to `https://www.ollamaclient.in/`.
- Documentation updated for image input, browser-context tools, and model capability gating.
- Tool guidance now tells models to use `web_search` for current/time-sensitive facts, include the current date in search planning, and cite returned URLs.
- Web-search results are normalized, capped, and treated as untrusted snippets before being returned to the model.
- Web-search sources now split used and unused results, show richer metadata, and keep source identity stable when multiple tool runs return the same URL.
- Web-search backends now support time-range filtering where available and dedupe normalized URLs before result caps are applied.

### Fixed

- Thinking-only tool responses now surface as the visible assistant answer instead of falling through to the generic "no final answer" fallback.
- Ollama and LM Studio provider capability docs now report tool-calling support correctly; Ollama model-level tools still require the model's reported `tools` tag.
- Settings batch writes now fail fast if scalar and field-level writes are mixed for the same storage key instead of silently dropping one write.
- Settings `focus` URL params are cleaned up after use so tab changes do not retry stale highlights.

## [0.10.1] - 2026-06-13

### Added

- Tool calling runtime (foundation): tool-capable models can call internal tools mid-conversation, with the calls and results round-tripped through both provider adapters (Ollama native `tools` + `tool`-role results; OpenAI-compatible `tools`/`tool_calls`). Gated on the model's resolved `toolCalling` capability — non-tool models are completely unaffected.
- Provider-agnostic, MCP-ready architecture: a `ToolSource` abstraction with a `ToolRegistry` that aggregates sources and routes calls by name. Internal tools are the first source; a future MCP server registers as another source with no change to the adapters, the tool loop, or the UI.
- Internal tools, all running locally: `rag_search` (past-conversation memory), `file_search` (uploaded/indexed documents), `current_tab` (active tab's readable text, incl. YouTube transcript), `list_tabs` + `read_tab` (enumerate and read any open tab by id or title/URL — answer about any tab without adding it through the tab-context UI), and `selected_text` (most recent page selection). Tab tools inject the content script on demand, so tabs opened before the extension load are read without a refresh. They honor the user's excluded-URL settings and explain gracefully when a tab is a browser-internal page (chrome://, web store) rather than failing.
- Transparency: the chain-of-thought reasoning trace now shows each tool run live (name, running/done/error status, and the sources it looked at), so it is always visible what the extension is doing on the user's behalf.
- Image / vision input: attach images to a chat message for vision-capable models. Drag-and-drop, file picker, and clipboard paste are supported; staged images appear in the composer's attachment sheet (reusing the file-attachment UI) and as click-to-enlarge thumbnails in sent messages.
- Image attach is gated on the selected model's resolved `vision` capability — non-vision models show a clear blocked state pointing at the model-menu capability override.
- Provider adapters send images in each provider's native format: Ollama `images` (base64), OpenAI-compatible `image_url` content parts.
- Images persist with the chat (reused `files` table, no schema migration) and reopen with previews.
- Configurable per-image size cap on the options page (default 10MB). Supported formats are PNG, JPEG, and WebP; HEIC/HEIF shows a specific "export as JPEG/PNG" message. Strings translated into all supported locales.
- Model capability detection foundation: a normalized `ModelCapabilities` layer (`text`, `vision`, `tool calling`, `reasoning`, `context length`) resolved per model with a `source` and `confidence`, layered as **user override → model metadata → provider default**.
- Capability detection across all providers: Ollama `/api/show` capability tags (high confidence), LM Studio model `type` (`vlm`/`embeddings`, medium confidence), and provider defaults elsewhere. Unknown capabilities resolve to off — never enabled on a guess.
- Per-model capability badges in the model menu (completion, vision, tools, thinking, embeddings) with tooltips, fetched only while the menu is open and cached.
- Manual capability overrides: a Model Capabilities sheet for models whose provider can't self-report, to declare vision/tools/etc. by hand. Overrides persist per model and are sync-safe. Translated into all supported locales.

### Changed

- Tool calls are now inspectable in the reasoning trace: each tool step shows its name, status, the input arguments the model passed, and a preview of the output (or the error / sources / "trimmed" note). The panel auto-expands while a tool is running and collapses once the answer streams.
- Reasoning ("thinking") is now shown inline and live instead of behind a click-to-open popover. It auto-expands while the model is thinking — so on reasoning models like qwen3, where the long thinking phase used to look frozen with the answer appearing all at once, the live reasoning is now visible and scrolls as it streams; it collapses once the answer starts and can be toggled anytime.
- When tools are offered to a model, the system prompt now names them and tells the model to call them for "current page / this video / my files / open tabs / selected text" questions. Without this, capable models sometimes replied "I can't access your tabs" instead of calling the tool. (Reasoning-distill models such as deepseek-r1 still tag `tools` but call them unreliably — prefer qwen3 / llama3.x for tool use.)
- Tool results are now trimmed to a configurable per-result character cap (default 10,000) before the model reads them, so a long page, transcript, or document dump no longer balloons the prompt and stalls generation on a laptop. When a result is trimmed it is shown in the reasoning trace ("result trimmed — change limit in Settings → Context") and the limit is adjustable on the options page.
- Model tool-capability is cached per session instead of re-fetched (`/api/show`) on every message, cutting pre-stream latency and request churn.
- Each tool call has a 60s timeout; a hung tool degrades to an error result instead of blocking the chat.
- Browser tab access now defaults to **on** so tab context and the tab tools work out of the box (still toggleable from context settings / options).
- Sending a message now shows the "Thinking…" state immediately. Previously the indicator only appeared after pre-stream work (RAG embedding, vector search) finished, so a slow context build looked like nothing was happening.
- `read_tab` now treats a stale tab id as recoverable: it refreshes readable tabs and falls back to the active readable tab when possible, instead of surfacing a hard tool error.
- Tool-call status icons and labels were tightened so provider health, embedding health, exports, context controls, stop generation, and session drawer actions read correctly at a glance.
- Provider errors now surface a clean, human-readable message in chat instead of the raw provider response body (the raw text is kept for diagnostics only).
- OpenAI-compatible providers no longer default to `https://api.openai.com/v1`; a blank base URL falls back to a local endpoint so a misconfigured provider never silently sends data to a cloud API.

### Notes

- The tool exchange is ephemeral, mirroring RAG context injection: only the final answer and the tool-run trace persist — no schema migration and no new message rows.
- Architecture is MCP-ready: a future MCP server registers as another tool source with no change to the adapters, loop, or UI.

### Fixed

- Image attach no longer false-blocks on the first try while the selected model's vision capability is still being detected.
- Capability override sheet: an external (Chrome-sync) update no longer overwrites unsaved edits, and a failed save keeps the sheet open and surfaces the error instead of failing silently.
- Per-model capability overrides are written through a serialized queue so two rapid saves can't drop one another.
- Reranking no longer silently drops documents that lack an embedding; they keep a neutral score instead of being removed from results.

## [0.8.0] - 2026-06-10

### Added

- Selection Actions: selected page text now opens a local AI action toolbar with Summarize, Rewrite, Shorten, Fix Grammar, Explain, Extract Action Items, Translate to English, and Custom Prompt actions.
- Floating result panel with streaming output, retry/cancel, copy, Open in Chat, and preview-first Replace/Insert controls.
- Safe page editing helpers for `input`, `textarea`, and simple single-block `contenteditable` selections. Generated output is inserted as plain text only so page UI and heading/list structure are preserved.
- Selection Actions settings for enablement, minimum selected characters, and enabled action list.
- Thinking/reasoning model support in the selection overlay: live "Reasoning…" section with animated pulse indicator auto-expands during streaming and collapses when done.
- Inline model selector in the panel header (same row as title); filters out embedding models; syncs with sidebar model selection.
- Dev-only Theme Lab for tuning sidebar, chat, composer, message, and control tokens live during local development.
- Context preview sheets for selected tabs, RAG sources, and attached files with searchable tab context and scrollable extracted text previews.
- Tab count badge on the context menu icon shows how many tabs are active in the current context.
- Copy button on each RAG source and tab context chunk (inside the sources sheet) for quick content copying.
- Copy button on expanded file attachment previews in the composer attachment sheet.
- Markdown rendering in the selection overlay thinking/reasoning panel during streaming.

### Changed

- Selection overlay fully rewritten as a React component (`SelectionOverlayApp`) mounted inside the shadow DOM, replacing the prior imperative content-script logic. State is managed by a `useReducer` state machine; stream lifecycle is handled imperatively to avoid declarative/imperative conflicts.
- Selection overlay panel split into focused sub-components: `PanelHeader`, `PanelThinking`, `PanelFooter`, `SelectionPanel`, `SelectionToolbar`.
- Panel uses shadcn `Card` and `buttonVariants` for design-system consistency with the rest of the extension.
- Shadow DOM CSS extracted to `overlay-shadow-styles.ts`; stream chunk/done/error logic extracted to `overlay-stream.ts`; content script reduced from 966 to ~530 lines.
- `SourceAccordionItem` renamed to generic `AccordionCard` with an optional `metadata` prop — reusable outside the RAG/source context.
- `MessageSourcesSheet` now uses `PreviewSheet` as its structural shell, eliminating the duplicated sheet/header layout.
- `PreviewSheet` body wrapped in a bounded flex scroll container so content always scrolls within the sheet height rather than overflowing it.
- Accordion item content areas (RAG chunks, tab context) capped at `min(16rem, 40vh)` with vertical scroll, matching the attachment preview behaviour.
- Sidebar, chat transcript, composer, message footer, run details, and session metrics now use the token-driven compact UI system.
- Chat action buttons now render from shared tooltip/action primitives with smaller icon sizing and compact overflow behaviour.
- Session metrics moved into the chat header as a compact metric trigger with a short popover summary.
- File attachments in the composer now sit in a compact horizontal rail; attachment list and prompt selector dialogs replaced with right-side sheets.
- `IconBadge` component extracted to deduplicate the icon + count badge pattern used across context buttons.
- Icon sizes standardised to `icon-xs` for thumbs up/down feedback and source-chunk action buttons.
- Chat/session stores, content scripts, provider settings, and selection-action UI split into smaller focused modules.
- Magic-number timeouts extracted into named constants.

### Fixed

- Selection toolbar not reappearing after closing the overlay and re-highlighting text on the same page.
- Shorten, Cancel, and more-menu actions broken in the selection overlay due to a stream lifecycle conflict between a declarative `useEffect` controller and imperative `setTimeout(startStream)` calls. Resolved by removing the `useEffect` controller entirely.
- Selected text now included in the message when opening a selection result in chat, with a separator between the quoted text and the action output.
- Streaming renders in the selection overlay throttled to prevent layout thrash on fast-arriving chunks.
- Shadow DOM CSS variables now isolated from host-page design tokens by pinning all tokens with concrete OKLCH values on the container element.
- Tailwind rem-based sizing fixed on pages with non-standard root font-size (e.g. YouTube) by overriding spacing, text, and radius with absolute `px` values.
- Toolbar/panel placement corrected for pages that apply CSS `transform` to ancestor elements.
- Reasoning trace state now distinguishes thinking from answering and avoids duplicate streaming indicators.
- Context injection now respects selected page/RAG state instead of leaking stale context across conversations.
- Chat history now uses the SQLite facade only; the Dexie chat-history fallback has been removed.
- Left border removed from PDF message export cards.
- Extra padding on guides page and prompt list.
- Session metric now centred in the chat header.
- File chip sizing and composer attachment rail layout.
- Embedding models filtered from the panel model selector using the same `isEmbeddingModel` check as the sidebar.
- Shadow DOM CSS variables now isolated from host-page design tokens (YouTube, etc.) by pinning all tokens with concrete OKLCH values on the container element.
- Tailwind rem-based sizing (`h-7`, `size-*`, `gap-*`) fixed on pages with non-standard root font-size (e.g. YouTube `html{font-size:62.5%}`) by overriding `--spacing`, `--text-xs`, and `--radius` with absolute `px` values.
- All remaining `rem` values in shadow DOM custom CSS replaced with `px` so sizing is consistent across all host pages.
- Toolbar/panel placement corrected for pages that apply CSS `transform` to ancestor elements (creates a shifted fixed-positioning context); drift is measured and compensated after initial placement.
- Tooltip dark mode background uses card colour instead of foreground in shadow DOM context.
- Tooltip arrow hidden in shadow DOM.

## [0.7.3] - 2026-06-02

### Added

- Standardized error handling across all background handlers, providers, and storage layers with typed error envelopes and centralized `error-handler.ts`.
- Improved user-facing error display with guidance text mapped to common failure modes (connection refused, model not found, auth errors, etc.).

### Fixed

- System prompt now autosaves on change;
- Astro docs BaseLayout: replaced invalid Tailwind v4 `supports-[backdrop-filter]` syntax with standard `supports-backdrop-filter`.
- Theme toggle button on mobile screens: switched from duplicate `id` attributes to `data-theme-toggle` + `querySelectorAll` so multiple toggle instances work correctly.

## [0.7.2] - 2026-06-01

### Fixed

- YouTube watch pages now extract only the video title and transcript instead of falling back to generic page content.
- YouTube transcript extraction now supports modern transcript panels, legacy segment renderers, and caption-track fallback data.
- Udemy lecture pages now try the transcript panel first and fall back to normal page extraction when no transcript is available.
- Removed stale provider configs, such as OpenAI entries no longer present in the provider UI, from saved provider settings.
- Restored the lockfile dependency resolution for frozen CI installs.

### Changed

- Tab-context retrieval now respects the configured maximum context budget during RAG retrieval.
- Local development logging defaults to debug level for easier extraction troubleshooting.

## [0.7.1] - 2026-05-30

### Added

- Zod runtime validation across all JSON.parse sites in provider, storage, and prompt-import paths.
- Structured logger (`src/lib/logger.ts`) replacing ad-hoc `console.*` calls throughout the background, provider, and storage layers.
- `pnpm verify` convenience script: `pnpm typecheck && pnpm lint:check && pnpm test:run`.

### Changed

- Provider factory: replaced `if/else if` chain with `Record<ProviderId, ProviderConstructor>` lookup.
- Docs synced: README, AGENTS.md, and docs-src version/LOC references updated for 0.7.1.

### Fixed

- Removed catch-and-silence patterns in provider error handling — all catch blocks now log through the structured logger.

## [0.7.0]

### Added

- Chrome extension package localization metadata (`default_locale`, manifest `__MSG_*` substitutions, and `_locales` messages) so Chrome Web Store can detect supported languages.
- 0.7.0 frontend foundation: app-owned layout, form, settings, and feedback primitives that sit above shadcn/Base UI so preset refreshes do not own product behavior.
- Data-display primitives for repeated provider, model, source, file, metadata, context preview, command item, and info-list patterns.
- React Hook Form-safe controlled wrappers for number inputs, sliders, text inputs, textareas, selects, and switches.
- Internal frontend design-system documentation and visual-smoke screenshot capture for options/sidepanel light, dark, and long-locale checks.
- Selection button overlay that captures selected text and delivers it to the side panel chat via the background port.
- Composer context preview showing selected text before sending.
- `src/i18n/resources.ts` is now build-generated from `src/locales/` by `tools/generate-i18n-resources.ts`. It is `.gitignored` and regenerated by `pnpm prepare` (so a fresh install produces it) and by `pnpm dev`/`build`/`package` (which chain `pnpm generate:resources &&` first).
- `.husky/pre-push` running the full `pnpm test:run`; `pre-commit` no longer runs the full suite, only `test:related` via lint-staged. Commits got faster, the safety net moves to push.

### Changed

- Embedding test tools split into two standalone `SettingsCard` components (`EmbeddingTestGeneration`, `EmbeddingTestSearch`) with `modelExists` guard internalized.
- Fixed uneven card gap in embedding settings by removing stray spacer text nodes.
- Bumped package version to `0.7.0`.
- Chrome Web Store locale metadata is now generated from `src/locales/<lang>/translation.json` extension blocks, making `src/locales` the single source of truth for app translations and extension package localization.
- Newly synced locale keys now have localized copy across supported languages instead of English fallback text.
- Migrated high-churn settings surfaces to shared layout/settings primitives, including model parameters, context settings, RAG retrieval controls, text splitting, embedding search/limits/generation, storage stats, database management, and search empty states.
- Moved control-density sizing and slider cursor behavior out of global CSS fallbacks and into tokenized utilities / component-level classes.
- Removed dead code: `src/lib/rag/core/` (browser-RAG interface scaffolding never wired up), the orphan `src/stores/speech-store.ts` (live store is `src/features/chat/stores/speech-store.ts`), `src/contents/selection-button.tsx`, `src/background/migrations/rag-quality-migration.ts`, `src/components/ui/sidebar.tsx`, `src/scripts/verify-rag.ts`, `src/contents/i18n-lite.ts` (had zero importers; the live selection-button content script carries its own inline translations), and an unregistered provider stub that was never wired into the factory, default providers, or registry.
- Pruned 29 unused shadcn primitives from `src/components/ui/` and removed the corresponding npm deps (`embla-carousel-react`, `input-otp`, `react-resizable-panels`, `recharts`, `sonner`, `vaul`) — install tree drops by 39 packages.
- Removed the blanket `src/components/ui/**` lint override in `biome.json`; remaining vendored-shadcn a11y exceptions are now per-line `// 
` comments inside the offending files.
- Manifest (CSP, host permissions, web-accessible resources, gecko settings) is no longer duplicated in `package.json`; `wxt.config.ts` is the single source of truth.
- Migrations consolidated under `src/lib/migration/` (moved `embedding-dimension-migration.ts` over from `src/background/migrations/`, which is now gone).
- `MESSAGE_KEYS.OLLAMA` map trimmed to keys whose string value *actually* differs from `MESSAGE_KEYS.PROVIDER` (8 entries instead of 17). The dispatcher in `src/background/index.ts` shed the now-dead duplicate `case` arms — those compiled to the same string and were unreachable.
- Provider factory: replaced the `if/else if` chain that picked OpenAI-compatible subclasses with a `Record<ProviderId, ProviderConstructor>` lookup; collapsed `getProvider` and `getProviderWithConfig` to share one `instantiate(config)` helper.
- TypeScript target bumped to ES2022; surfaced a real latent class-field initialization bug in 5 OpenAI-compatible provider subclasses (`override capabilities = { ...this.capabilities, ... }` read the child's uninitialized slot under `useDefineForClassFields`). Each capability merge moved into the subclass constructor.
- `src/types/index.ts` (568 lines) split into six domain files (`chat`, `model`, `messaging`, `errors`, `content-extraction`, `ui-state`); `index.ts` is now a re-export barrel so the 98 existing `@/types` importers keep working.

### Removed

- `*.tsx`, `types.ts`, `index.ts` from `vitest.config.ts` coverage `exclude`. Coverage reports were hiding every UI component, type file, and barrel. They now reflect reality.

### Docs

- AGENTS.md, README, and CHANGELOG synced to reflect the actual repo layout and provider list.

## [0.6.5] - 2026-05-20

### Added

- Settings deep-links so other surfaces can open the options page at a specific section.
- Grounding mode plus configurable per-conversation context limits.
- Tab-content extraction wired into chat context.
- Tab-extraction inspector for debugging page content capture.
- Cross-browser verification automation (`pnpm verify:browser-smoke`, `pnpm verify:browser-automation`) covering CSP, manifest permissions, and an optional Ollama connectivity check.

### Changed

- Migrated shadcn primitives to the `base-mira` preset on Tailwind v4 across sidepanel and options for consistent design tokens.
- Trimmed unused dependencies as part of the shadcn preset migration.
- Standardized status styling and replaced ad-hoc emoji status indicators with shared status components.
- Aligned options and sidepanel UI on shared shadcn preset tokens.
- Expanded extension CSP to allow remote provider endpoints and added in-UI connection-troubleshooting hints.
- Hardened streaming-message updates against partial-state races.
- Extracted-tab content viewer is now a scrollable modal; extracted HTML is sanitized before display.

### Fixed

- Chat-stream now handles unexpected runtime-port disconnects without leaving the UI in a stuck loading state.
- Slider behavior and several lint violations introduced during the shadcn migration.
- i18n strings added for the extracted-tab context popup and the context-settings screen.

## [0.6.2] - 2026-04-05

### Added

- Multi-provider model support with explicit provider capabilities and routing for Ollama, LM Studio, llama.cpp, and additional providers (vLLM, LocalAI, KoboldCPP).
- Full backup/export and restore flows with manifest versioning, partial failure reporting, and ZIP-based data migration.
- Enhanced RAG pipeline features: hybrid search, reranking, quality filtering, feedback blending, recency boosting, and memory-aware retrieval.
- Embedding health and rebuild tooling, including progress feedback, dimension health checks, and model status indicators.
- Search UI enhancements with scoped tabs, result grouping, and dedicated search components.
- Print/PDF export entrypoint and improved export flows.
- Expanded i18n coverage across settings, prompts, feedback, and embedding/RAG controls.
- New welcome screen layout with modular hero/status/features components and refreshed onboarding.

### Changed

- Embedding strategy and storage now track provider/model metadata, support provider-aware fallbacks, and filter search results by embedding model/provider/dimension.
- Model selection and provider settings refactored with SelectedModelRef, provider migrations, and capability-aware UI.
- Chat UI and input UX refined (message bubbles, toolbar, scroll behavior, loading states, and context menus).
- File upload and extraction pipeline simplified for local PDF/DOCX processing.
- UI system migrated/refined with updated shadcn/base components, Tailwind v4 upgrades, and layout/styling polish.
- Settings layout reorganized with better navigation, more granular controls, and migration tooling.
- Storage migrations updated (provider mappings, embeddings, feedback) with clearer diagnostics and safer defaults.

### Fixed

- Embedding model detection, download, and fallback flows with improved status checks and timeouts.
- RAG pipeline edge cases (full mode, empty results) and search ranking inconsistencies.
- Context menu and background handler stability issues.
- Chat streaming jitter, scroll flicker, and race conditions around message updates.
- Tests updated for new provider and embedding metadata.

## [0.6.0] - 2026-02-08

### Added

- Multi-provider support with routing and provider settings (Ollama, LM Studio, llama.cpp).
- Internationalization for provider settings and related UI text.
- RAG enhancements: hybrid search, reranking, quality filtering, async retrieval, and sources UX.
- File attachment viewer in chat.
- Multi-browser build targets via WXT for Chrome MV3 and Firefox MV2.

### Changed

- Settings page layout with sidebar navigation, standardized form fields, and improved UI consistency.
- Embedding strategy updates with provider-aware embeddings and enforced fallbacks.
- Model management cleanup, including removal of model pull and embedding download UI.
- Chat streaming and handler refactors for improved behavior and clarity.
- Provider display tweaks (full version labels, model name truncation cleanup).

### Fixed

- Embedding model name normalization and more robust model checks.
- Legacy Ollama base URL synchronization for provider detection.
- Branch navigation logic in chat message footer.
- Minor i18n text cleanup and translation updates.

### Documentation

- Comprehensive docs refresh for v0.6.0, including RAG and WXT migration updates.

[Unreleased]: https://github.com/Shishir435/ollama-client/compare/0.13.3...HEAD
[0.13.3]: https://github.com/Shishir435/ollama-client/compare/0.13.2...0.13.3
[0.13.2]: https://github.com/Shishir435/ollama-client/compare/0.13.1...0.13.2
[0.13.1]: https://github.com/Shishir435/ollama-client/compare/0.13.0...0.13.1
[0.13.0]: https://github.com/Shishir435/ollama-client/compare/0.12.8...0.13.0
[0.12.8]: https://github.com/Shishir435/ollama-client/compare/0.12.7...0.12.8
[0.12.7]: https://github.com/Shishir435/ollama-client/compare/0.12.6...0.12.7
[0.12.6]: https://github.com/Shishir435/ollama-client/compare/0.12.5...0.12.6
[0.12.5]: https://github.com/Shishir435/ollama-client/compare/0.12.4...0.12.5
[0.12.4]: https://github.com/Shishir435/ollama-client/compare/0.12.3...0.12.4
[0.12.3]: https://github.com/Shishir435/ollama-client/compare/0.11.27...0.12.3
[0.11.27]: https://github.com/Shishir435/ollama-client/compare/v0.10.3...0.11.27
[0.10.3]: https://github.com/Shishir435/ollama-client/compare/v0.10.2...v0.10.3
[0.10.2]: https://github.com/Shishir435/ollama-client/compare/v0.10.1...v0.10.2
[0.10.1]: https://github.com/Shishir435/ollama-client/compare/v0.8.0...v0.10.1
[0.8.0]: https://github.com/Shishir435/ollama-client/compare/v0.7.3...v0.8.0
[0.7.3]: https://github.com/Shishir435/ollama-client/compare/v0.7.2...v0.7.3
[0.7.2]: https://github.com/Shishir435/ollama-client/compare/v0.7.1...v0.7.2
[0.7.1]: https://github.com/Shishir435/ollama-client/compare/v0.7.0...v0.7.1
[0.7.0]: https://github.com/Shishir435/ollama-client/compare/v0.6.5...v0.7.0
[0.6.5]: https://github.com/Shishir435/ollama-client/compare/v0.6.2...v0.6.5
[0.6.2]: https://github.com/Shishir435/ollama-client/compare/v0.6.0...v0.6.2
[0.6.0]: https://github.com/Shishir435/ollama-client/releases/tag/v0.6.0

---

# Keyboard Shortcuts

Source: https://www.ollamaclient.in/about/keyboard-shortcuts/
Markdown: https://www.ollamaclient.in/about/keyboard-shortcuts.md
Description: Default keyboard shortcuts for Ollama Client.

All shortcuts are customizable in Settings → Shortcuts. Defaults are listed below.

_Rendered component: KeyboardShortcuts._

## Notes

- `Mod` refers to `Ctrl` on Windows/Linux and `Cmd` on macOS.
- Shortcuts are persisted via `chrome.storage.sync` and synced across devices.
- Conflicting shortcuts are flagged in the settings UI and must be resolved before saving.

