<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>whysooraj&#x27;s Portfolio - gemini</title>
    <subtitle>Portfolio showcasing projects and research.</subtitle>
    <link rel="self" type="application/atom+xml" href="https://blog.sooraj.fun/tags/gemini/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://blog.sooraj.fun/"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2024-07-04T00:00:00+00:00</updated>
    <id>https://blog.sooraj.fun/tags/gemini/atom.xml</id>
    <entry xml:lang="en">
        <title>How I Got Claude Code Running on My Gemini Subscription (Without Any API Keys)</title>
        <published>2024-07-04T00:00:00+00:00</published>
        <updated>2024-07-04T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blog.sooraj.fun/blog/codeweaver-launch/"/>
        <id>https://blog.sooraj.fun/blog/codeweaver-launch/</id>
        
        <content type="html" xml:base="https://blog.sooraj.fun/blog/codeweaver-launch/">&lt;p&gt;&lt;strong&gt;TL;DR:&lt;&#x2F;strong&gt; I built a lightweight local proxy called &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;whysooraj&#x2F;CodeWeaver&quot;&gt;CodeWeaver&lt;&#x2F;a&gt; that translates Claude Code&#x27;s Anthropic API calls into Google Cloud Code Assist requests — using your existing Gemini CLI OAuth session. Zero dependencies, one file, ~500 lines.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;the-problem&quot;&gt;The Problem&lt;&#x2F;h2&gt;
&lt;p&gt;If you&#x27;re a developer working with AI coding agents, you&#x27;ve probably noticed a split in the ecosystem:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Claude Code&lt;&#x2F;strong&gt; has arguably the best UX among AI coding CLIs — great streaming, tool use, multi-turn conversations, and a polished workflow.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Gemini CLI&lt;&#x2F;strong&gt; comes bundled with your Google account and doesn&#x27;t require managing API keys, but the CLI experience is different.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;I found myself wanting the Claude Code interface with my Gemini subscription. Paying for two AI subscriptions felt wasteful, and setting up API keys for every tool was a pain.&lt;&#x2F;p&gt;
&lt;p&gt;So I built a bridge.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-architecture&quot;&gt;The Architecture&lt;&#x2F;h2&gt;
&lt;p&gt;CodeWeaver is a local HTTP proxy that sits between Claude Code and Google&#x27;s APIs:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;Claude Code ──&amp;gt; Anthropic API request ──&amp;gt; CodeWeaver ──&amp;gt; Gemini Request ──&amp;gt; Google
                                                                                │
Claude Code &amp;lt;── Anthropic response &amp;lt;── CodeWeaver &amp;lt;── Gemini Response &amp;lt;────────┘
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It&#x27;s a single Node.js file using only native modules (&lt;code&gt;http&lt;&#x2F;code&gt;, &lt;code&gt;fs&lt;&#x2F;code&gt;, &lt;code&gt;path&lt;&#x2F;code&gt;, &lt;code&gt;crypto&lt;&#x2F;code&gt;) — zero npm dependencies. It runs on localhost:8099 and speaks the Anthropic Messages API on one side and the Google Cloud Code Assist streaming API on the other.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;how-protocol-translation-works&quot;&gt;How Protocol Translation Works&lt;&#x2F;h2&gt;
&lt;p&gt;This was the most interesting part. Claude Code and Gemini have different API shapes, and bridging them required handling several translation layers:&lt;&#x2F;p&gt;
&lt;h3 id=&quot;1-message-role-mapping&quot;&gt;1. Message Role Mapping&lt;&#x2F;h3&gt;
&lt;p&gt;Anthropic uses &lt;code&gt;&quot;user&quot;&lt;&#x2F;code&gt; &#x2F; &lt;code&gt;&quot;assistant&quot;&lt;&#x2F;code&gt; roles, while Gemini uses &lt;code&gt;&quot;user&quot;&lt;&#x2F;code&gt; &#x2F; &lt;code&gt;&quot;model&quot;&lt;&#x2F;code&gt;. Simple enough. The tricky part was handling tool interactions.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2-tool-use-function-calling&quot;&gt;2. Tool Use ↔ Function Calling&lt;&#x2F;h3&gt;
&lt;p&gt;When Claude Code calls a tool, it sends a &lt;code&gt;tool_use&lt;&#x2F;code&gt; content block. CodeWeaver translates this into Gemini&#x27;s &lt;code&gt;functionCall&lt;&#x2F;code&gt; format:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;Anthropic:            Gemini:
tool_use block  ──&amp;gt;  functionCall { name, args }
tool_result     ──&amp;gt;  functionResponse { name, response }
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The trickiest bit was preserving the &lt;strong&gt;thought signature&lt;&#x2F;strong&gt; — Gemini 3 models include a cryptographic signature in tool responses for security. CodeWeaver encodes this inside the tool_use ID with a custom encoding scheme (&lt;code&gt;toolu_{name}_{random}_sig_{sig}&lt;&#x2F;code&gt;) and decodes it on the way back.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;3-schema-sanitization&quot;&gt;3. Schema Sanitization&lt;&#x2F;h3&gt;
&lt;p&gt;This was the biggest gotcha. Claude Code sends OpenAPI 3.1-style tool schemas with keywords like &lt;code&gt;$schema&lt;&#x2F;code&gt;, &lt;code&gt;anyOf&lt;&#x2F;code&gt;, &lt;code&gt;oneOf&lt;&#x2F;code&gt;, &lt;code&gt;const&lt;&#x2F;code&gt;, and &lt;code&gt;exclusiveMinimum&lt;&#x2F;code&gt;. Google&#x27;s API strictly rejects these.&lt;&#x2F;p&gt;
&lt;p&gt;CodeWeaver&#x27;s &lt;code&gt;sanitizeSchema()&lt;&#x2F;code&gt; function strips unsupported keywords, flattens &lt;code&gt;anyOf&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;oneOf&lt;&#x2F;code&gt; into their typed variant, and converts &lt;code&gt;const&lt;&#x2F;code&gt; to &lt;code&gt;enum&lt;&#x2F;code&gt; arrays — all while preserving the actual type structure.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;4-streaming-response-translation&quot;&gt;4. Streaming Response Translation&lt;&#x2F;h3&gt;
&lt;p&gt;Claude Code expects Server-Sent Events (SSE) with a specific event structure:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;event: message_start
event: content_block_start
event: content_block_delta    (text_delta &amp;#x2F; input_json_delta)
event: content_block_stop
event: message_delta
event: message_stop
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Google sends a different SSE format. CodeWeaver maintains state about the current active content block (text vs. tool_use) and translates Google&#x27;s stream chunks into the Anthropic event sequence on the fly.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;authentication-the-best-part&quot;&gt;Authentication: The Best Part&lt;&#x2F;h2&gt;
&lt;p&gt;No API keys. No &lt;code&gt;.env&lt;&#x2F;code&gt; files. No vertex AI setup.&lt;&#x2F;p&gt;
&lt;p&gt;CodeWeaver reuses the OAuth credentials from your existing Gemini CLI session. When you run &lt;code&gt;codeweaver --login&lt;&#x2F;code&gt;, it:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Spins up a local callback server on port 8085&lt;&#x2F;li&gt;
&lt;li&gt;Opens a Google OAuth consent screen (PKCE flow)&lt;&#x2F;li&gt;
&lt;li&gt;Exchanges the authorization code for access + refresh tokens&lt;&#x2F;li&gt;
&lt;li&gt;Optionally provisions a free-tier Cloud Code Assist project&lt;&#x2F;li&gt;
&lt;li&gt;Stores credentials locally&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;After that, it handles token refresh transparently — keeping your session alive without any manual intervention.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;rate-limiting-and-fallbacks&quot;&gt;Rate Limiting and Fallbacks&lt;&#x2F;h2&gt;
&lt;p&gt;Google&#x27;s Cloud Code Assist has strict per-minute quotas on Pro models. CodeWeaver handles this with a self-healing fallback:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;If a Pro model (&lt;code&gt;gemini-2.5-pro&lt;&#x2F;code&gt;) hits a 429, the proxy transparently retries with &lt;code&gt;gemini-2.5-flash&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;If the Flash model also hits limits, it parses the retry-after duration and waits&lt;&#x2F;li&gt;
&lt;li&gt;Up to 3 retry attempts before giving up&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This means your Claude Code session rarely fails — it just gracefully degrades to a faster (but still capable) model when traffic is high.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;model-mapping&quot;&gt;Model Mapping&lt;&#x2F;h2&gt;
&lt;p&gt;Claude Code has a hard-coded model selector. CodeWeaver maps those to their Gemini equivalents:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Claude Code Model&lt;&#x2F;th&gt;&lt;th&gt;Gemini Model&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Sonnet (default)&lt;&#x2F;td&gt;&lt;td&gt;gemini-2.5-pro&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Haiku&lt;&#x2F;td&gt;&lt;td&gt;gemini-2.5-flash&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Opus&lt;&#x2F;td&gt;&lt;td&gt;gemini-3.1-pro-preview&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Fable&lt;&#x2F;td&gt;&lt;td&gt;gemini-3.1-flash-lite&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;You can also pass raw Gemini model IDs directly: &lt;code&gt;claude --model gemini-3.1-pro-preview&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-result-500-lines-zero-dependencies&quot;&gt;The Result: 500 Lines, Zero Dependencies&lt;&#x2F;h2&gt;
&lt;p&gt;The entire proxy is a single &lt;code&gt;proxy.js&lt;&#x2F;code&gt; file. Here&#x27;s the breakdown:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;~80 lines&lt;&#x2F;strong&gt; — OAuth login flow with PKCE&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;~60 lines&lt;&#x2F;strong&gt; — Schema sanitization&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;~120 lines&lt;&#x2F;strong&gt; — Request translation (Anthropic → Gemini)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;~200 lines&lt;&#x2F;strong&gt; — HTTP server + streaming response handling&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;~40 lines&lt;&#x2F;strong&gt; — Token management and config&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Total: ~500 lines of vanilla Node.js. No TypeScript, no frameworks, no npm packages.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-s-next&quot;&gt;What&#x27;s Next&lt;&#x2F;h2&gt;
&lt;p&gt;CodeWeaver is intentionally focused on the Gemini → Claude bridge right now. But the roadmap aims for something bigger:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Plugin architecture&lt;&#x2F;strong&gt; — provider-agnostic backend swapping&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Ollama support&lt;&#x2F;strong&gt; — run Claude Code against local models&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;OpenAI &#x2F; DeepSeek &#x2F; OpenRouter&lt;&#x2F;strong&gt; — any API-compatible provider&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Auto failover&lt;&#x2F;strong&gt; — cascade through providers on rate limits or outages&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Docker image&lt;&#x2F;strong&gt; — containerized deployment&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Web dashboard&lt;&#x2F;strong&gt; — visual provider configuration&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The vision is to make Claude Code a universal frontend for any AI model backend.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;try-it&quot;&gt;Try It&lt;&#x2F;h2&gt;
&lt;pre data-lang=&quot;bash&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;curl -fsSL https:&amp;#x2F;&amp;#x2F;raw.githubusercontent.com&amp;#x2F;whysooraj&amp;#x2F;CodeWeaver&amp;#x2F;main&amp;#x2F;claude-gemini-proxy&amp;#x2F;install.sh | bash
codeweaver --login
codeweaver
claude
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Or clone and run manually:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;git clone https:&amp;#x2F;&amp;#x2F;github.com&amp;#x2F;whysooraj&amp;#x2F;CodeWeaver.git
cd CodeWeaver&amp;#x2F;claude-gemini-proxy
node proxy.js --login
node proxy.js
claude
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Requirements:&lt;&#x2F;strong&gt; Node.js 18+, a Google account, and the Gemini CLI.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;em&gt;CodeWeaver is open source under MIT. Contributions, issues, and feature requests are welcome!&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Links:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;GitHub: &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;whysooraj&#x2F;CodeWeaver&quot;&gt;github.com&#x2F;whysooraj&#x2F;CodeWeaver&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Install: One-liner above or clone the repo&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;em&gt;Have questions? Found a bug? Want another provider supported? Let me know in the comments or open an issue on GitHub.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
</feed>
