{"slug": "show-hn-mandocode-local-first-ai-coding-agent-net-and-ollama", "title": "Show HN: MandoCode – local-first AI coding agent (.NET and Ollama)", "summary": "MandoCode, a new open-source AI coding agent built on .NET and Ollama, launched today as a local-first alternative to cloud-based assistants. The tool, which requires no API keys and runs entirely in the terminal, can read, write, search, and plan across entire codebases while supporting any file type. Its release addresses developer concerns about privacy and cost by offering a fully local AI coding experience that can optionally connect to cloud models for more powerful capabilities.", "body_md": "**Your AI coding assistant — run locally or in the cloud with Ollama.**\n\nNo API keys required. Just you and your code.\n\nMandoCode is an AI coding assistant built on [RazorConsole](https://github.com/RazorConsole/RazorConsole), powered by [Semantic Kernel](https://github.com/microsoft/semantic-kernel) and [Ollama](https://ollama.ai). RazorConsole makes the entire terminal UI possible — Razor components, a virtual DOM, and Spectre.Console rendering all running in the console.\n\nRun locally or connect to Ollama cloud — no API keys required for anything, including web search (an optional free [Tavily](https://www.tavily.com/) key upgrades search reliability). It gives you Claude-Code-style project awareness — reading, writing, searching, planning, and web browsing across your entire codebase — without ever leaving your terminal. It understands **any file type**: C#, JavaScript, TypeScript, Python, CSS, HTML, JSON, config files, and more.\n\n**.NET 8 SDK**—[dotnet.microsoft.com/download/dotnet/8.0](https://dotnet.microsoft.com/en-us/download/dotnet/8.0)*(SDK includes the runtime — install only the SDK)***Ollama**—[ollama.com/download](https://ollama.com/download)*(MandoCode walks you through setup on first run)*\n\n```\ndotnet tool install -g MandoCode\nmandocode\n```\n\nFirst run launches a guided wizard: it detects Ollama, offers to start it, walks you through cloud sign-in if you'd like more powerful models, and auto-pulls a sensible default. You can re-run it any time with `/setup`\n\n.\n\n```\nmandocode --doctor\n```\n\nPrints your runtime version, Ollama status, models pulled, and cloud sign-in state.\n\nUsing cloud models (Cloud model context is managed on Ollama's servers and set to the model's maximum by default — nothing on your machine affects it, including the desktop app's slider.`:cloud`\n\ntags)? Skip this section.\n\nIf you use **local models** and see responses cut off, the model \"forgetting\" earlier conversation, edits failing repeatedly on files it just wrote, or this message:\n\n⚠ Response was cut off because the model's CONTEXT WINDOW filled …\n\n…your Ollama **context window** is almost certainly too small. The context window is how much conversation + code the model can see at once — and **Ollama defaults it to ~4k tokens**, which an agentic session fills almost immediately. When it overflows, the oldest content (including the system prompt — the model's instructions!) is silently dropped.\n\n**If you use the Ollama desktop app** (the tray icon), the app's **Settings → Context length** slider controls this — and it overrides everything else, including MandoCode's config:\n\nThere's no universally right slider position — it's a trade between *how much the model can see* and *fitting in your GPU's memory* (every 8k of window costs roughly 0.5–1.5 GB of VRAM depending on the model):\n\n**Too low**(the 4k default): the symptoms above — the model's own instructions silently fall out of the window and it stops behaving.**Too high for your GPU**: the model spills into system RAM, tokens/sec craters, and turns crawl or look hung.** Starting points**:** 16k**for most GPUs,** 32k**with 8 GB+ VRAM. Only raise it if you're seeing the symptoms above; step back down a notch if generation slows badly after raising it.\n\n**If you run ollama serve yourself** (no desktop app), MandoCode handles it: it sets\n\n`OLLAMA_CONTEXT_LENGTH`\n\nfrom your `contextLength`\n\nconfig when it starts the daemon, and auto-sizes it to the hardware tier of the model you pick in `/setup`\n\nor `/model`\n\n. Tune it manually with:\n\n```\nmandocode --config set contextLength 16384\n```\n\nVerify what your daemon is actually using with `ollama ps`\n\n(look at the CONTEXT column). Run `/learn`\n\ninside MandoCode for a friendly explainer.\n\nThe context window's evil twin — and unlike the slider above, this one applies to **every model, cloud included**. If the model **announces work and then just stops** — *\"I'll create the game…\"* and the turn ends with no plan, no files, and no error — your `maxTokens`\n\nis too low. It caps a *single reply* (`NumPredict`\n\n), and reasoning models spend output tokens thinking **before** they emit a tool call, so a low cap cuts them off before they ever act.\n\nFresh installs default to 32k and never notice it. But if your config predates v0.11, or you once lowered `maxTokens`\n\nthinking it was the context window (they're different knobs — this caps what the model *says*, the context window caps what it *sees*), check it:\n\n```\nmandocode --config show                  # look at \"Max Tokens\"\nmandocode --config set maxTokens 32768\n```\n\nThe telltale sign: token tracking shows output pinned at exactly your cap, turn after turn (e.g. `2k out`\n\nevery time). Note that a running session keeps the config it loaded at startup — restart MandoCode (or use `/config set`\n\nin-app) for the change to take effect.\n\n```\ngit clone https://github.com/DevMando/MandoCode.git\ncd MandoCode\ndotnet build src/MandoCode/MandoCode.csproj\ndotnet run --project src/MandoCode/MandoCode.csproj -- /path/to/your/project\n```\n\n|\nEvery file write and delete is intercepted with a color-coded diff. You approve, deny, or redirect — nothing touches disk without your say-so.\n|\nType\n|\n|\nComplex requests are automatically broken into step-by-step plans. Review the plan, then watch each step execute with progress tracking.\n|\nThe AI can search the web and read webpages to find documentation, tutorials, or answers — no API keys needed. Optionally add a free\n|\n|\nLofi and synthwave tracks bundled right in. A waveform visualizer runs in the corner while you code. Because vibes matter.\n|\nIf Ollama isn't running, MandoCode shows setup guidance inline instead of a bare error. Use\n|\n\n| Feature | Description | |\n|---|---|---|\nAI |\nProject-aware assistant | Reads, writes, deletes, and searches your entire codebase |\nAI |\nWeb search & fetch | Web search and webpage reading — keyless via DuckDuckGo, or Tavily with a free API key |\nAI |\nMCP server support | Connect to any Model Context Protocol server (stdio or remote HTTP) — Claude-Desktop-compatible config |\nAI |\nStreaming responses | Real-time output with animated spinners |\nAI |\nTask planner | Auto-detects complex requests and breaks them into steps |\nAI |\nFallback function parsing | Handles models that output tool calls as raw JSON |\nUI |\nDiff approvals | Color-coded diffs with approve / deny / redirect |\nUI |\nMarkdown rendering | Rich terminal output — headers, tables, code blocks, quotes |\nUI |\nSyntax highlighting | C#, Python, JavaScript/TypeScript, Bash |\nUI |\nClickable file links | OSC 8 hyperlinks for file paths |\nUI |\nTerminal theme detection | Auto-adapts colors for light and dark terminals |\nUI |\nTaskbar progress | Windows Terminal integration during task execution |\nInput |\n`/` command autocomplete |\nSlash commands with dropdown navigation |\nInput |\n`@` file references |\nAttach file content to any prompt |\nInput |\n`!` shell escape |\nRun shell commands inline (`!git status` , `!ls` ) |\nInput |\n`/copy` and `/copy-code` |\nCopy responses or code blocks to clipboard |\nMusic |\nLofi + synthwave | Bundled tracks with volume, genre switching, waveform visualizer |\nConfig |\nConfiguration wizard | Guided setup with model selection and connection testing |\nConfig |\nConfig validation | Auto-clamps invalid settings to safe ranges |\nReliability |\nRetry + deduplication | Exponential backoff and duplicate call prevention |\nEducation |\n`/learn` command |\nLLM education guide with optional AI educator chat |\n\nType `/`\n\nto see the autocomplete dropdown, or `!`\n\nto run a shell command.\n\n| Command | What it does |\n|---|---|\n`/help` |\nShow commands and usage examples |\n`/setup` |\nGuided wizard — reconnect to Ollama, install/sign in, or pick a different model |\n`/model` |\nQuick switch — pick a different model (context window auto-sized for local tiers) |\n`/config` |\nAdjust settings — guided wizard |\n`/config set <key> <value>` |\nSet one setting inline without leaving the session (e.g. `/config set modelResponseTimeout 300` ); no args lists all keys + current values |\n`/retry` |\nRetry Ollama connection |\n`/learn` |\nInteractive guide to LLMs and local AI |\n`/copy` |\nCopy last AI response to clipboard |\n`/copy-code` |\nCopy code blocks from last response |\n`/command <cmd>` |\nRun a shell command |\n`/music` |\nStart playing music |\n`/music-stop` |\nStop playback |\n`/music-pause` |\nPause / resume |\n`/music-next` |\nNext track |\n`/music-vol <0-100>` |\nSet volume |\n`/music-lofi` |\nSwitch to lofi |\n`/music-synthwave` |\nSwitch to synthwave |\n`/music-list` |\nList available tracks |\n`/mcp` |\nList configured MCP servers with status and tool counts |\n`/mcp add` |\nInteractively add a new MCP server to config |\n`/mcp remove <name>` |\nRemove an MCP server from config |\n`/mcp tools <server>` |\nList tools exposed by connected MCP servers (server optional) |\n`/mcp-reload` |\nRestart all MCP servers and re-register their tools |\n`/clear` |\nClear conversation history |\n`/exit` |\nExit MandoCode |\n`!<cmd>` |\nShell escape (e.g., `!git status` ) |\n`!cd <path>` |\nChange project root directory |\n\n— first-run wizard, guided. Detects Ollama, offers to install it, walks you through cloud sign-in, picks a model with hardware-aware tiers, auto-pulls a sensible default. Use when something's broken or you're a newcomer.`/setup`\n\n— quick switch. Pick a model from your pulled list and go — local picks get a context window sized to their hardware tier automatically. Use when you just want to swap models.`/model`\n\n— adjust settings. Full configuration form covering temperature, timeouts, ignore dirs, etc. Use when you know exactly what knob you want to turn.`/config`\n\n```\nmandocode --doctor          # preflight check: .NET runtime, Ollama status, models, sign-in\nmandocode --config show     # print current config\nmandocode --config init     # create a default config file\nmandocode --config set <key> <value>   # set a single value (e.g. set model qwen3.5:9b)\nmandocode --config path     # show config file location\n```\n\nRun `mandocode --doctor`\n\nany time chat is misbehaving — exits 0 if everything's green, 1 if anything's missing, with a clear summary of what's wrong.\n\n```\n  You type a prompt\n        |\n  MandoCode adds project context (@files, system prompt)\n        |\n  Semantic Kernel sends to Ollama (local or cloud model)\n        |\n  AI responds with text + function calls\n        |\n  File operations go through diff approval\n  Web searches and fetches run directly\n        |\n  Rich markdown rendered in your terminal\n```\n\nThe AI has sandboxed access to your project through a **FileSystemPlugin** (9 functions: list files, glob search, read, write, delete files/folders, text search, path resolution) and a **WebSearchPlugin** (web search via Tavily or DuckDuckGo, webpage fetching — works without any API key). All file operations are locked to your project root — path traversal is blocked.\n\nModels with **tool/function calling** support work best with MandoCode. The first-run wizard offers exactly the models below — auto-pulls the cloud default, or lets you pick a local tier matched to your hardware.\n\n**Cloud** (no GPU required — runs on Ollama's servers, free with `ollama signin`\n\n):\n\n| Model | Notes |\n|---|---|\n`minimax-m2.7:cloud` |\nDefault — auto-pulled by `/setup` when you pick Cloud |\n\n**Local** (fully offline, runs on your hardware):\n\n| Model | Size | Hardware |\n|---|---|---|\n`qwen3.5:0.8b` |\n~1.0 GB | CPU-only / integrated GPU — fast on any laptop, light reasoning |\n`qwen3.5:2b` |\n~2.7 GB | Modern CPU or 4 GB+ GPU — quick Q&A, simple code edits |\n`qwen3.5:4b` |\n~3.4 GB | Mid-range GPU (4-6 GB VRAM) or 16 GB RAM — balanced day-to-day use |\n`qwen3.5:9b` |\n~6.6 GB | Dedicated GPU (8+ GB VRAM) — best local quality, multi-file refactors |\n\nMandoCode validates model compatibility on startup. Run `/learn`\n\nfor a detailed guide on model sizes and hardware requirements, or `/setup`\n\nto switch between tiers any time.\n\nLocated at `~/.mandocode/config.json`\n\n```\n{\n  \"ollamaEndpoint\": \"http://localhost:11434\",\n  \"modelName\": \"minimax-m2.7:cloud\",\n  \"modelPath\": null,\n  \"temperature\": 0.7,\n  \"maxTokens\": 4096,\n  \"ignoreDirectories\": [],\n  \"enableDiffApprovals\": true,\n  \"enableTaskPlanning\": true,\n  \"enableTokenTracking\": true,\n  \"enableThemeCustomization\": true,\n  \"enableFallbackFunctionParsing\": true,\n  \"functionDeduplicationWindowSeconds\": 5,\n  \"maxRetryAttempts\": 2,\n  \"music\": {\n    \"volume\": 0.5,\n    \"genre\": \"lofi\",\n    \"autoPlay\": false\n  }\n}\n```\n\n| Key | Default | Description |\n|---|---|---|\n`ollamaEndpoint` |\n`http://localhost:11434` |\nOllama server URL |\n`modelName` |\n`minimax-m2.7:cloud` |\nModel to use |\n`modelPath` |\n`null` |\nOptional path to a local GGUF model file |\n`temperature` |\n`0.7` |\nResponse creativity (0.0 = focused, 1.0 = creative) |\n`maxTokens` |\n`32768` |\nCap on a single reply (`NumPredict` ) — a runaway-generation safety ceiling, not the context window. If the model announces work then stops without acting, this is too low (see Troubleshooting) |\n`contextLength` |\n`8192` |\nContext window (`num_ctx` / KV-cache size) for local models, set via `OLLAMA_CONTEXT_LENGTH` when MandoCode starts the Ollama daemon. `0` = leave Ollama's default (~4k). Bigger window = more VRAM. Cloud models manage context server-side |\n`ignoreDirectories` |\n`[]` |\nAdditional directories to exclude from file scanning |\n`enableDiffApprovals` |\n`true` |\nShow diffs and prompt for approval before file writes/deletes |\n`enableTaskPlanning` |\n`true` |\nEnable automatic task planning for complex requests |\n`enableTokenTracking` |\n`true` |\nShow session token totals and per-response token costs |\n`enableThemeCustomization` |\n`true` |\nDetect terminal theme and apply a curated ANSI palette |\n`enableFallbackFunctionParsing` |\n`true` |\nParse function calls from text output |\n`functionDeduplicationWindowSeconds` |\n`5` |\nTime window to prevent duplicate function calls |\n`maxRetryAttempts` |\n`2` |\nMax retry attempts for transient errors |\n`music.volume` |\n`0.5` |\nMusic volume (0.0 - 1.0) |\n`music.genre` |\n`lofi` |\nDefault genre (`lofi` or `synthwave` ) |\n`music.autoPlay` |\n`false` |\nAuto-start music on launch |\n\n```\nmandocode config show              # Display current configuration\nmandocode config init              # Create default configuration file\nmandocode config set <key> <value> # Set a configuration value\nmandocode config path              # Show configuration file location\nmandocode config --help            # Show help\n```\n\n| Variable | Overrides |\n|---|---|\n`OLLAMA_ENDPOINT` |\n`ollamaEndpoint` in config |\n`OLLAMA_MODEL` |\n`modelName` in config |\n\nWhen the AI writes or deletes a file, MandoCode intercepts the operation and shows a color-coded diff before applying changes.\n\n**Red lines**— content being removed** Light blue lines**— content being added** Dim lines**— unchanged context (3 lines around each change)- Long unchanged sections are collapsed with a summary\n\n| Option | Behavior |\n|---|---|\nApprove |\nApply this change |\nApprove - Don't ask again |\nAuto-approve future changes to this file (per-file), or all files (global) |\nDeny |\nReject the change, the AI is told it was denied |\nProvide new instructions |\nRedirect the AI with custom feedback |\n\nFor **new files**, \"don't ask again\" sets a **global bypass** — all future writes and deletes are auto-approved for the session. For **existing files**, the bypass is **per-file**.\n\nEven when auto-approved, diffs are still rendered so you can follow along.\n\nFile deletions show all existing content as red removals with a deletion warning. The same approval options apply.\n\n```\nmandocode config set diffApprovals false\n```\n\nType `@`\n\nanywhere in your input (after a space or at position 0) to trigger file autocomplete. A dropdown appears showing your project files, filtered as you type.\n\n- Type your prompt and hit\n`@`\n\n— a file dropdown appears - Type a partial name to filter (e.g.,\n`Conf`\n\n) — matches narrow down - Use arrow keys to navigate,\n**Tab** or**Enter** to select - The selected path is inserted (e.g.,\n`@src/MandoCode/Models/MandoCodeConfig.cs`\n\n) - Continue typing and press\n**Enter** to submit - MandoCode reads the referenced file(s) and injects the content as context for the AI\n\n```\nexplain @src/MandoCode/Services/AIService.cs to me\nwhat does the ProcessFileReferences method do in @src/MandoCode/Components/App.razor\nrefactor @src/MandoCode/Models/LoadingMessages.cs to use fewer spinners\n```\n\nMultiple `@`\n\nreferences in one prompt are supported. Files over 10,000 characters are automatically truncated.\n\n| Key | Action |\n|---|---|\n`@` |\nOpen file dropdown |\n| Type | Filter files by name |\n| Up/Down | Navigate dropdown |\n| Tab/Enter | Insert selected file path (does not submit) |\n| Escape | Close dropdown, keep text |\n| Backspace | Re-filter, or close if you delete past `@` |\n\nMandoCode automatically detects complex requests and offers to break them into a step-by-step plan before execution.\n\nThe planner activates for requests like:\n\n`Create a REST API service with authentication and rate limiting for the user module`\n\n(12+ words with imperative verb and scope indicator)`Build an application that handles user registration and sends email confirmations`\n\n- Numbered lists with 3+ items\n- Requests over 400 characters\n\nSimple questions, short prompts, and single-action operations (delete, remove, read, show, list, find, search, rename) bypass planning automatically.\n\n**Detection**— heuristics identify complex requests** Plan generation**— AI creates numbered steps** User approval**— review the plan table, then choose: execute, skip planning, or cancel** Step-by-step execution**— each step runs with progress tracking** Error handling**— skip failed steps or cancel the entire plan\n\nSee [Task Planner Documentation](/DevMando/MandoCode/blob/main/src/MandoCode/docs/TaskPlanner.md) for full technical details.\n\nThe `/learn`\n\ncommand helps new users understand local LLMs and get set up.\n\n| Scenario | What happens |\n|---|---|\n| Startup, no Ollama detected | Automatically displays the educational guide instead of a bare error |\n`/learn` typed, no model running |\nDisplays the static educational guide |\n`/learn` typed, model is running |\nShows the guide, then offers to enter AI educator chat mode |\n\n**What are Open-Weight LLMs?**— Free, private, offline models vs. cloud AI** Model Sizes & Hardware**— Parameters, quantization, VRAM requirements** Cloud vs Local Models**— Ollama cloud models (no GPU) vs local models** Recommended Models**— Table of cloud and local options** Getting Started**— Step-by-step setup instructions\n\nWhen Ollama is running, `/learn`\n\noffers an interactive chat mode where the AI explains LLM concepts using beginner-friendly language. Type `/clear`\n\nto return to normal mode.\n\nMandoCode speaks the [Model Context Protocol](https://modelcontextprotocol.io) as a client, which means you can plug in any published MCP server — filesystem, database, GitHub, Linear, Slack, whatever — and its tools show up to the model alongside MandoCode's built-in plugins.\n\nTwo ways:\n\ninside MandoCode — an interactive wizard that prompts through name, transport, URL/command, and optional headers/env vars, previews the JSON, and saves + reloads automatically.`/mcp add`\n\n**Hand-edit**— useful when copy-pasting a`~/.mandocode/config.json`\n\n`mcpServers`\n\nblock from a server's README. Run`/mcp-reload`\n\nafter saving.\n\nThe `mcpServers`\n\nblock mirrors [Claude Desktop's schema](https://modelcontextprotocol.io/docs/develop/connect-local-servers), so you can copy-paste any server's README installation snippet directly into `~/.mandocode/config.json`\n\n:\n\n```\n{\n  \"enableMcp\": true,\n  \"mcpServers\": {\n    \"filesystem\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@modelcontextprotocol/server-filesystem\", \"/path/to/allow\"]\n    },\n    \"solana\": {\n      \"url\": \"https://mcp.solana.com/mcp\",\n      \"transport\": \"http\"\n    },\n    \"github\": {\n      \"url\": \"https://api.githubcopilot.com/mcp/\",\n      \"headers\": { \"Authorization\": \"Bearer ghp_your_token_here\" },\n      \"autoApprove\": [\"list_issues\", \"get_pr\"]\n    }\n  }\n}\n```\n\n**stdio**— for local servers. Populate`command`\n\n+`args`\n\n+ optional`env`\n\n. Works with any server published as an npm/pip/go binary.**HTTP / SSE**— for remote servers. Populate`url`\n\n; the client auto-detects Streamable HTTP or SSE. Custom headers go in`headers`\n\n— most commonly`Authorization: Bearer …`\n\nfor servers that accept static tokens.\n\n**No.** MandoCode itself is pure .NET. But *individual servers* may need whatever runtime their `command`\n\npoints at — Node for `npx`\n\n, Python for `uvx`\n\n, or nothing extra for standalone binaries. Same situation as Claude Desktop, Cursor, and VS Code.\n\nNative OAuth is not in this release. For servers that require an OAuth flow (some hosted connectors like Google Drive), wrap them in stdio via the community [ mcp-remote](https://www.npmjs.com/package/mcp-remote) proxy, which handles the browser dance itself:\n\n```\n\"gdrive\": {\n  \"command\": \"npx\",\n  \"args\": [\"mcp-remote\", \"https://example.com/mcp\"]\n}\n```\n\nMandoCode cannot tell a read-only MCP tool from a destructive one by inspecting arguments, so the first call of each `(server, tool)`\n\npair prompts you with **Approve / Approve for session / Deny**. Pre-trusted tools can be listed under `autoApprove`\n\nin a server's config entry to skip the prompt entirely.\n\n`/mcp`\n\n— shows each configured server with its transport, connection status, and live tool count`/mcp add`\n\n— interactive wizard for adding a new server without hand-editing JSON`/mcp remove <name>`\n\n— remove a server from config (with confirm)`/mcp tools <server>`\n\n— list every tool exposed by connected servers with descriptions (server arg optional — omit to list all)`/mcp-reload`\n\n— tears down every MCP client, restarts them, and re-registers their tools on the kernel (useful when you edit the config mid-session)\n\n```\nmandocode --config set mcp false   # disable all MCP integration\n```\n\nIndividual servers can be muted without deleting them — set `\"disabled\": true`\n\non any entry in `mcpServers`\n\n.\n\nThe AI has sandboxed access to your project directory through these functions:\n\n| Function | Description |\n|---|---|\n`list_all_project_files()` |\nRecursively lists all project files, excluding ignored directories |\n`list_files_match_glob_pattern(pattern)` |\nLists files matching a glob pattern (`*.cs` , `src/**/*.ts` ) |\n`read_file_contents(relativePath, startLine?, endLine?)` |\nReads file content with line count — large files page via `startLine` /`endLine` , and truncated output names the exact line to resume from |\n`write_file(relativePath, content)` |\nWrites/creates a file (creates directories as needed) |\n`delete_file(relativePath)` |\nDeletes a file |\n`create_folder(relativePath)` |\nCreates a new directory |\n`delete_folder(relativePath)` |\nDeletes a directory and all its contents |\n`search_text_in_files(pattern, searchText)` |\nSearches file contents for text, returns paths and line numbers |\n`get_absolute_path(relativePath)` |\nConverts a relative path to absolute |\n\n**Security:** All operations are sandboxed to the project root. Path traversal is blocked with a separator-boundary check.\n\n**Ignored directories:** `.git`\n\n, `node_modules`\n\n, `bin`\n\n, `obj`\n\n, `.vs`\n\n, `.vscode`\n\n, `packages`\n\n, `dist`\n\n, `build`\n\n, `__pycache__`\n\n, `.idea`\n\n— plus any custom directories from your config.\n\nThe AI can search the web and fetch page content — no API keys required.\n\n| Function | Description |\n|---|---|\n`search_web(query, maxResults)` |\nSearches the web and returns titles, URLs, and snippets (1–10 results) |\n`fetch_webpage(url, maxCharacters)` |\nFetches a URL and extracts readable text content (500–15,000 chars) |\n\nOut of the box, search uses DuckDuckGo's free HTML endpoint — which rate-limits and temporarily blocks IPs under heavy agentic use, so searches can randomly fail. For reliable, AI-optimized search, add a free [Tavily](https://www.tavily.com/) API key (free tier ~1,000 searches/month):\n\n```\n/config set tavilyKey tvly-...        # in-app — verifies the key live against Tavily\nmandocode --config set tavilyKey tvly-...   # or from the CLI\n```\n\nWith a key set, `search_web`\n\nprefers Tavily and keeps DuckDuckGo as the fallback; clear it anytime with `/config set tavilyKey clear`\n\n. The key is stored locally in `~/.mandocode/config.json`\n\nand only ever sent to Tavily — set the `TAVILY_API_KEY`\n\nenvironment variable instead if you'd rather keep it out of the file. Fetched pages are cleaned of scripts, nav, and non-content elements via HtmlAgilityPack.\n\nTransient errors (HTTP failures, timeouts, socket errors) are retried with exponential backoff:\n\n``` php\nAttempt 1 -> fail -> wait 500ms\nAttempt 2 -> fail -> wait 1000ms\nAttempt 3 -> fail -> throw\n```\n\n| Operation | Window | Matching |\n|---|---|---|\n| Read operations | 2 seconds | Function name + arguments |\n| Write operations | 5 seconds (configurable) | Function name + path + content hash (SHA256) |\n\nSome local models output function calls as JSON text instead of proper tool calls. MandoCode detects and parses:\n\n- Standard:\n`{\"name\": \"func\", \"parameters\": {...}}`\n\n- OpenAI-style:\n`{\"function_call\": {\"name\": \"func\", \"arguments\": {...}}}`\n\n- Tool calls:\n`{\"tool_calls\": [{\"function\": {\"name\": \"func\", \"arguments\": {...}}}]}`\n\nAI responses are rendered as rich terminal output:\n\n| Markdown | Rendered as |\n|---|---|\n`**bold**` |\nBold text |\n`*italic*` |\nItalic text |\n``code`` |\nCyan highlighted |\n| Fenced code blocks | Bordered panels with syntax highlighting |\n| Tables | Spectre.Console table widgets |\n`# Headers` |\nBold yellow with horizontal rules |\n`- lists` |\nIndented bullet points |\n`> quotes` |\nGrey-bordered block quotes |\n| URLs | Clickable OSC 8 hyperlinks |\n\nSyntax highlighting supports **C#**, **Python**, **JavaScript/TypeScript**, and **Bash** with language-specific keyword coloring.\n\n**Per-response:**`[~1.2k in, 847 out]`\n\nafter each AI response**Session total:**`Total [4.2k tokens]`\n\nabove the prompt**File estimates:**`@file`\n\nattachments show estimated token cost (chars/4)\n\nFunction executions use semaphore-based signaling, ensuring each task plan step fully completes before the next begins.\n\n```\nsrc/MandoCode/\n  Components/        Razor UI (App, Banner, HelpDisplay, ConfigMenu, Prompt)\n  Services/          Core logic (AI, markdown, syntax, tokens, music, diffs, input state machine)\n  Models/            Data models, config, system prompts, educational content\n  Plugins/           Semantic Kernel plugins (FileSystem, WebSearch)\n  Audio/             Bundled lofi and synthwave MP3 tracks\n  docs/              Feature and architecture documentation\n  Program.cs         Entry point and DI registration\n```\n\n| Package | Purpose |\n|---|---|\n|\n\n[Ollama Connector](https://github.com/microsoft/semantic-kernel)1.72.0-alpha[RazorConsole.Core](https://github.com/RazorConsole/RazorConsole)0.5.0-alpha[Markdig](https://github.com/xoofx/markdig)1.0.0[NAudio](https://github.com/naudio/NAudio)2.2.1[HtmlAgilityPack](https://html-agility-pack.net/)1.11.72[FileSystemGlobbing](https://www.nuget.org/packages/Microsoft.Extensions.FileSystemGlobbing)10.0.3Most AI coding agents in the wild are built with Python, Rust, or TypeScript. .NET rarely gets mentioned — but it should.\n\n[Semantic Kernel](https://github.com/microsoft/semantic-kernel) is Microsoft's open-source SDK for building AI agents, and it's one of the most capable orchestration frameworks available: native plugin systems, function calling, structured planning, and first-class support for local models through connectors like Ollama. It runs cross-platform on Windows, Linux, and macOS.\n\nMandoCode exists partly to prove the point: you can build a full-featured, agentic CLI tool on .NET and Semantic Kernel that stands alongside anything built in other ecosystems. The tooling is there. It's open source. It just doesn't get the attention it deserves.", "url": "https://wpnews.pro/news/show-hn-mandocode-local-first-ai-coding-agent-net-and-ollama", "canonical_source": "https://github.com/DevMando/MandoCode", "published_at": "2026-06-12 03:22:10+00:00", "updated_at": "2026-06-12 03:47:17.118786+00:00", "lang": "en", "topics": ["ai-tools", "ai-agents", "ai-products", "generative-ai", "large-language-models"], "entities": ["MandoCode", "RazorConsole", "Semantic Kernel", "Ollama", "Tavily", "Claude-Code", "Spectre.Console", ".NET"], "alternates": {"html": "https://wpnews.pro/news/show-hn-mandocode-local-first-ai-coding-agent-net-and-ollama", "markdown": "https://wpnews.pro/news/show-hn-mandocode-local-first-ai-coding-agent-net-and-ollama.md", "text": "https://wpnews.pro/news/show-hn-mandocode-local-first-ai-coding-agent-net-and-ollama.txt", "jsonld": "https://wpnews.pro/news/show-hn-mandocode-local-first-ai-coding-agent-net-and-ollama.jsonld"}}