mirror of
https://github.com/ggozad/oterm.git
synced 2026-10-22 15:11:26 +02:00
1 line
No EOL
33 KiB
JSON
1 line
No EOL
33 KiB
JSON
{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"],"fields":{"title":{"boost":1000.0},"text":{"boost":1.0},"tags":{"boost":1000000.0}}},"docs":[{"location":"","title":"oterm","text":"<p>the terminal client for Ollama, OpenAI, Anthropic, and any pydantic-ai-supported provider.</p>"},{"location":"#features","title":"Features","text":"<ul> <li>intuitive and simple terminal UI, no need to run servers, frontends, just type <code>oterm</code> in your terminal.</li> <li>supports Linux, MacOS, and Windows and most terminal emulators.</li> <li>multiple persistent chat sessions, stored together with system prompt & parameter customizations in sqlite.</li> <li>talks to Ollama, OpenAI, Anthropic, Google (AI / Vertex), Groq, Mistral, Cohere, AWS Bedrock, DeepSeek, Cerebras, Grok, Hugging Face, and any OpenAI-compatible endpoint \u2014 local (vLLM, LM Studio, llama.cpp, \u2026) or hosted (OpenRouter, LiteLLM, \u2026).</li> <li>tools \u2014 built-in (<code>shell</code>, <code>date_time</code>, <code>think</code>), custom Python plugins via entry points, and any Model Context Protocol (MCP) server.</li> <li>allows for easy customization of the model's system prompt and parameters.</li> </ul>"},{"location":"#installation","title":"Installation","text":"<p>See the Installation section.</p>"},{"location":"#using-oterm","title":"Using oterm","text":"<p><code>oterm</code> picks up providers automatically from your environment. If Ollama is running on <code>http://127.0.0.1:11434</code> it shows up out of the box; for any other hosted provider, set the relevant API key (<code>OPENAI_API_KEY</code>, <code>ANTHROPIC_API_KEY</code>, etc.) and it appears in the provider dropdown. For other local runners (vLLM, LM Studio, llama.cpp, \u2026) or hosted OpenAI-compatible endpoints (OpenRouter, LiteLLM, \u2026), add an entry to the <code>openaiCompatible</code> section of <code>config.json</code>. See Providers and API keys and the <code>openaiCompatible</code> config block.</p> <p>To point Ollama at a non-default host or disable SSL verification, see Environment variables.</p> <p>To start <code>oterm</code> simply run:</p> <pre><code>oterm\n</code></pre> <p>If you installed oterm using <code>uvx</code>, you can also start it using:</p> <pre><code>uvx oterm\n</code></pre>"},{"location":"#screenshots","title":"Screenshots","text":"<p> The splash screen animation that greets users when they start oterm.</p> <p> A view of the chat interface, showcasing the conversation between the user and the model.</p> <p> oterm supports multiple themes, allowing users to customize the appearance of the interface.</p>"},{"location":"#license","title":"License","text":"<p>This project is licensed under the MIT License.</p>"},{"location":"app_config/","title":"Configuration","text":""},{"location":"app_config/#configuration","title":"Configuration","text":"<p><code>oterm</code> is configured through a JSON file (<code>config.json</code>) and a small set of environment variables.</p>"},{"location":"app_config/#where-configjson-lives","title":"Where <code>config.json</code> lives","text":"<p>The file is stored in a directory specific to your operating system. By default:</p> <ul> <li>Linux: <code>~/.local/share/oterm</code></li> <li>macOS: <code>~/Library/Application Support/oterm</code></li> <li>Windows: <code>C:/Users/<USER>/AppData/Roaming/oterm</code></li> </ul> <p>On Linux & MacOS we honour the <code>XDG_DATA_HOME</code> environment variable; the directory becomes <code>${XDG_DATA_HOME}/oterm</code>. Override the location entirely by setting <code>OTERM_DATA_DIR</code>.</p> <p>If in doubt, run <code>oterm --data-dir</code> (or <code>uvx oterm --data-dir</code>) to print the resolved location.</p>"},{"location":"app_config/#configjson-at-a-glance","title":"<code>config.json</code> at a glance","text":"<p>A complete example showing every supported key:</p> <pre><code>{\n \"splash-screen\": true,\n \"theme\": \"textual-dark\",\n \"keymap\": {\n \"next.chat\": \"ctrl+tab\",\n \"prev.chat\": \"ctrl+shift+tab\",\n \"new.chat\": \"ctrl+n\",\n \"show.logs\": \"ctrl+l\",\n \"quit\": \"ctrl+q\",\n \"newline\": \"shift+enter\",\n \"add.image\": \"ctrl+i\"\n },\n \"openaiCompatible\": {\n \"vllm\": {\n \"base_url\": \"http://localhost:8000/v1\"\n },\n \"openrouter\": {\n \"base_url\": \"https://openrouter.ai/api/v1\",\n \"api_key\": \"${OPENROUTER_API_KEY}\"\n }\n },\n \"mcpServers\": {\n \"everything\": {\n \"command\": \"npx\",\n \"args\": [\"-y\", \"@modelcontextprotocol/server-everything\"]\n }\n }\n}\n</code></pre> <p>Each key is optional; the sections below cover them in turn. For <code>mcpServers</code>, see the full reference in Model Context Protocol.</p>"},{"location":"app_config/#splash-screen-and-theme","title":"<code>splash-screen</code> and <code>theme</code>","text":"<ul> <li><code>splash-screen</code> (boolean, default <code>true</code>) \u2014 whether the splash screen plays on startup.</li> <li><code>theme</code> (string, default <code>\"textual-dark\"</code>) \u2014 the active theme. <code>oterm</code> rewrites this whenever you switch themes from the command palette, so you generally don't need to set it by hand.</li> </ul>"},{"location":"app_config/#keymap-customizing-key-bindings","title":"<code>keymap</code> \u2014 customizing key bindings","text":"<p>Sane defaults are provided, but terminal emulators and shells will sometimes intercept them. Override any of the bindings below by setting the matching key in the <code>keymap</code> block:</p> ID Default Action <code>next.chat</code> <code>ctrl+tab</code> Switch to the next chat tab. <code>prev.chat</code> <code>ctrl+shift+tab</code> Switch to the previous chat tab. <code>new.chat</code> <code>ctrl+n</code> Open the new-chat dialog. <code>show.logs</code> <code>ctrl+l</code> Open the log viewer. <code>quit</code> <code>ctrl+q</code> Quit <code>oterm</code>. <code>newline</code> <code>shift+enter</code> Insert a newline in the prompt. <code>ctrl+m</code> is also accepted as a fallback for terminals that can't distinguish <code>shift+enter</code> from <code>enter</code>, and is not configurable. <code>add.image</code> <code>ctrl+i</code> Attach an image to the next message."},{"location":"app_config/#openaicompatible-custom-openai-compatible-endpoints","title":"<code>openaiCompatible</code> \u2014 custom OpenAI-compatible endpoints","text":"<p>Connect to any OpenAI API-compatible service \u2014 local runners (vLLM, LM Studio, llama.cpp) or hosted aggregators (OpenRouter, LiteLLM) \u2014 by adding named endpoints under <code>openaiCompatible</code>:</p> <pre><code>{\n \"openaiCompatible\": {\n \"vllm\": {\n \"base_url\": \"http://localhost:8000/v1\"\n },\n \"openrouter\": {\n \"base_url\": \"https://openrouter.ai/api/v1\",\n \"api_key\": \"${OPENROUTER_API_KEY}\"\n }\n }\n}\n</code></pre> <p>Each entry takes:</p> <ul> <li><code>base_url</code> (required) \u2014 the OpenAI-compatible API base URL.</li> <li><code>api_key</code> (optional) \u2014 an API key. Reference an environment variable with <code>${VAR}</code> (or <code>${VAR:-default}</code> to fall back when unset), or pass a literal string. Omit for local endpoints that don't require authentication.</li> </ul> <p>When configured, an OpenAI Compatible provider appears in the provider dropdown. Select it, choose your endpoint, and type the model name. If the endpoint exposes <code>/v1/models</code>, suggestions appear as you type.</p>"},{"location":"app_config/#providers-and-api-keys","title":"Providers and API keys","text":"<p><code>oterm</code> discovers providers from your environment at startup. A provider appears in the new-chat dropdown only when its required environment variables are set. <code>.env</code> files in the working directory are loaded automatically.</p> Provider Provider ID Required env var(s) Ollama <code>ollama</code> none for local; <code>OLLAMA_API_KEY</code> for <code>ollama.com</code> cloud models. Endpoint via <code>OLLAMA_HOST</code> / <code>OLLAMA_URL</code>. OpenAI <code>openai</code> <code>OPENAI_API_KEY</code> OpenAI Responses <code>openai-responses</code> <code>OPENAI_API_KEY</code> Anthropic <code>anthropic</code> <code>ANTHROPIC_API_KEY</code> Google AI <code>google-gla</code> <code>GOOGLE_API_KEY</code> Google Vertex AI <code>google-vertex</code> <code>GOOGLE_APPLICATION_CREDENTIALS</code> Groq <code>groq</code> <code>GROQ_API_KEY</code> Mistral <code>mistral</code> <code>MISTRAL_API_KEY</code> Cohere <code>cohere</code> <code>COHERE_API_KEY</code> AWS Bedrock <code>bedrock</code> <code>AWS_ACCESS_KEY_ID</code>, <code>AWS_SECRET_ACCESS_KEY</code> DeepSeek <code>deepseek</code> <code>DEEPSEEK_API_KEY</code> Grok <code>grok</code> <code>GROK_API_KEY</code> Cerebras <code>cerebras</code> <code>CEREBRAS_API_KEY</code> Hugging Face <code>huggingface</code> <code>HF_TOKEN</code> <p>The <code>openai-responses</code> provider routes through OpenAI's Responses API and enables image generation as a builtin tool \u2014 pick a Responses-compatible model (e.g. <code>gpt-5.4</code>) and ask for an image in the prompt. Returned images render inline in the chat; click one to save it to <code>$OTERM_DATA_DIR/downloads/</code>.</p> <p>For any other backend with an OpenAI-compatible API, see the <code>openaiCompatible</code> config block above.</p>"},{"location":"app_config/#environment-variables","title":"Environment variables","text":"Variable Default Purpose <code>OTERM_DATA_DIR</code> OS-specific (above) Directory for <code>config.json</code> and <code>store.db</code>. <code>OTERM_VERIFY_SSL</code> <code>True</code> Set to <code>False</code> to disable SSL verification when talking to Ollama. <code>OLLAMA_HOST</code> <code>127.0.0.1:11434</code> Ollama host/port. Used to derive <code>OLLAMA_URL</code> when it isn't set. <code>OLLAMA_URL</code> from <code>OLLAMA_HOST</code> Full Ollama base URL (e.g. <code>https://ollama.example.com</code>). <code>OLLAMA_API_KEY</code> unset Bearer token for <code>ollama.com</code> cloud models. Local Ollama doesn't need it. <p>Provider-specific API keys (<code>OPENAI_API_KEY</code>, <code>ANTHROPIC_API_KEY</code>, \u2026) are listed in the provider table above.</p>"},{"location":"app_config/#chat-storage","title":"Chat storage","text":"<p>All chat sessions are stored locally in a sqlite database under <code>OTERM_DATA_DIR</code>. Run <code>oterm --db</code> to print its path.</p>"},{"location":"commands/","title":"Commands & shortcuts","text":""},{"location":"commands/#commands","title":"Commands","text":"<p>By pressing ^ Ctrl+p you can access the command palette from where you can perform most of the chat actions. The following commands are available:</p> <ul> <li><code>New chat</code> - create a new chat session</li> <li><code>Edit chat parameters</code> - edit the current chat session (change system prompt, tools, parameters, or thinking)</li> <li><code>Rename chat</code> - rename the current chat session</li> <li><code>Export chat</code> - export the current chat session as markdown</li> <li><code>Delete chat</code> - delete the current chat session</li> <li><code>Clear chat</code> - clear the chat history, preserving the chat configuration (provider, model, system prompt, tools, parameters, and thinking)</li> <li><code>Regenerate last message</code> - regenerates the last assistant message. Useful if you want to change the system prompt or parameters, or just try again.</li> <li><code>Prompt history</code> - browse previously sent prompts in the current chat and re-use one.</li> <li><code>Show logs</code> - shows the logs of the current oterm session.</li> </ul> <p>The palette also surfaces Textual's built-in commands (<code>Theme</code>, <code>Quit</code>, <code>Keys</code>, <code>Screenshot</code>, <code>Maximize</code>/<code>Minimize</code>).</p>"},{"location":"commands/#keyboard-shortcuts","title":"Keyboard shortcuts","text":"<p>The following keyboard shortcuts are supported:</p> <ul> <li> <p>^ Ctrl+q - quit</p> </li> <li> <p>Enter - send the message</p> </li> <li>Shift+Enter or ^ Ctrl+m - insert a newline; the prompt grows to fit (up to 10 lines)</li> <li>^ Ctrl+i - select an image to include with the next message</li> <li>\u2191/\u2193 (while messages are focused) - navigate through the messages</li> <li> <p>^ Ctrl+l - show logs</p> </li> <li> <p>^ Ctrl+n - open a new chat</p> </li> <li> <p>^ Ctrl+Tab - open the next chat</p> </li> <li>^ Ctrl+Shift+Tab - open the previous chat</li> </ul> <p>The prompt is always a multi-line input that auto-grows as you type or paste; long lines wrap. To recall a previously sent prompt, open <code>Prompt history</code> from the command palette (^ Ctrl+p).</p> <p>While the model is inferring the next message, you can press Esc to cancel the inference.</p> <p>Note</p> <p>If the key bindings clash with your terminal, it is possible to change them by editing the configuration file. See Configuration.</p>"},{"location":"commands/#copy-paste","title":"Copy / Paste","text":"<p>It is difficult to properly support copy/paste in terminal applications. You can copy blocks to your clipboard as such:</p> <ul> <li>clicking a message will copy it to the clipboard.</li> <li>clicking a code block will only copy the code block to the clipboard.</li> </ul> <p>For most terminals there exists a key modifier you can use to click and drag to manually select text. For example: * <code>iTerm</code> Option key. * <code>Gnome Terminal</code> Shift key. * <code>Windows Terminal</code> Shift key.</p> <p> The image selection interface.</p> <p> Images returned by the model are rendered inline in the chat. Click an image to save it to disk.</p>"},{"location":"installation/","title":"Installation","text":""},{"location":"installation/#installation","title":"Installation","text":"<p>Note</p> <p><code>oterm</code> works with multiple LLM providers \u2014 local and hosted. For local models, point it at Ollama, vLLM, LM Studio, llama.cpp, or any OpenAI-compatible runner. For hosted providers (OpenAI, Anthropic, Groq, \u2026), set the relevant API key. See Providers and API keys and the <code>openaiCompatible</code> config block.</p> <p>Using <code>uvx</code>:</p> <pre><code>uvx oterm\n</code></pre> <p>Using <code>brew</code> for MacOS:</p> <pre><code>brew install oterm\n</code></pre> <p>Note</p> <p>Since version <code>0.13.1</code>, <code>oterm</code> is in the official <code>homebrew/core</code> repository. If you have installed <code>oterm</code> by tapping <code>ggozad/formulas</code> you can now remove the tap and reinstall <code>oterm</code>.</p> <p>Using <code>yay</code> (or any AUR helper) for Arch Linux, thanks goes to Daniel Chesters for maintaining the package:</p> <pre><code>yay -S oterm\n</code></pre> <p>Using <code>nix-env</code> on NixOs, thanks goes to Ga\u00ebl James for maintaining the package:</p> <pre><code>nix-env -iA nixpkgs.oterm\n</code></pre> <p>Using <code>pip</code>:</p> <pre><code>pip install oterm\n</code></pre> <p>Using <code>pkg</code> for FreeBSD, thanks goes to Nicola Vitale for maintaining the package:</p> <pre><code>pkg install misc/py-oterm\n</code></pre> <p>Using <code>x-cmd</code>:</p> <pre><code>x install oterm\n</code></pre>"},{"location":"installation/#updating-oterm","title":"Updating oterm","text":"<p>To update oterm to the latest version, you can use the same method you used for installation:</p> <p>Using <code>uvx</code>:</p> <pre><code>uvx oterm@latest\n</code></pre> <p>Using <code>brew</code> for MacOS:</p> <p><pre><code>brew upgrade oterm\n</code></pre> Using 'yay' (or any AUR helper) for Arch Linux:</p> <p><pre><code>yay -Syu oterm\n</code></pre> Using <code>pip</code>:</p> <pre><code>pip install --upgrade oterm\n</code></pre> <p>Using <code>pkg</code> for FreeBSD:</p> <pre><code>pkg upgrade misc/py-oterm\n</code></pre>"},{"location":"parameters/","title":"Chat parameters","text":"<p>When creating a new chat, you may select the provider and model you want and customize the following:</p> <ul> <li><code>system</code> instruction prompt</li> <li><code>tools</code> used. See Tools for more information on how to make tools available.</li> <li>chat <code>parameters</code> passed to the model: <code>temperature</code>, <code>top_p</code>, and <code>max_tokens</code>.</li> <li>enable <code>thinking</code> for models that support it.</li> </ul> <p>Note</p> <p>When <code>thinking</code> is enabled you will observe the model thinking while generating its response. The thinking process is not persisted in the database in order to save context, so you will not see it on later sessions.</p> <p>You can also \"edit\" an existing chat to change the system prompt, parameters, tools, or thinking. Note that the provider and model cannot be changed once the chat has started.</p> <p> The new-chat screen, where you pick the provider and model and customize the system prompt, tools, parameters, and thinking.</p>"},{"location":"rag_example/","title":"RAG with haiku.rag","text":"<p>Transform oterm into a powerful RAG (Retrieval-Augmented Generation) system by integrating with haiku.rag (from <code>oterm</code>'s author), a SQLite-based RAG library that works seamlessly with oterm through MCP.</p>"},{"location":"rag_example/#what-is-haikurag","title":"What is haiku.rag?","text":"<p>haiku.rag is a comprehensive RAG library that:</p> <ul> <li>Uses only SQLite (no external vector databases needed)</li> <li>Supports 40+ file formats (PDF, DOCX, HTML, Markdown, code files, URLs)</li> <li>Provides hybrid search (semantic + full-text) with Reciprocal Rank Fusion</li> <li>Works with multiple embedding providers (Ollama, OpenAI, VoyageAI)</li> <li>Offers built-in reranking and question-answering capabilities</li> <li>Exposes functionality through MCP tools for seamless AI assistant integration</li> </ul>"},{"location":"rag_example/#configuration","title":"Configuration","text":"<p>Add the haiku-rag MCP server to your oterm configuration. Edit your <code>config.json</code> file (run <code>oterm --data-dir</code> to find its location) and add:</p> <pre><code>{\n \"mcpServers\": {\n \"haiku-rag\": {\n \"command\": \"uvx\",\n \"args\": [\n \"haiku-rag\",\n \"serve\",\n \"--stdio\",\n \"--db\",\n \"/path/to/your/rag.db\"\n ]\n }\n }\n}\n</code></pre> <p>Replace <code>/path/to/your/rag.db</code> with the path where you want to store your RAG database.</p>"},{"location":"rag_example/#available-rag-tools","title":"Available RAG Tools","text":"<p>Once configured, oterm will have access to powerful RAG capabilities through these MCP tools:</p> <ul> <li>Add documents: Upload text, files, or URLs to your knowledge base</li> <li>List documents: View all documents in your RAG database</li> <li>Delete documents: Remove documents from your knowledge base</li> <li>Update documents: Modify existing documents</li> <li>Search documents: Performs hybrid search on your knowledge base</li> </ul>"},{"location":"rag_example/#usage-examples","title":"Usage Examples","text":""},{"location":"rag_example/#1-building-a-personal-knowledge-base","title":"1. Building a Personal Knowledge Base","text":"<p>Start a new chat in oterm and use the RAG tools to build your knowledge base:</p> <p><code>Add this document to my knowledge base: \"Machine Learning is a subset of artificial intelligence that focuses on algorithms that can learn from data...\"</code></p>"},{"location":"rag_example/#2-adding-files","title":"2. Adding Files","text":"<p>You can add various file types:</p> <p><code>Please add the PDF file at /Users/me/Documents/research_paper.pdf to my RAG database</code></p>"},{"location":"rag_example/#3-adding-web-content","title":"3. Adding Web Content","text":"<p>Add content from URLs:</p> <p><code>Add the content from https://example.com/article to my knowledge base</code></p>"},{"location":"rag_example/#4-searching-your-knowledge-base","title":"4. Searching Your Knowledge Base","text":"<p>Perform semantic searches:</p> <p><code>Search my knowledge base for information about \"neural networks\"</code></p>"},{"location":"rag_example/#5-question-answering","title":"5. Question Answering","text":"<p>Ask questions about your documents:</p> <p><code>Based on my knowledge base, what are the main differences between supervised and unsupervised learning?</code></p>"},{"location":"rag_example/#advanced-configuration","title":"Advanced Configuration","text":""},{"location":"rag_example/#custom-embedding-providers","title":"Custom Embedding Providers","text":"<p>Configure haiku.rag to use different embedding providers, rerankers, models by setting environment variables. See <code>haiku.rag</code> documentation</p> <pre><code>{\n \"mcpServers\": {\n \"haiku-rag\": {\n \"command\": \"uvx\",\n \"args\": [\n \"haiku-rag\",\n \"serve\",\n \"--stdio\",\n \"--db\",\n \"/path/to/rag.db\"\n ],\n \"env\": {\n \"EMBEDDINGS_PROVIDER\": \"ollama\",\n \"EMBEDDINGS_MODEL\": \"nomic-embed-text\"\n }\n }\n }\n}\n</code></pre>"},{"location":"rag_example/#further-reading","title":"Further Reading","text":"<ul> <li>haiku.rag Documentation</li> <li>haiku.rag GitHub Repository</li> </ul>"},{"location":"rag_example/#example-use-cases","title":"Example Use Cases","text":""},{"location":"rag_example/#research-assistant","title":"Research Assistant","text":"<p>Build a personal research database by adding academic papers, articles, and notes. Ask questions across your entire research collection.</p>"},{"location":"rag_example/#documentation-helper","title":"Documentation Helper","text":"<p>Index your project's documentation, code comments, and README files. Get instant answers about your codebase.</p>"},{"location":"rag_example/#learning-companion","title":"Learning Companion","text":"<p>Add course materials, textbooks, and learning resources. Create a personalized tutor that can answer questions about your study materials.</p>"},{"location":"development/","title":"Development & Debugging","text":""},{"location":"development/#inspecting-logs","title":"Inspecting logs","text":"<p>You can inspect basic logs from oterm by invoking the log viewer with ^ Ctrl+l or by using the command palette. This is particularly useful if you want to debug tool calling.</p> <p> oterm's internal log viewer showing the Brave Search MCP tool in action.</p>"},{"location":"development/#setup-for-development","title":"Setup for development","text":"<ul> <li>Create a virtual environment <pre><code>uv venv\n</code></pre></li> <li> <p>Activate the virtual environment <pre><code>source .venv/bin/activate\n# or on Windows\n.venv\\Scripts\\activate\n</code></pre></p> </li> <li> <p>Install oterm <pre><code>uv pip install oterm\n</code></pre> or checkout the repository and install the oterm package from source <pre><code>git clone git@github.com:ggozad/oterm.git\nuv sync\n</code></pre></p> </li> </ul>"},{"location":"development/#debugging","title":"Debugging","text":"<ul> <li> <p>In order to inspect logs from oterm, open a new terminal and run: <pre><code>source .venv/bin/activate\ntextual console -x SYSTEM -x EVENT -x WORKER -x DEBUG\n</code></pre> This will start the textual console and listen all log messages from oterm, hiding some of the textual UI messsages.</p> </li> <li> <p>You can now start oterm in debug mode: <pre><code>source .venv/bin/activate\ntextual run -c --dev oterm\n</code></pre></p> </li> </ul>"},{"location":"development/#documentation","title":"Documentation","text":"<p>oterm uses mkdocs with material to generate the documentation. To build the documentation, run: <pre><code>source .venv/bin/activate\nmkdocs serve -o\n</code></pre> This will start a local server and open the documentation pages in your default web browser.</p>"},{"location":"mcp/","title":"Model Context Protocol","text":"<p><code>oterm</code> has support for Anthropic's open-source Model Context Protocol. It connects to MCP servers and exposes their tools to whichever model you're chatting with.</p> <p>Add MCP servers under the <code>mcpServers</code> key in <code>oterm</code>'s config.json. The schema matches the convention used by Claude Desktop, Cursor, and pydantic-ai \u2014 so you can copy a config block between hosts.</p> <p>Breaking changes from earlier oterm releases</p> <p>The MCP integration was rewritten on top of pydantic-ai's MCP support. If you're upgrading, your existing <code>mcpServers</code> config likely needs the following edits:</p> <ul> <li><code>auth: { type: bearer, token: \"X\" }</code> is no longer recognised. Use <code>headers: { \"Authorization\": \"Bearer X\" }</code> instead. Old configs are silently dropped \u2014 you'll see 401s from the server until you migrate.</li> <li><code>cwd</code> is no longer recognised. Use an absolute path in <code>command</code> (or pass the working directory via <code>args</code>).</li> <li><code>ws://</code> / <code>wss://</code> transports are no longer supported. Use HTTP transport instead.</li> <li>MCP prompts are gone \u2014 the \"Use MCP prompt\" command, the modal, and the prompt config in test fixtures are all removed.</li> <li>Stdio subprocess env is no longer inherited from the parent shell. Declare every env var you need explicitly under <code>env</code>. Use <code>${VAR}</code> substitution to pull values from the parent environment without committing secrets \u2014 see Environment variables below.</li> </ul>"},{"location":"mcp/#tools","title":"Tools","text":"<p>MCP tools appear in oterm's tool selector and can be enabled per chat.</p> <p>Note</p> <p>Not all models support tools. For models that don't, the tool selection is disabled.</p> <p>Smaller LLMs are often less capable with tools than larger ones. If you have issues, try reducing the number of tools attached to a chat, increasing the context size, or using a larger LLM.</p>"},{"location":"mcp/#transports","title":"Transports","text":""},{"location":"mcp/#stdio-transport","title":"<code>stdio</code> transport","text":"<p>For local MCP servers. Accepts <code>command</code>, <code>args</code>, and <code>env</code>. For the git MCP server:</p> <pre><code>{\n \"mcpServers\": {\n \"git\": {\n \"command\": \"docker\",\n \"args\": [\n \"run\",\n \"--rm\",\n \"-i\",\n \"--mount\",\n \"type=bind,src=/Users/ggozad/dev/open-source/oterm,dst=/oterm\",\n \"mcp/git\"\n ]\n }\n }\n}\n</code></pre>"},{"location":"mcp/#streamable-http-transport","title":"<code>Streamable HTTP</code> transport","text":"<p>For remote MCP servers over HTTP. The <code>url</code> must start with <code>http://</code> or <code>https://</code>. URLs ending in <code>/sse</code> are treated as SSE; everything else is streamable HTTP.</p> <pre><code>{\n \"mcpServers\": {\n \"my_mcp\": {\n \"url\": \"http://remote:port/path\"\n }\n }\n}\n</code></pre>"},{"location":"mcp/#http-headers-auth","title":"HTTP headers (auth)","text":"<p>Use the <code>headers</code> dict to attach arbitrary HTTP headers \u2014 including <code>Authorization</code> for bearer-token auth:</p> <pre><code>{\n \"mcpServers\": {\n \"my_mcp\": {\n \"url\": \"http://remote:port/path\",\n \"headers\": {\n \"Authorization\": \"Bearer XXX\"\n }\n }\n }\n}\n</code></pre>"},{"location":"mcp/#environment-variables","title":"Environment variables","text":"<p>For security, <code>stdio</code> MCP subprocesses do not inherit <code>oterm</code>'s parent environment. That keeps credentials like <code>OPENAI_API_KEY</code> or <code>AWS_SECRET_ACCESS_KEY</code> out of third-party MCP server processes unless you explicitly share them.</p> <p>Declare env vars in the <code>env</code> dict of each server. Any string value (in <code>env</code>, <code>command</code>, <code>args</code>, <code>url</code>, or <code>headers</code>) can reference the parent environment via <code>${VAR}</code> (required) or <code>${VAR:-default}</code> (optional with fallback):</p> <pre><code>{\n \"mcpServers\": {\n \"github\": {\n \"command\": \"${HOME}/.local/bin/mcp-github\",\n \"args\": [\"--repo\", \"${REPO:-ggozad/oterm}\"],\n \"env\": {\n \"GITHUB_TOKEN\": \"${GITHUB_TOKEN}\"\n }\n }\n }\n}\n</code></pre> <p>If a referenced variable is not set and has no default, server setup fails with an error naming the missing variable.</p>"},{"location":"mcp/#sampling","title":"Sampling","text":"<p>MCP sampling is not currently supported \u2014 <code>oterm</code> advertises sampling as disabled to every server, so any sampling request is rejected by the protocol rather than crashing the chat.</p>"},{"location":"oracle/","title":"Oracle \u2014 example oterm tool plugin","text":"<p>A minimal example of how to ship a Python package whose function is auto-discovered as an oterm tool.</p> <p>The tool itself is intentionally trivial \u2014 <code>oracle(question)</code> always answers <code>\"oterm\"</code> \u2014 so you can focus on the packaging:</p> <ul> <li><code>src/oracle/tool.py</code> defines the function. Its name, docstring, and type annotations are what oterm passes to the model.</li> <li><code>pyproject.toml</code> registers the function under the <code>oterm.tools</code> entry-point group:</li> </ul> <pre><code>[project.entry-points.\"oterm.tools\"]\noracle = \"oracle.tool:oracle\"\n</code></pre> <p>Install it into the same environment as oterm:</p> <pre><code>cd docs/oracle\nuv pip install . # or: pip install .\n</code></pre> <p>After restart, the <code>oracle</code> tool appears in the new-chat tool selector.</p> <p>See the tools guide for the full walkthrough.</p>"},{"location":"tools/","title":"Tools","text":"<p><code>oterm</code> supports integration with tools. Tools are special \"functions\" that can provide external information to the LLM model that it does not otherwise have access to.</p> <p>With tools, you can provide the model with access to the web, run shell commands, perform RAG and more.</p> <p>Use existing Model Context Protocol servers</p> <p>or</p> <p>create your own custom tools.</p>"},{"location":"tools/#custom-tools-with-oterm","title":"Custom tools with oterm","text":"<p>You can create your own custom tools and integrate them with <code>oterm</code> using Python entry points.</p>"},{"location":"tools/#create-a-python-package","title":"Create a python package","text":"<p>Create a python package that exports a callable function. The function's name, docstring, and type annotations are used to generate the tool definition for the model.</p> <p>Here is an example of a simple tool that implements an Oracle:</p> <pre><code>def oracle(question: str) -> str:\n \"\"\"Function to return the Oracle's answer to any question.\n\n Args:\n question: The question to ask.\n \"\"\"\n return \"oterm\"\n</code></pre>"},{"location":"tools/#register-the-tool-as-an-entry-point","title":"Register the tool as an entry point","text":"<p>In your package's <code>pyproject.toml</code>, register the tool under the <code>oterm.tools</code> entry-point group:</p> <pre><code>[project.entry-points.\"oterm.tools\"]\noracle = \"oracle.tool:oracle\"\n</code></pre>"},{"location":"tools/#install-and-use","title":"Install and use","text":"<p>Install the package in the same environment where <code>oterm</code> is installed:</p> <pre><code>cd oracle\nuv pip install . # or pip install .\n</code></pre> <p>That's it! <code>oterm</code> discovers all tools registered under the <code>oterm.tools</code> entry-point group at startup. You can now select the tool when creating or editing a chat.</p>"},{"location":"tools/#built-in-tools","title":"Built-in tools","text":"<p>The following tools are built-in to <code>oterm</code> and available by default:</p> <ul> <li><code>think</code> - provides the model with a way to think about a question before answering it. This is useful for complex questions that require reasoning. Use it for adding a \"thinking\" step to the model's response.</li> <li><code>date_time</code> - provides the current date and time in ISO format.</li> <li><code>shell</code> - allows you to run shell commands and use the output as input to the model. Obviously this can be dangerous, so use with caution.</li> <li><code>generate_image</code> - generates an image from a text prompt using an Ollama image-generation model (e.g. <code>x/z-image-turbo</code>, <code>x/flux2-klein</code>). The default model is <code>x/z-image-turbo</code>; override it for a single call via the tool's <code>model</code> argument or globally via the <code>OTERM_OLLAMA_IMAGE_MODEL</code> environment variable. The image renders inline in the chat. Requires an Ollama server with an image-capable model installed; the host LLM (any provider) writes the prompt and calls the tool.</li> </ul>"},{"location":"tools/#tool-calls-in-the-chat","title":"Tool calls in the chat","text":"<p>When the model invokes a tool during a response, <code>oterm</code> renders the call inline as a collapsible entry between any \"thoughts\" and the response itself:</p> <pre><code>\u25b8 tool call: search_repo\n</code></pre> <p>Click the line (or its arrow) to expand it. The expanded body shows:</p> <ul> <li><code>args:</code> \u2014 the arguments the model passed to the tool. Dictionaries and JSON-encoded strings are pretty-printed with syntax highlighting; plain strings are shown verbatim and truncated if very long.</li> <li><code>result:</code> \u2014 the value the tool returned, formatted the same way. Appears once the tool has finished.</li> </ul> <p>Click again to collapse. Multiple calls within the same turn each get their own entry.</p>"}]} |