README.md

June 10, 2026 · View on GitHub

MandoCode Logo

Your AI coding assistant — run locally or in the cloud with Ollama.
No API keys required. Just you and your code.

NuGet License: MIT .NET 8.0 Ollama Platform Made with <3 by Mando

MandoCode in action

MandoCode is an AI coding assistant built on RazorConsole, powered by Semantic Kernel and Ollama. RazorConsole makes the entire terminal UI possible — Razor components, a virtual DOM, and Spectre.Console rendering all running in the console.

Run locally or connect to Ollama cloud — no API keys required for anything, including web search. 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.


Prerequisites

Install

dotnet tool install -g MandoCode
mandocode

First 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.

Troubleshooting

mandocode --doctor

Prints your runtime version, Ollama status, models pulled, and cloud sign-in state.

⚠️ Local models: check your Ollama context window (the #1 gotcha)

If 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:

⚠ Response was cut off because the model's CONTEXT WINDOW filled …

…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.

If you use the Ollama desktop app (the tray icon), the app's slider controls this — and it overrides everything else:

Ollama desktop app — Settings → Context length slider

Open Ollama Settings → Context length and drag it to 16k (safe for most GPUs) or 32k (8 GB+ VRAM). Bigger windows use more GPU memory (~0.5–1.5 GB per 8k depending on the model), so don't max it out "just in case" — if your tokens/sec craters after raising it, go down one notch.

If you run ollama serve yourself (no desktop app), MandoCode handles it: it sets OLLAMA_CONTEXT_LENGTH from your contextLength config when it starts the daemon, and auto-sizes it to the hardware tier of the model you pick in /setup or /model. Tune it manually with:

mandocode --config set contextLength 16384

Verify what your daemon is actually using with ollama ps (look at the CONTEXT column) — cloud models are unaffected either way, since their context is managed on Ollama's servers. Run /learn inside MandoCode for a friendly explainer.

Or build from source

git clone https://github.com/DevMando/MandoCode.git
cd MandoCode
dotnet build src/MandoCode/MandoCode.csproj
dotnet run --project src/MandoCode/MandoCode.csproj -- /path/to/your/project

What Makes MandoCode Different

Safe File Editing with Diff Approvals

Every file write and delete is intercepted with a color-coded diff. You approve, deny, or redirect — nothing touches disk without your say-so.

Diff approval

@ File References

Type @ to autocomplete any project file and attach it as context. The AI sees the full file content alongside your prompt. Reference multiple files in a single message.

File autocomplete

Task Planner

Complex requests are automatically broken into step-by-step plans. Review the plan, then watch each step execute with progress tracking.

Task planner

Web Search & Fetch

The AI can search DuckDuckGo and read webpages to find documentation, tutorials, or answers — no API keys needed.

Web search

Built-in Music Player

Lofi and synthwave tracks bundled right in. A waveform visualizer runs in the corner while you code. Because vibes matter.

Music player

Offline-Friendly Startup

If Ollama isn't running, MandoCode shows setup guidance inline instead of a bare error. Use /retry to reconnect without restarting.

Offline guidance

Features at a Glance

FeatureDescription
AIProject-aware assistantReads, writes, deletes, and searches your entire codebase
AIWeb search & fetchDuckDuckGo search and webpage reading — no API keys needed
AIMCP server supportConnect to any Model Context Protocol server (stdio or remote HTTP) — Claude-Desktop-compatible config
AIStreaming responsesReal-time output with animated spinners
AITask plannerAuto-detects complex requests and breaks them into steps
AIFallback function parsingHandles models that output tool calls as raw JSON
UIDiff approvalsColor-coded diffs with approve / deny / redirect
UIMarkdown renderingRich terminal output — headers, tables, code blocks, quotes
UISyntax highlightingC#, Python, JavaScript/TypeScript, Bash
UIClickable file linksOSC 8 hyperlinks for file paths
UITerminal theme detectionAuto-adapts colors for light and dark terminals
UITaskbar progressWindows Terminal integration during task execution
Input/ command autocompleteSlash commands with dropdown navigation
Input@ file referencesAttach file content to any prompt
Input! shell escapeRun shell commands inline (!git status, !ls)
Input/copy and /copy-codeCopy responses or code blocks to clipboard
MusicLofi + synthwaveBundled tracks with volume, genre switching, waveform visualizer
ConfigConfiguration wizardGuided setup with model selection and connection testing
ConfigConfig validationAuto-clamps invalid settings to safe ranges
ReliabilityRetry + deduplicationExponential backoff and duplicate call prevention
Education/learn commandLLM education guide with optional AI educator chat

Commands

Type / to see the autocomplete dropdown, or ! to run a shell command.

CommandWhat it does
/helpShow commands and usage examples
/setupGuided wizard — reconnect to Ollama, install/sign in, or pick a different model
/modelQuick switch — pick a different model (context window auto-sized for local tiers)
/configAdjust settings — guided wizard
/config set <key> <value>Set one setting inline without leaving the session (e.g. /config set modelResponseTimeout 300); no args lists all keys + current values
/retryRetry Ollama connection
/learnInteractive guide to LLMs and local AI
/copyCopy last AI response to clipboard
/copy-codeCopy code blocks from last response
/command <cmd>Run a shell command
/musicStart playing music
/music-stopStop playback
/music-pausePause / resume
/music-nextNext track
/music-vol <0-100>Set volume
/music-lofiSwitch to lofi
/music-synthwaveSwitch to synthwave
/music-listList available tracks
/mcpList configured MCP servers with status and tool counts
/mcp addInteractively add a new MCP server to config
/mcp remove <name>Remove an MCP server from config
/mcp tools <server>List tools exposed by connected MCP servers (server optional)
/mcp-reloadRestart all MCP servers and re-register their tools
/clearClear conversation history
/exitExit MandoCode
!<cmd>Shell escape (e.g., !git status)
!cd <path>Change project root directory

Setup vs config vs model

  • /setup — 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.
  • /model — 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.
  • /config — adjust settings. Full configuration form covering temperature, timeouts, ignore dirs, etc. Use when you know exactly what knob you want to turn.

CLI flags (outside the chat loop)

mandocode --doctor          # preflight check: .NET runtime, Ollama status, models, sign-in
mandocode --config show     # print current config
mandocode --config init     # create a default config file
mandocode --config set <key> <value>   # set a single value (e.g. set model qwen3.5:9b)
mandocode --config path     # show config file location

Run mandocode --doctor any time chat is misbehaving — exits 0 if everything's green, 1 if anything's missing, with a clear summary of what's wrong.


How It Works

  You type a prompt
        |
  MandoCode adds project context (@files, system prompt)
        |
  Semantic Kernel sends to Ollama (local or cloud model)
        |
  AI responds with text + function calls
        |
  File operations go through diff approval
  Web searches and fetches run directly
        |
  Rich markdown rendered in your terminal

The 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 DuckDuckGo, webpage fetching — no API keys required). All file operations are locked to your project root — path traversal is blocked.


Models 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.

Cloud (no GPU required — runs on Ollama's servers, free with ollama signin):

ModelNotes
minimax-m2.7:cloudDefault — auto-pulled by /setup when you pick Cloud

Local (fully offline, runs on your hardware):

ModelSizeHardware
qwen3.5:0.8b~1.0 GBCPU-only / integrated GPU — fast on any laptop, light reasoning
qwen3.5:2b~2.7 GBModern CPU or 4 GB+ GPU — quick Q&A, simple code edits
qwen3.5:4b~3.4 GBMid-range GPU (4-6 GB VRAM) or 16 GB RAM — balanced day-to-day use
qwen3.5:9b~6.6 GBDedicated GPU (8+ GB VRAM) — best local quality, multi-file refactors

MandoCode validates model compatibility on startup. Run /learn for a detailed guide on model sizes and hardware requirements, or /setup to switch between tiers any time.


Configuration Reference

Config File

Located at ~/.mandocode/config.json

{
  "ollamaEndpoint": "http://localhost:11434",
  "modelName": "minimax-m2.7:cloud",
  "modelPath": null,
  "temperature": 0.7,
  "maxTokens": 4096,
  "ignoreDirectories": [],
  "enableDiffApprovals": true,
  "enableTaskPlanning": true,
  "enableTokenTracking": true,
  "enableThemeCustomization": true,
  "enableFallbackFunctionParsing": true,
  "functionDeduplicationWindowSeconds": 5,
  "maxRetryAttempts": 2,
  "music": {
    "volume": 0.5,
    "genre": "lofi",
    "autoPlay": false
  }
}

All Options

KeyDefaultDescription
ollamaEndpointhttp://localhost:11434Ollama server URL
modelNameminimax-m2.7:cloudModel to use
modelPathnullOptional path to a local GGUF model file
temperature0.7Response creativity (0.0 = focused, 1.0 = creative)
maxTokens4096Maximum response token length (NumPredict — output cap, not the context window)
contextLength8192Context 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
ignoreDirectories[]Additional directories to exclude from file scanning
enableDiffApprovalstrueShow diffs and prompt for approval before file writes/deletes
enableTaskPlanningtrueEnable automatic task planning for complex requests
enableTokenTrackingtrueShow session token totals and per-response token costs
enableThemeCustomizationtrueDetect terminal theme and apply a curated ANSI palette
enableFallbackFunctionParsingtrueParse function calls from text output
functionDeduplicationWindowSeconds5Time window to prevent duplicate function calls
maxRetryAttempts2Max retry attempts for transient errors
music.volume0.5Music volume (0.0 - 1.0)
music.genrelofiDefault genre (lofi or synthwave)
music.autoPlayfalseAuto-start music on launch

CLI Config Commands

mandocode config show              # Display current configuration
mandocode config init              # Create default configuration file
mandocode config set <key> <value> # Set a configuration value
mandocode config path              # Show configuration file location
mandocode config --help            # Show help

Environment Variables

VariableOverrides
OLLAMA_ENDPOINTollamaEndpoint in config
OLLAMA_MODELmodelName in config

Diff Approvals — Deep Dive

When the AI writes or deletes a file, MandoCode intercepts the operation and shows a color-coded diff before applying changes.

What You See

  • 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

Approval Options

OptionBehavior
ApproveApply this change
Approve - Don't ask againAuto-approve future changes to this file (per-file), or all files (global)
DenyReject the change, the AI is told it was denied
Provide new instructionsRedirect the AI with custom feedback

For 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.

Even when auto-approved, diffs are still rendered so you can follow along.

Delete Approvals

File deletions show all existing content as red removals with a deletion warning. The same approval options apply.

Toggle

mandocode config set diffApprovals false

@ File References — Deep Dive

Type @ anywhere 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.

How It Works

  1. Type your prompt and hit @ — a file dropdown appears
  2. Type a partial name to filter (e.g., Conf) — matches narrow down
  3. Use arrow keys to navigate, Tab or Enter to select
  4. The selected path is inserted (e.g., @src/MandoCode/Models/MandoCodeConfig.cs)
  5. Continue typing and press Enter to submit
  6. MandoCode reads the referenced file(s) and injects the content as context for the AI

Examples

explain @src/MandoCode/Services/AIService.cs to me
what does the ProcessFileReferences method do in @src/MandoCode/Components/App.razor
refactor @src/MandoCode/Models/LoadingMessages.cs to use fewer spinners

Multiple @ references in one prompt are supported. Files over 10,000 characters are automatically truncated.

Controls

KeyAction
@Open file dropdown
TypeFilter files by name
Up/DownNavigate dropdown
Tab/EnterInsert selected file path (does not submit)
EscapeClose dropdown, keep text
BackspaceRe-filter, or close if you delete past @

Task Planner — Deep Dive

MandoCode automatically detects complex requests and offers to break them into a step-by-step plan before execution.

Triggers

The planner activates for requests like:

  • Create a REST API service with authentication and rate limiting for the user module (12+ words with imperative verb and scope indicator)
  • Build an application that handles user registration and sends email confirmations
  • Numbered lists with 3+ items
  • Requests over 400 characters

Simple questions, short prompts, and single-action operations (delete, remove, read, show, list, find, search, rename) bypass planning automatically.

Workflow

  1. Detection — heuristics identify complex requests
  2. Plan generation — AI creates numbered steps
  3. User approval — review the plan table, then choose: execute, skip planning, or cancel
  4. Step-by-step execution — each step runs with progress tracking
  5. Error handling — skip failed steps or cancel the entire plan

See Task Planner Documentation for full technical details.

/learn — LLM Education

The /learn command helps new users understand local LLMs and get set up.

ScenarioWhat happens
Startup, no Ollama detectedAutomatically displays the educational guide instead of a bare error
/learn typed, no model runningDisplays the static educational guide
/learn typed, model is runningShows the guide, then offers to enter AI educator chat mode

Educational Content

  1. What are Open-Weight LLMs? — Free, private, offline models vs. cloud AI
  2. Model Sizes & Hardware — Parameters, quantization, VRAM requirements
  3. Cloud vs Local Models — Ollama cloud models (no GPU) vs local models
  4. Recommended Models — Table of cloud and local options
  5. Getting Started — Step-by-step setup instructions

AI Educator Chat Mode

When Ollama is running, /learn offers an interactive chat mode where the AI explains LLM concepts using beginner-friendly language. Type /clear to return to normal mode.

MCP Servers — Deep Dive

MandoCode speaks the Model Context Protocol 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.

Adding a server

Two ways:

  • /mcp add inside MandoCode — an interactive wizard that prompts through name, transport, URL/command, and optional headers/env vars, previews the JSON, and saves + reloads automatically.
  • Hand-edit ~/.mandocode/config.json — useful when copy-pasting a mcpServers block from a server's README. Run /mcp-reload after saving.

Config shape

The mcpServers block mirrors Claude Desktop's schema, so you can copy-paste any server's README installation snippet directly into ~/.mandocode/config.json:

{
  "enableMcp": true,
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/allow"]
    },
    "solana": {
      "url": "https://mcp.solana.com/mcp",
      "transport": "http"
    },
    "github": {
      "url": "https://api.githubcopilot.com/mcp/",
      "headers": { "Authorization": "Bearer ghp_your_token_here" },
      "autoApprove": ["list_issues", "get_pr"]
    }
  }
}

Transports

  • stdio — for local servers. Populate command + args + optional env. Works with any server published as an npm/pip/go binary.
  • HTTP / SSE — for remote servers. Populate url; the client auto-detects Streamable HTTP or SSE. Custom headers go in headers — most commonly Authorization: Bearer … for servers that accept static tokens.

Does MandoCode need Node?

No. MandoCode itself is pure .NET. But individual servers may need whatever runtime their command points at — Node for npx, Python for uvx, or nothing extra for standalone binaries. Same situation as Claude Desktop, Cursor, and VS Code.

OAuth-only servers

Native 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 proxy, which handles the browser dance itself:

"gdrive": {
  "command": "npx",
  "args": ["mcp-remote", "https://example.com/mcp"]
}

Approvals

MandoCode cannot tell a read-only MCP tool from a destructive one by inspecting arguments, so the first call of each (server, tool) pair prompts you with Approve / Approve for session / Deny. Pre-trusted tools can be listed under autoApprove in a server's config entry to skip the prompt entirely.

Slash commands

  • /mcp — shows each configured server with its transport, connection status, and live tool count
  • /mcp add — interactive wizard for adding a new server without hand-editing JSON
  • /mcp remove <name> — remove a server from config (with confirm)
  • /mcp tools <server> — list every tool exposed by connected servers with descriptions (server arg optional — omit to list all)
  • /mcp-reload — tears down every MCP client, restarts them, and re-registers their tools on the kernel (useful when you edit the config mid-session)

Toggle

mandocode --config set mcp false   # disable all MCP integration

Individual servers can be muted without deleting them — set "disabled": true on any entry in mcpServers.

AI Plugins

FileSystemPlugin

The AI has sandboxed access to your project directory through these functions:

FunctionDescription
list_all_project_files()Recursively lists all project files, excluding ignored directories
list_files_match_glob_pattern(pattern)Lists files matching a glob pattern (*.cs, src/**/*.ts)
read_file_contents(relativePath, startLine?, endLine?)Reads file content with line count — large files page via startLine/endLine, and truncated output names the exact line to resume from
write_file(relativePath, content)Writes/creates a file (creates directories as needed)
delete_file(relativePath)Deletes a file
create_folder(relativePath)Creates a new directory
delete_folder(relativePath)Deletes a directory and all its contents
search_text_in_files(pattern, searchText)Searches file contents for text, returns paths and line numbers
get_absolute_path(relativePath)Converts a relative path to absolute

Security: All operations are sandboxed to the project root. Path traversal is blocked with a separator-boundary check.

Ignored directories: .git, node_modules, bin, obj, .vs, .vscode, packages, dist, build, __pycache__, .idea — plus any custom directories from your config.

WebSearchPlugin

The AI can search the web and fetch page content — no API keys required.

FunctionDescription
search_web(query, maxResults)Searches DuckDuckGo and returns titles, URLs, and snippets (1–10 results)
fetch_webpage(url, maxCharacters)Fetches a URL and extracts readable text content (500–15,000 chars)

Web search uses DuckDuckGo's HTML endpoint. Fetched pages are cleaned of scripts, nav, and non-content elements via HtmlAgilityPack.

Reliability & Internals

Retry Policy

Transient errors (HTTP failures, timeouts, socket errors) are retried with exponential backoff:

Attempt 1 -> fail -> wait 500ms
Attempt 2 -> fail -> wait 1000ms
Attempt 3 -> fail -> throw

Function Deduplication

OperationWindowMatching
Read operations2 secondsFunction name + arguments
Write operations5 seconds (configurable)Function name + path + content hash (SHA256)

Fallback Function Parsing

Some local models output function calls as JSON text instead of proper tool calls. MandoCode detects and parses:

  • Standard: {"name": "func", "parameters": {...}}
  • OpenAI-style: {"function_call": {"name": "func", "arguments": {...}}}
  • Tool calls: {"tool_calls": [{"function": {"name": "func", "arguments": {...}}}]}

Markdown Rendering

AI responses are rendered as rich terminal output:

MarkdownRendered as
**bold**Bold text
*italic*Italic text
`code`Cyan highlighted
Fenced code blocksBordered panels with syntax highlighting
TablesSpectre.Console table widgets
# HeadersBold yellow with horizontal rules
- listsIndented bullet points
> quotesGrey-bordered block quotes
URLsClickable OSC 8 hyperlinks

Syntax highlighting supports C#, Python, JavaScript/TypeScript, and Bash with language-specific keyword coloring.

Token Tracking

  • Per-response: [~1.2k in, 847 out] after each AI response
  • Session total: Total [4.2k tokens] above the prompt
  • File estimates: @file attachments show estimated token cost (chars/4)

Event-Based Completion Tracking

Function executions use semaphore-based signaling, ensuring each task plan step fully completes before the next begins.


Architecture

src/MandoCode/
  Components/        Razor UI (App, Banner, HelpDisplay, ConfigMenu, Prompt)
  Services/          Core logic (AI, markdown, syntax, tokens, music, diffs, input state machine)
  Models/            Data models, config, system prompts, educational content
  Plugins/           Semantic Kernel plugins (FileSystem, WebSearch)
  Audio/             Bundled lofi and synthwave MP3 tracks
  docs/              Feature and architecture documentation
  Program.cs         Entry point and DI registration

Dependencies

PackagePurpose
Microsoft.SemanticKernel 1.72.0LLM orchestration and plugin system
Ollama Connector 1.72.0-alphaOllama model integration
RazorConsole.Core 0.5.0-alphaTerminal UI with Razor components
Markdig 1.0.0Markdown parsing
NAudio 2.2.1Audio playback
HtmlAgilityPack 1.11.72HTML parsing for web search
FileSystemGlobbing 10.0.3Glob pattern matching

Why .NET?

Most AI coding agents in the wild are built with Python, Rust, or TypeScript. .NET rarely gets mentioned — but it should.

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.

MandoCode 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.


MIT License