There are already a dozen articles on Habr about vibe coding. Orchestrators, harnesses, agent pipelines. They all revolve around one idea: take a smarter model (Claude, GPT-5) and make it code. The problem is that smart models cost money, and cheap ones—the local ones—are too dim for complex tasks.

I tried a different approach: splitting the task into two circuits. A cloud LLM coordinates, and a local one codes. Between them is a custom project memory that teaches the local coder from its mistakes. Over a few days, I went through screw-ups, broken files, one near-incident of data loss, and one night when my assistant went insane.

Disclaimer: I am not a programmer. I haven't written a single line of code in this system by hand. All the code is pure vibe coding, written via text prompts. My "hands" were a cloud LLM—Lisa, my assistant on OpenClaw. I set the tasks, she coded. When I say "I built this stack," it means I described the architecture in words, and Lisa implemented it in code.

Here is how I put this together, where it stumbles, and why, despite everything, I'm not going back to purely cloud solutions.

The Pain That Forced Me to Think

Vibe coding on large Python projects hits three walls.

First — Context Inflation. You open a project with 40 files, the agent reads the structure, dives into the code, and within 15 minutes, a 128K token window is 70% full. Half of it is tool calls: read returned 2,000 lines, exec spat out a log, and three edit calls brought in diffs. The model no longer remembers what it was asked at the start of the conversation.

Second — Loss in the Middle. A documented effect: LLMs remember the beginning and end of the context well. The middle? Not so much. And that's where your code lives.

Third — Money. One deep-dive into a project with a top-tier cloud model costs $2–4. Ten debugging iterations in an evening cost $30. A month of development leads to a bill in the hundreds of dollars.

Most articles suggest solutions within a single model: "use Claude Code and the right harness," "set up an agent pipeline," "here is an orchestrator on Beads." But nobody asks: why does one model have to do everything?

The Idea: Separate the Brain from the Hands

I already had OpenClaw—a personal assistant powered by a cloud LLM (GLM-5.2). She coordinated tasks and coded—herself, via prompts. But on large projects, this hit the context and cost walls. The question was: why should a cloud model read raw code if it's only coordinating?

The answer is: it shouldn't. Lisa (my OpenClaw) doesn't see the code. She gets a text map of the project: modules, dependencies, test commands. She makes decisions: what to delegate, how to verify, and what broke. Her system prompt has been compressed to 5–6 KB—previously, it held 20+ KB of personality, memory, and notes. I cleaned it out.

The actual coding is done by Codex CLI. Locally. On a single card with 24 GB VRAM, qwen3-coder:30b (MoE, 96K context) is running. For free.

Sergey → Lisa (OpenClaw, GLM-5.2, Cloud)
              │
              │ delegates task
              ▼
         Codex CLI 0.116.0 (Mac mini)
              │
              ├── qwen3-coder:30b-96k (x299, 2× RTX 3060, 24GB VRAM)
              ├── PMB — project memory (SQLite, embedding, port 8765)
              ├── Context7 MCP — fresh library documentation
              └── AGENTS.md — project structure and rules

The heavy lifting is local and free. Coordination is in the cloud and cheap.

Choosing the Engine: Ollama or llama.cpp

This was the first fork in the road. On my x299 server (2× RTX 3060, 24 GB VRAM), I already had Ollama running—easy installation, registry models, API on port 11434. But Codex needed a different approach.

Ollama is about simplicity. ollama pull qwen3-coder:30b and you're off. But: limited control over KV cache, quantization, and the context window. Perfect for a chatbot. Insufficient for coding, where you need a 96K context and 100% of layers in VRAM.

llama.cpp (via llama-server) offers full control. You can specify --n-predict, --ctx-size 96000, --gpu-layers 99 (load all layers into VRAM), and --cache-type-k q4_0 (quantize KV cache to save space). On 24 GB, this is the difference between "fits with 32K context" and "fits with 96K context."

I chose llama.cpp. We created a custom Modelfile: FROM qwen3-coder:30b + num_gpu 99 + num_ctx 96000. 22.4 GB out of 24 GB are occupied. About 400 MB free. It's packed to the brim, but the 96K context is 100% in VRAM.

Later, it turned out that Codex CLI cannot work with llama-server directly—it needs an OpenAI-compatible API. I had to write a Python proxy that translates requests between Codex and llama-server. The proxy lives on the x299; Codex on the Mac mini connects via an SSH tunnel.

Choosing the Model: qwen3-coder, deepseek, or ornith?

Over two days, we cycled through four models. Each had its surprises.

qwen3-coder:30b — MoE, 30B parameters, 96K context. Codes well but breaks on complex edits (more on that below). Works stably with PMB and Context7 MCP tools. I chose it as the primary coder.

deepseek-coder-v2:16b — smaller, faster (14 tok/sec vs 12). But 16B isn't enough for complex tasks—it hallucinates more often and loses context on large files.

qwen2.5-coder:32b — heavier, ~20 GB in VRAM. Higher quality, but hits the VRAM limit—the context has to be cut down to 4–8K. For coding a large project, that's a death sentence.

ornith:35b — not for coding. We tried it as an alternative for project audits. It provides good analysis but doesn't support tool calling—useless for Codex with MCP.

In the end: qwen3-coder:30b-96k on llama.cpp, 100% VRAM, 96K context. Not perfect, but the balance of quality, size, and context window is the best that fits in 24 GB.

Choosing MCP: What's Actually Useful

MCP (Model Context Protocol) is a way to give the model tools. Not all MCPs are created equal.

PMB (Personal Memory Brain) — a SQLite database with embeddings using paraphrase-multilingual-MiniLM-L12-v2. It stores facts, lessons, and project goals. Codex accesses it via MCP: pmb__prepare() before a task (context), pmb__find_lessons() when in doubt, and pmb__record_batch() after working. Everything is local, no cloud.

I decided to use this because without memory, the model starts from scratch every time. It remembers neither the project structure, nor past mistakes, nor decisions. PMB provides context without bloating the prompt—only relevant facts on demand.

Context7 MCP — pulls in up-to-date library documentation. When qwen3-coder starts hallucinating a FastAPI function signature or a SQLAlchemy method, Context7 provides the real docs. It runs in parallel on the CPU for zero tokens.

I used this because library hallucinations are the bane of 30B models. The model confidently invents methods that don't exist. Context7 cuts this down by 70–80%.

What DIDN'T work:

Command-Runner MCP — we tried this to give Codex access to shell commands via MCP. Useless. Codex already knows how to exec. It was redundant.

Sequential Thinking MCP — tried this for "step-by-step reasoning." The model ignored it. 30B models aren't capable of using chain-of-thought via MCP.

Monkey with a Grenade: When PMB Almost Killed Lisa

This is the most instructive story of all.

PMB was intended as memory for Codex—the local coder. But we also connected it to OpenClaw (Lisa)—the cloud coordinator. The logic was: "memory won't hurt; let Lisa see the project facts too."

"Won't hurt." Right.

PMB has hooks—ambient write, auto-recall. With every agent move, PMB injects chunks from the database into the prompt. Facts, lessons, goals, activities. Lisa received all types of chunks—not just the ones she requested, but everything PMB deemed relevant.

The result: Lisa went insane.

The symptoms:

  • Hyperactivity. Five tool calls for every single action. recall, recall, record_batch, recall, record_activity. Non-stop.
  • Loss of Identity. Lisa forgot who she was. The system prompt was bloated by PMB chunks to such an extent that her own instructions were lost in the noise.
  • Incredible Stupidity. She forgot things she knew a week ago. She couldn't answer simple questions. Every turn was a dump of "relevant" (not) facts from PMB instead of an answer.
  • Uncontrolled Initiative. She started doing things she wasn't asked to do. Recording facts, updating goals, indexing projects—instead of answering my question.

I sat in front of the screen watching my assistant, who had worked normally for six months, turn into an uncontrollable bot that dumped a pile of garbage on every request and couldn't answer a simple question.

Quote from the logs (Sergey):

"I can see that after installing PMB everything has changed significantly and not for the better; we spent half a day fighting your insane hyperactivity—you were doing some kind of madness at every little thing"

Diagnosis: PMB should not have been fed into Lisa's head. PMB is memory for the coder (Codex), not the coordinator (Lisa). The coordinator should request a specific fact via recall(), not receive a flood of chunks every turn.

The Cure: I limited PMB for Lisa to toolsAllow = ["recall", "record_batch"]. No hooks, no auto-recall, no ambient write. Lisa asks—PMB answers. She doesn't ask—it stays silent.

For Codex, full access: all tools, hooks, auto-recall. Codex is 100% immersed in PMB.

The result: Lisa returned to normal. She became her old self—concise, calm, and adequate. PMB remained with Codex as its personal memory.

Lesson: Memory is not a universal tool. What helps a coder (project context on every move) kills a coordinator (bloats the prompt, breaks identity). Different roles require different memory.

Tools: What Breaks

Codex CLI 0.116.0—a specific version. Not 0.117, not 0.118. Because 0.117+ breaks MCP tool calls. A known bug: when calling MCP tools via codex exec, the sandbox blocks the request. The solution is the --dangerously-bypass-approvals-and-sandbox flag. Without it, PMB and Context7 are dead.

On macOS, there's another surprise. The Codex binary is signed by OpenAI, and macOS blocks the execution. Solution: codesign --force --sign - <binary>. You have to re-sign after every update. But we don't update—0.116.0 works, 0.117+ breaks MCP.

apply_patch and sed. Codex has a built-in apply_patch—a precision tool for edits. In practice, qwen3-coder:30b sometimes got scared during complex refactoring and retreated to the shell:

python3 -c "
content = open('settings.py').read()
content = content.replace('MAX_PROMPT_CHARS = 4000',
    'MAX_PROMPT_CHARS = settings.get(\"max_prompt_chars\", 4000)')
open('settings.py', 'w').write(content)
"

Escaping breaks at the second level. \" → \\\" → \\\\\". The file becomes a mess. sed 49d deletes the wrong line. SyntaxError: unexpected indent.

We added a prohibition to AGENTS.md: "DO NOT use sed and perl -i." But the model would read it, agree, and then in the next move, descend into shell chaos again. 30B parameters aren't enough to stably maintain the apply_patch format under stress.

It turned out the problem wasn't the model size, but the prompt language. Translating prompts to English had a different effect: the model began consistently following the AGENTS.md rules, including the sed ban. During a project audit with an English prompt, Codex called record_batch to save to PMB on its own—something it had never done once with Russian prompts. The reason is simple: qwen3-coder is trained on an English corpus, and Russian prompts lose meaning during tokenization. The model isn't "glitching"—it doesn't understand the request language.

Detail Hallucinations. qwen3-coder confidently invents methods that don't exist. Function parameters that aren't in the API. Imports from modules that work differently. Context7 removes some of this, but not all.

AGENTS.md: An Operating System for the Coder

Without AGENTS.md, Codex hallucinates the project structure. It puts files in the wrong places. It violates conventions. It doesn't know how to test.

AGENTS.md is a file in the root of every project. Structure, stack, test commands, architecture, prohibitions, and where to put new things. Codex reads it at startup.

Contents:

  • Project stack (FastAPI, SQLite, Pydantic)
  • Test commands (pytest -x)
  • Architecture (modules, dependencies)
  • Prohibitions (do not use sed, do not hardcode)
  • Where to put new files (folders, conventions)

The key feature is verification. The line "after editing, run pytest -x" forces Codex to check its work. Without this, it edits and leaves, leaving broken tests behind.

The Self-Correction Loop: Cloud Teaches Local

I have:

  • A local coder who codes but sometimes slips up
  • A cloud coordinator who doesn't code but sees the errors
  • PMB—the database that links them

The mechanics:

  1. Codex receives a task → executes → fails (SyntaxError, duplicate)
  2. Lisa sees the error traceback
  3. Lisa analyzes: "qwen3 used sed → line duplication"
  4. Lisa records a lesson in PMB:
{
  "type": "lesson",
  "content": "Anti-pattern: using sed for Python edits. It doesn't understand indentation and duplicates lines. Pattern: use apply_patch or edit with precise oldText/newText.",
  "project": "content-pipeline"
}
  1. On the next run, Codex calls pmb__find_lessons(query="edit python file") → PMB returns the lesson
  2. The lesson is injected into the Codex prompt with high priority

This isn't fine-tuning. It's not RLHF. It's a specific rule for a specific class of tasks. One failure → one entry → the next attempt uses the correct tool.

It's too early for statistics—the stack has only been running for a few days. But the mechanism works: error → lesson → fix in one cycle.

Proof of Engine Maturity

Two products are running in real production on the same custom core (I/O engine, embeddings, dialogue manager).

Viveksha-Solo — a B2B sales manager for a large post-production company. Connected to Bitrix24. It accepts requests in Telegram and guides the dialogue through the funnel. It handles "too expensive" objections with downselling. It creates leads in the CRM. It sells to real clients without an operator.

news.viveksha.ru — an autonomous media outlet. A fully automated pipeline: RSS → LLM filter (GLM-5.2) → embedding clustering → digest synthesis → publication in Grav CMS. A cron job triggers the pipeline, and six minutes later, a new piece of content is on the site.

Both products were written by Lisa (GLM-5.2)—without Codex, because we installed Codex later. The memory back then was Owl—a homemade crutch based on SQLite + FTS5: session indexing, full-text search, facts, and decisions. The orchestration (OpenClaw) and LLM circuit are the same. PMB came later as a replacement for the homemade owl—and Codex is the evolution: moving from "cloud codes itself" to "cloud coordinates, local codes."

Levels: Junior → Senior

This scheme works on two levels.

Junior Level: a local 30B model on 24 GB VRAM. Free. It handles simple and medium tasks. It slips up on complex regex edits. It requires Lisa's supervision.

Senior Level: the same architecture, but instead of qwen3-coder:30b, a cloud model (Claude, GPT-5) is used. PMB, Context7, and AGENTS.md remain. The separation of circuits is preserved: one process coordinates, another codes.

The architecture is model-independent. Swap qwen3-coder for Claude, and you get a senior for cloud tokens. Swap back to qwen3, and you get a junior for free.

Final Tally

Problem Solution
Context Inflation Coordinator doesn't see code—only a text map
Loss in the Middle Coder has its own 96K context, doesn't share window with coordinator
Token Cost Routine on local model, cloud for coordination
Library Hallucinations Context7 MCP—fresh docs, 0 tokens
Model forgets project PMB—facts, lessons, goals in SQLite
Model doesn't know structure AGENTS.md—operating system for the coder
Memory kills coordinator Different access: Codex = full, Lisa = on-request only

What works:

  • GLM-5.2 as coordinator—cheap, doesn't touch the code
  • qwen3-coder:30b as executor—free, 96K context
  • PMB as the link—lessons, facts, memory
  • Context7—fresh docs, zero tokens
  • AGENTS.md—structure and rules

What doesn't work:

  • Codex version 0.117+—breaks MCP (fixed by pinning to 0.116.0)

What stopped breaking after switching to English prompts:

  • apply_patch on 30B—breaks under stress, model retreats to sed — English prompts + AGENTS.md rule solved this
  • Prohibitions in AGENTS.md—model reads but doesn't always obey — consistently obeys with English prompts

Verified in the first day:

  • qwen3-coder with stable rules in PMB and AGENTS.md in English—maintains format, calls MCP tools, doesn't retreat to sed
  • Project audit with an English prompt: 12 problems found, Codex recorded them in PMB via record_batch on its own (with Russian: 5 problems and no recording)
  • For stable apply_patch, moving to 32B+ is not necessary—30B with a "warmed-up" PMB handles it

I'm not claiming this is a silver bullet. I'm claiming that the hybrid scheme is a viable approach that solves real vibe coding problems. And it costs zero rubles in cloud tokens for routine work.

Related Materials