<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Homelab on vishctl</title><link>https://vishctl.dev/tags/homelab/</link><description>Recent content in Homelab on vishctl</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Mon, 07 Sep 2026 14:30:00 +0800</lastBuildDate><atom:link href="https://vishctl.dev/tags/homelab/index.xml" rel="self" type="application/rss+xml"/><item><title>Running a 35B MoE Model on an 8 GB Laptop GPU: Testing FreeToken</title><link>https://vishctl.dev/posts/running-freetoken-on-8gb-laptop-gpu/</link><pubDate>Mon, 07 Sep 2026 14:30:00 +0800</pubDate><guid>https://vishctl.dev/posts/running-freetoken-on-8gb-laptop-gpu/</guid><category>ai</category><category>local-llm</category><category>freetoken</category><category>gpu</category><category>homelab</category><category>nvidia</category><description>Testing FreeToken on an RTX 4070 Laptop GPU: running Qwen 3.6 35B-A3B NVFP4 across 8 GB VRAM and 32 GB RAM with hierarchical memory offloading.</description><content:encoded><![CDATA[<p>Running large language models locally usually comes down to a hard hardware boundary: video RAM. If a model does not fit into your GPU&rsquo;s VRAM, performance usually falls off a cliff as soon as standard runtimes fall back to system memory over the PCIe bus.</p>
<p>Mixture of Experts (MoE) architectures offer an attractive theoretical escape hatch. While the total parameter count can be large (30B to 70B+), only a sparse subset of expert layers activates for any given token. However, standard local runtimes still require loading the entire weight footprint into memory, which puts 30B+ models out of reach for everyday consumer laptops with 8 GB of VRAM.</p>
<p>Enter <a href="https://github.com/FlashML-org/FreeToken">FreeToken</a> by FlashML, backed by their research paper (<a href="https://arxiv.org/abs/2608.16157">arXiv:2608.16157</a>). FreeToken is an edge inference runtime designed specifically to run frontier MoE models on consumer hardware by dynamically managing a hierarchical cache between GPU VRAM and host RAM.</p>
<p>I recently downloaded FreeToken to put their claims to the test on my modest laptop GPU. Here is what the setup looked like, how FreeToken handles memory under the hood, and the real-world generation numbers I observed.</p>
<h3 id="the-test-rig">The Test Rig</h3>
<p>My test machine is a portable laptop, not a high-end multi-GPU workstation:</p>
<ul>
<li><strong>CPU:</strong> 13th Gen Intel Core i9-13900H (14 cores, 20 threads)</li>
<li><strong>GPU:</strong> NVIDIA GeForce RTX 4070 Laptop GPU (8.0 GiB VRAM)</li>
<li><strong>Host RAM:</strong> 32 GB DDR5 (31.7 GiB usable)</li>
<li><strong>Operating System:</strong> Windows 11</li>
<li><strong>Runtime:</strong> FreeToken Desktop (v0.2.0-beta.17)</li>
</ul>
<figure class="post-screenshot">
    <img loading="lazy" src="https://vishctl.dev/images/posts/freetoken-8gb-laptop-gpu/01-freetoken-website-download.png"
         alt="FreeToken website download page"/> <figcaption>
            <p>The FreeToken landing page highlights bringing frontier models to consumer edge hardware.</p>
        </figcaption>
</figure>

<p>On paper, an 8 GB VRAM budget makes running a 35-billion parameter model look impossible. In traditional setups, 8 GB VRAM limits you to 7B or 8B parameter models in 4-bit quantizations (such as Q4_K_M). Attempting to load a 35B model typically triggers out-of-memory errors or slows inference to a crawl.</p>
<h3 id="installing-freetoken-and-exploring-the-library">Installing FreeToken and Exploring the Library</h3>
<p>The FreeToken desktop app is available to download directly from the <a href="https://www.flashml.ai/">FlashML website</a>. It provides a self-contained installer that is quick to set up on Windows. When you launch it, the interface automatically detects your hardware specs, available VRAM, and system RAM, and presents a curated library of models optimized for edge offloading.</p>
<figure class="post-screenshot">
    <img loading="lazy" src="https://vishctl.dev/images/posts/freetoken-8gb-laptop-gpu/02-hardware-specs-and-model-library.png"
         alt="FreeToken hardware detection and model library"/> <figcaption>
            <p>FreeToken accurately detects the RTX 4070 Laptop GPU (8 GB) and 32 GB RAM, recommending compatible models.</p>
        </figcaption>
</figure>

<p>For this test, I selected <code>Qwen3.6-35B-A3B NVFP4</code> (<code>nvidia/Qwen3.6-35B-A3B-NVFP4</code>). This is a 35-billion parameter MoE model using NVIDIA&rsquo;s 4-bit floating point (NVFP4) format, with an initial download size of 21.9 GiB.</p>
<p>Before loading the model, the console dashboard showed clean baseline resource usage:</p>
<ul>
<li><strong>GPU VRAM:</strong> 0.4 / 8.0 GiB</li>
<li><strong>Host RAM:</strong> 11.0 / 31.7 GiB</li>
<li><strong>GPU Temp:</strong> 42°C at idle</li>
</ul>
<figure class="post-screenshot">
    <img loading="lazy" src="https://vishctl.dev/images/posts/freetoken-8gb-laptop-gpu/03-system-resources-idle.png"
         alt="System resources at idle before model loading"/> <figcaption>
            <p>Idle console telemetry: 0.4 GiB VRAM used, ready for model weights.</p>
        </figcaption>
</figure>

<h3 id="weight-conversion-the-ftw-format">Weight Conversion: The FTW Format</h3>
<p>Once the 21.9 GiB download finished, FreeToken flagged the model as needing conversion before it could be launched.</p>
<figure class="post-screenshot">
    <img loading="lazy" src="https://vishctl.dev/images/posts/freetoken-8gb-laptop-gpu/05-download-complete-needs-conversion.png"
         alt="Download complete prompt indicating conversion is required"/> <figcaption>
            <p>Raw model download complete (21.9 GiB), prompting for weight conversion.</p>
        </figcaption>
</figure>

<p>FreeToken converts raw Hugging Face weights into its proprietary format called <strong>FTW</strong> (FreeToken Weight format). During this process, the engine repacks and organizes the tensors into memory-mapped structures optimized for rapid streaming between host RAM and GPU memory.</p>
<figure class="post-screenshot">
    <img loading="lazy" src="https://vishctl.dev/images/posts/freetoken-8gb-laptop-gpu/06-converting-weights-to-ftw.png"
         alt="Converting raw weights into FTW format"/> <figcaption>
            <p>Repacking raw weights into FTW format for fast memory streaming.</p>
        </figcaption>
</figure>

<p>The conversion took just over a minute on the i9-13900H and NVMe storage, producing a compact 19.5 GiB weight package.</p>
<figure class="post-screenshot">
    <img loading="lazy" src="https://vishctl.dev/images/posts/freetoken-8gb-laptop-gpu/07-conversion-complete-ftw.png"
         alt="Conversion complete showing 19.5 GiB repacked size"/> <figcaption>
            <p>Conversion complete: 19.5 GiB ready for execution.</p>
        </figcaption>
</figure>

<h3 id="loading-the-model-and-memory-allocation">Loading the Model and Memory Allocation</h3>
<p>Starting the model triggers the weight allocation phase. Instead of attempting to cram the entire 19.5 GiB into the 8 GB VRAM, FreeToken partitions the workload across both memory tiers.</p>
<figure class="post-screenshot">
    <img loading="lazy" src="https://vishctl.dev/images/posts/freetoken-8gb-laptop-gpu/08-loading-weights-into-vram.png"
         alt="Loading model weights into VRAM"/> <figcaption>
            <p>Starting model and populating active weights into VRAM.</p>
        </figcaption>
</figure>

<p>Once loaded, the memory profile was eye-opening:</p>
<ul>
<li><strong>VRAM Usage:</strong> 6.8 GiB / 8.0 GiB (85% utilization, leaving a healthy buffer for OS display compositing)</li>
<li><strong>Host RAM Usage:</strong> 30.2 GiB / 31.7 GiB (95% utilization)</li>
<li><strong>GPU Status:</strong> Running at 45°C, drawing only 7W at idle</li>
</ul>
<figure class="post-screenshot">
    <img loading="lazy" src="https://vishctl.dev/images/posts/freetoken-8gb-laptop-gpu/09-model-running-vram-ram-usage.png"
         alt="Model running with VRAM and RAM utilization"/> <figcaption>
            <p>Model running: 6.8 GiB in VRAM and 30.2 GiB in system RAM.</p>
        </figcaption>
</figure>

<h3 id="the-cache-architecture-under-the-hood">The Cache Architecture Under the Hood</h3>
<p>The console view provides detailed insight into how FreeToken manages this memory footprint:</p>
<ol>
<li><strong>MoE Expert Cache:</strong> FreeToken allocated 916 active expert slots in VRAM out of a total pool of 10,240 slots, consuming 1.51 GiB of VRAM. As different experts are needed during generation, they are dynamically paged in and out from the host RAM cache.</li>
<li><strong>KV Cache:</strong> 8K tokens of context were allocated in VRAM, consuming just 0.16 GiB.</li>
<li><strong>Mamba State Slots:</strong> 24 state slots were reserved, using 1.44 GiB of VRAM.</li>
</ol>
<figure class="post-screenshot">
    <img loading="lazy" src="https://vishctl.dev/images/posts/freetoken-8gb-laptop-gpu/10-cache-architecture-console.png"
         alt="Cache architecture telemetry in console"/> <figcaption>
            <p>Detailed cache breakdown: MoE expert cache, KV cache, and Mamba state slots in VRAM.</p>
        </figcaption>
</figure>

<p>This hierarchical design is the core reason the model can run without crashing. Inactive experts reside in system RAM (filling ~30 GB of system memory), while the active attention layers, KV cache, and currently triggered experts reside in the 8 GB VRAM.</p>
<h3 id="real-world-performance--generation-speed">Real-World Performance &amp; Generation Speed</h3>
<p>To evaluate real-world performance, I tested a conversational prompt with reasoning enabled:</p>
<blockquote>
<p><strong>User:</strong> &ldquo;hi, how are you ?&rdquo;</p>
</blockquote>
<p>The model engaged its full thinking process, taking 1 minute and 9 seconds to plan and structure its response, and then generated 393 tokens at <strong>4.3 tokens per second</strong>.</p>
<figure class="post-screenshot">
    <img loading="lazy" src="https://vishctl.dev/images/posts/freetoken-8gb-laptop-gpu/11-chat-inference-test.png"
         alt="Chat inference test output and token speed"/> <figcaption>
            <p>Chat generation benchmark: 393 tokens generated at 4.3 tok/s with full chain-of-thought thinking.</p>
        </figcaption>
</figure>

<p>While 4.3 tokens per second is not real-time voice conversational speed, it is remarkably steady for running a <strong>35-billion parameter model on an 8 GB laptop GPU</strong>. For tasks like code review, background agent execution, document analysis, or local drafting, 4.3 tok/s is completely practical.</p>
<p>The model detail sheet confirms the architecture and licensing details:</p>
<ul>
<li><strong>Base Repository:</strong> <code>nvidia/Qwen3.6-35B-A3B-NVFP4</code></li>
<li><strong>Context Length:</strong> 262,144 tokens (256K context window)</li>
<li><strong>License:</strong> Apache 2.0</li>
</ul>
<figure class="post-screenshot">
    <img loading="lazy" src="https://vishctl.dev/images/posts/freetoken-8gb-laptop-gpu/12-model-details-huggingface.png"
         alt="Model detail card on FreeToken"/> <figcaption>
            <p>Model details: 262K context window, NVFP4 quantization, and Apache 2.0 license.</p>
        </figcaption>
</figure>

<h3 id="built-in-agentic-tooling--local-endpoints">Built-in Agentic Tooling &amp; Local Endpoints</h3>
<p>FreeToken also includes built-in support for developer tools and coding agents.</p>
<p>The <strong>Apps</strong> tab exposes both OpenAI-compatible and Anthropic-compatible local HTTP endpoints:</p>
<ul>
<li><strong>OpenAI Endpoint:</strong> <code>http://127.0.0.1:1919/v1</code></li>
<li><strong>Anthropic Messages Endpoint:</strong> <code>http://127.0.0.1:1919/v1/messages</code></li>
</ul>
<figure class="post-screenshot">
    <img loading="lazy" src="https://vishctl.dev/images/posts/freetoken-8gb-laptop-gpu/04-local-api-endpoints-and-apps.png"
         alt="FreeToken Apps tab showing local endpoints and integrations"/> <figcaption>
            <p>Local OpenAI and Anthropic compatible endpoints with one-click configurations for Claude Code, Codex, opencode, and more.</p>
        </figcaption>
</figure>

<p>FreeToken provides quick configuration presets for popular coding assistants:</p>
<ul>
<li><strong>Claude Code:</strong> Configurable via local Anthropic endpoint routing</li>
<li><strong>Codex / opencode / openclaw:</strong> One-click environment setups</li>
<li><strong>Hermes / DeepSeek Harness:</strong> Direct command-line integration</li>
</ul>
<p>Having drop-in compatibility with both OpenAI and Anthropic API schemas means you can point tools like Claude Code directly to your localhost port without running a reverse proxy.</p>
<h3 id="where-freetoken-fits">Where FreeToken Fits</h3>
<p>FreeToken is a relatively young product, but its approach solves a real constraint for local inference.</p>
<h4 id="strengths">Strengths</h4>
<ul>
<li><strong>Bypasses the VRAM limit:</strong> Running a 35B MoE model on an 8 GB laptop GPU without manual layer-by-layer offload tuning works out of the box.</li>
<li><strong>Hierarchical caching:</strong> The dynamic MoE expert cache keeps VRAM usage around 6.8 GiB, preventing driver resets and CUDA out-of-memory crashes.</li>
<li><strong>Local developer endpoints:</strong> Dual support for OpenAI and Anthropic endpoints makes integration with modern coding agents straightforward.</li>
<li><strong>Simple setup on Windows:</strong> No manual compilation, no CUDA toolkit troubleshooting, and a clean desktop GUI.</li>
</ul>
<h4 id="limitations">Limitations</h4>
<ul>
<li><strong>System RAM is the real requirement:</strong> While VRAM requirements drop significantly, your host RAM must be large enough to hold the repacked weights. On my machine, the model took 30.2 GB of system RAM. If your laptop only has 16 GB of RAM, you will not be able to run 35B models this way.</li>
<li><strong>Initial conversion step:</strong> Each new model requires a one-time repacking step into the FTW format before the first run.</li>
<li><strong>Generation throughput:</strong> At roughly 4.3 tokens per second, it is well suited for asynchronous workloads, coding agents, and complex reasoning queries, but not for instant conversational back-and-forth.</li>
</ul>
<h3 id="wrap-up">Wrap-up</h3>
<p>If you have a laptop with 32 GB of system RAM and a modest 8 GB NVIDIA GPU, FreeToken is worth checking out. It makes 35B-class MoE models runnable on consumer hardware that would otherwise choke on them, keeping your data completely local.</p>
<p>You can download the desktop app directly from <a href="https://www.flashml.ai/">FlashML</a>, check out the project on <a href="https://github.com/FlashML-org/FreeToken">GitHub</a>, and read their research paper on <a href="https://arxiv.org/abs/2608.16157">arXiv:2608.16157</a>.</p>
]]></content:encoded></item><item><title>Running Ollama on a 32 GB MacBook Air: A Practical First Setup</title><link>https://vishctl.dev/posts/running-ollama-on-32gb-macbook-air/</link><pubDate>Thu, 03 Sep 2026 09:30:00 +0800</pubDate><guid>https://vishctl.dev/posts/running-ollama-on-32gb-macbook-air/</guid><category>ai</category><category>local-llm</category><category>ollama</category><category>apple-silicon</category><category>homelab</category><description>Install Ollama, pull and run local models, and call the local API on a 32 GB Apple-silicon MacBook Air.</description><content:encoded><![CDATA[<p>I have a 32 GB MacBook Air. It is not a workstation GPU box, but its unified memory makes it a surprisingly capable machine for local models, provided I choose models that fit and keep expectations sensible.</p>
<p>This is the first post in a small, practical series about running models locally. I am starting with Ollama because it gets a model running quickly without building a runtime from source or hand-managing dependencies.</p>
<h3 id="why-ollama">Why Ollama</h3>
<p><a href="https://ollama.com/">Ollama</a> manages model downloads, exposes a straightforward CLI, and starts a local HTTP API. On Apple silicon, it supports the Apple GPU; Ollama&rsquo;s current macOS requirement is Sonoma (14) or newer. The app stores models and configuration under <code>~/.ollama</code>. <a href="https://docs.ollama.com/macos">The macOS documentation</a> is the useful reference for install, storage, and logs.</p>
<p>Under the hood, Ollama packages model management and an API around inference backends including <a href="https://github.com/ggml-org/llama.cpp">llama.cpp</a>. That distinction is useful: Ollama is the convenient front door; llama.cpp is a lower-level route I can use later when I want to compare runtimes directly.</p>
<h3 id="step-1-install-ollama">Step 1: Install Ollama</h3>
<p>Download the macOS app from <a href="https://ollama.com/download">ollama.com/download</a>, mount the DMG, and drag Ollama to <code>/Applications</code>. Start it once. If the CLI is not already available, the app will offer to add it to your path.</p>
<p>Confirm that both the CLI and the local server are available:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">ollama --version
</span></span><span class="line"><span class="cl">ollama list
</span></span><span class="line"><span class="cl">ollama ps
</span></span></code></pre></div><p>On a new installation, <code>ollama list</code> and <code>ollama ps</code> should be empty. The first reports downloaded models; the second reports models currently loaded into memory.</p>
<h3 id="step-2-pull-a-model">Step 2: Pull a Model</h3>
<p>For this machine, I started with Ornith 1.5 9B:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">ollama pull ornith-1.5:9b
</span></span></code></pre></div><p>This feels deliberately familiar if you work with containers: <code>ollama pull</code> downloads the model and its layers, while <code>ollama run</code> starts an interactive session. The current Ollama build of <code>ornith-1.5:9b</code> is 6.6 GB with a 256K context window, which is a comfortable starting point on a 32 GB laptop. <a href="https://ollama.com/library/ornith-1.5">Ollama&rsquo;s model page</a> lists the available tags; the 35B download is 23 GB, so I would not make that the default on an Air.</p>
<figure class="post-screenshot">
    <img loading="lazy" src="https://vishctl.dev/images/posts/ollama-32gb-macbook-air/01-pull-ornith-1-5-9b.png"
         alt="Pulling Ornith 1.5 9B, then confirming the local model"/> <figcaption>
            <p>Pulling Ornith 1.5 9B, then confirming it is available locally.</p>
        </figcaption>
</figure>

<p>After the pull completes, confirm it is available:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">ollama list
</span></span></code></pre></div><h3 id="step-3-run-it-interactively">Step 3: Run It Interactively</h3>
<p>Start a chat session with the model:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">ollama run ornith-1.5:9b
</span></span></code></pre></div><p>Use a question that resembles the work you actually do. I tested a simple greeting first, then moved on to infrastructure questions. Exit the interactive prompt with <code>/exit</code> or <code>Ctrl-D</code>.</p>
<figure class="post-screenshot">
    <img loading="lazy" src="https://vishctl.dev/images/posts/ollama-32gb-macbook-air/02-run-ornith-1-5-9b.png"
         alt="An interactive Ornith 1.5 9B session in the terminal"/> <figcaption>
            <p>A first interactive conversation with the locally running model.</p>
        </figcaption>
</figure>

<p>For an initial sanity check, the model was responsive and produced a natural answer. That is useful confirmation that the model loads and runs locally, but it is not a benchmark. A real comparison needs the same prompt, context length, generation settings, and output length.</p>
<h3 id="step-4-inspect-performance-with---verbose">Step 4: Inspect Performance with <code>--verbose</code></h3>
<p>Ollama&rsquo;s <code>--verbose</code> flag is a quick way to see timings after every response:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">ollama run ornith-1.5:9b --verbose
</span></span></code></pre></div><p>On this MacBook Air, my short greeting test produced 114 output tokens at <strong>16.68 tokens/sec</strong>, with a total duration of <strong>7.22 seconds</strong>. The model&rsquo;s thinking trace was visible before its answer.</p>
<p>I ran the same kind of test with Gemma 4 E4B:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">ollama run gemma4:e4b --verbose
</span></span></code></pre></div><p>That run produced 228 output tokens at <strong>27.62 tokens/sec</strong>, with a total duration of <strong>8.49 seconds</strong>. It is faster in this small test, but it also generated a different and longer response. These figures are useful as a personal baseline, not as an apples-to-apples model ranking.</p>
<h3 id="ornith-15-9b-vs-gemma-4-e4b">Ornith 1.5 9B vs. Gemma 4 E4B</h3>
<p>Both models fit well on a 32 GB MacBook Air, but they are aimed at slightly different trade-offs.</p>
<table>
	<thead>
			<tr>
					<th>Model</th>
					<th>What I observed</th>
					<th>Practical fit</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>ornith-1.5:9b</code></td>
					<td>6.6 GB download; 16.68 tokens/sec in my short verbose run</td>
					<td>A capable 9B-class, text-and-image model with plenty of memory headroom</td>
			</tr>
			<tr>
					<td><code>gemma4:e4b</code></td>
					<td>9.6 GB download; 27.62 tokens/sec in my different short verbose run</td>
					<td>An efficient edge model for local chat, reasoning, coding, and multimodal work</td>
			</tr>
	</tbody>
</table>
<p>The <code>E</code> in Gemma 4 E4B means <strong>effective</strong> parameters. Ollama describes E4B as a 4.5B-effective-parameter edge model (8B including embeddings), with a 128K context window and text, image, and audio support. It is designed to do useful local work without the memory cost of the larger Gemma 4 workstation models. <a href="https://ollama.com/library/gemma4">The Gemma 4 library page</a> has the current tags, sizes, and capabilities.</p>
<p>In practice, I would start with <code>ornith-1.5:9b</code> if I want the smaller download and a roomy 256K context window, or <code>gemma4:e4b</code> if I want the efficient Gemma 4 feature set. Neither of these two quick runs says which model is universally better; use the prompts you care about and record the result.</p>
<h3 id="step-5-call-the-local-api">Step 5: Call the Local API</h3>
<p>The terminal chat is only the first test. Ollama exposes an API locally at <code>http://localhost:11434/api</code>, so the model can be part of a script or an application.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">curl http://localhost:11434/api/chat <span class="se">\
</span></span></span><span class="line"><span class="cl">  -d <span class="s1">&#39;{
</span></span></span><span class="line"><span class="cl"><span class="s1">    &#34;model&#34;: &#34;ornith-1.5:9b&#34;,
</span></span></span><span class="line"><span class="cl"><span class="s1">    &#34;messages&#34;: [{&#34;role&#34;: &#34;user&#34;, &#34;content&#34;: &#34;Hello!&#34;}],
</span></span></span><span class="line"><span class="cl"><span class="s1">    &#34;stream&#34;: false
</span></span></span><span class="line"><span class="cl"><span class="s1">  }&#39;</span>
</span></span></code></pre></div><figure class="post-screenshot">
    <img loading="lazy" src="https://vishctl.dev/images/posts/ollama-32gb-macbook-air/03-ornith-local-api.png"
         alt="Calling the local Ollama chat API with curl"/> <figcaption>
            <p>Calling the same model through Ollama&rsquo;s local chat API.</p>
        </figcaption>
</figure>

<p>The response includes the answer and useful timing fields. Keep this endpoint local by default. If I later expose it to another device, I will put authentication and a proper reverse proxy in front of it. I will not publish port 11434 directly. <a href="https://docs.ollama.com/api/introduction">Ollama&rsquo;s API documentation</a> covers the local base URL and client libraries.</p>
<h3 id="step-6-try-the-app-ui">Step 6: Try the App UI</h3>
<p>The CLI is great for testing and scripts, but the Ollama app also gives me a simple chat interface. Here, Ornith is selected in the model picker and used for a weather question.</p>
<figure class="post-screenshot">
    <img loading="lazy" src="https://vishctl.dev/images/posts/ollama-32gb-macbook-air/04-ollama-app-ornith.png"
         alt="The Ollama app with Ornith 1.5 9B selected"/> <figcaption>
            <p>The Ollama app with Ornith 1.5 9B selected for a web-assisted prompt.</p>
        </figcaption>
</figure>

<p>The app can also give a model access to web tools. In this example, Ornith searched for current Singapore weather before answering. That extends the model with fresh online information when the tool is enabled, but it does not replace the model&rsquo;s built-in training knowledge. Treat retrieved results as sources to verify, especially for technical or time-sensitive answers.</p>
<p>The UI is useful when I want to compare prompts casually. The local API is the path I will use when I want to integrate models into tooling.</p>
<h3 id="commands-worth-remembering">Commands Worth Remembering</h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># Download without entering an interactive chat</span>
</span></span><span class="line"><span class="cl">ollama pull ornith-1.5:9b
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Start an interactive chat</span>
</span></span><span class="line"><span class="cl">ollama run ornith-1.5:9b
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Show downloaded models and their disk usage</span>
</span></span><span class="line"><span class="cl">ollama list
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Show models currently loaded by the runner</span>
</span></span><span class="line"><span class="cl">ollama ps
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Remove a model I no longer need</span>
</span></span><span class="line"><span class="cl">ollama rm ornith-1.5:9b
</span></span></code></pre></div><p>Models are not small. Treat <code>ollama pull</code> the same way you would a sizeable <code>docker pull</code>: check disk space before collecting a pile of models &ldquo;just in case.&rdquo;</p>
<h3 id="what-this-macbook-air-is-good-at">What This MacBook Air Is Good At</h3>
<p>An 8B to 9B class model is a good fit for private note summarisation, explaining logs, drafting YAML, lightweight coding help, and experimenting with local integrations. This is not where I expect a 70B-class model to be effortless or where I would host production inference.</p>
<p>There are many ways to run models locally, but Ollama is an excellent Apple-silicon starting point. It gets the plumbing out of the way so I can spend time evaluating the models themselves.</p>
<p>Next, I will run llama.cpp directly on the same machine, then see whether a vLLM setup is worth comparing. Stay tuned.</p>
]]></content:encoded></item><item><title>Hello World</title><link>https://vishctl.dev/posts/hello-world/</link><pubDate>Wed, 02 Sep 2026 15:17:58 +0800</pubDate><guid>https://vishctl.dev/posts/hello-world/</guid><category>devops</category><category>kubernetes</category><category>infrastructure</category><category>ai</category><category>homelab</category><description>A quick intro to vishctl, my background in Kubernetes and AI infra, and why this blog exists.</description><content:encoded><![CDATA[<p>Hey, I&rsquo;m Vishnu. Welcome to my little corner of the internet.</p>
<h3 id="what-i-do">What I Do</h3>
<p>Professionally, I have about 9 years of overall experience under my belt. I actually started out writing code as a .NET developer before pivoting hard into DevOps and infrastructure engineering. Since 2019, I have been deep in the Kubernetes ecosystem, architecting and managing infrastructure across physical data centers and public clouds.</p>
<p>Over the years, that has meant running everything from standard high-traffic web platforms to mission-critical telco workloads, airgapped enterprise environments, and AI-native GPU clusters. Nowadays, my work revolves heavily around container orchestration, SUSE and Rancher setups, vLLM inference deployments, and homelab GPU testing.</p>
<h3 id="who-i-am">Who I Am</h3>
<p>At my core, I am a tech guy through and through. Whether it is tackling an infrastructure puzzle at work, geeking out over the latest gadgets, or dreaming of walking the floor at CES, technology is simply what makes the most sense to me.</p>
<p>Outside of terminal windows and YAML files, you will usually find me playing FPS PC games, binging a good web series, or unwinding with music. I also have a massive bucket list goal: to travel the entire world before I hit my deathbed.</p>
<h3 id="why-this-blog-exists">Why This Blog Exists</h3>
<p>This site is where I will document the problems I run into and the solutions that worked. Expect practical write-ups on Kubernetes quirks, AI infrastructure experiments, airgapped deployments, and whatever interesting challenge I am currently knee-deep in.</p>
<p>No fixed publishing schedule. No corporate polish guarantee. Just authentic notes from the trenches, mostly so future-me (and maybe you) does not have to re-solve the same headache twice.</p>
<p>More soon.</p>
]]></content:encoded></item></channel></rss>