Problem: You want to run Clojure programs in Claude Code Web, but you're getting all sorts of errors when trying to download dependencies from Maven Central or Clojars. Maven/Gradle fails with 401 Unauthorized in Claude Code web environment
Solution: Local proxy shim that handles authentication translation
Result: ✅ All JVM builds work perfectly
My Commentary: I was in utter awe watching Claude Code Web figure this out, along with lots of hints from ChatGPT Pro.) Together, they’re like the world’s best sysadmin and networking engineer, who also happens to also know Maven Central and Clojars.
Save proxy_shim.py (from this gist) and make it executable:
mkdir -p script
# Save proxy_shim.py to script/proxy_shim.py
chmod +x script/proxy_shim.py# Save .proxy-java-shim.env to project root
# Save settings.xml to ~/.m2/settings.xml# Terminal 1: Start proxy shim
python3 script/proxy_shim.py
# Terminal 2: Run your build
. ./.proxy-java-shim.env && clojure -M:test # Clojure
. ./.proxy-java-shim.env && mvn test # Maven
. ./.proxy-java-shim.env && gradle test # Gradle| File | Purpose |
|---|---|
README.md |
This file - quick start guide |
proxy_shim.py |
The proxy shim (Python 3, no dependencies) |
.proxy-java-shim.env |
Java configuration |
settings.xml |
Maven configuration |
Makefile.snippet |
Optional automation |
Environment: Claude Code on the web (https://claude.ai/code) Symptom:
Could not transfer artifact org.clojure:clojure:pom:1.12.0
status code: 401, reason phrase: Unauthorized (401)
Cause: Claude Code's security proxy returns 401 instead of RFC 9110 compliant 407, breaking Java's HTTP client authentication.
Fix: Local proxy shim translates authentication:
Java → localhost:15080 (no auth) → Shim → Claude Proxy (JWT) → Maven Central
After setup, test with:
# 1. Start shim in background
python3 script/proxy_shim.py &
# 2. Test dependency download
. ./.proxy-java-shim.env
clojure -Sdeps '{:deps {org.clojure/data.json {:mvn/version "2.5.0"}}}' -e '(+ 1 1)'
# Expected: Downloads successfullyUse the Makefile.snippet to automate shim lifecycle:
make proxy-shim-start # Start shim
make test # Run tests
make proxy-shim-stop # Stop shim
# OR all-in-one:
make test-with-shimClaude Code's proxy violates RFC 9110 by returning 401 (origin auth) instead of 407 (proxy auth). Java's HTTP client doesn't send proxy credentials when it sees 401.
The shim sends both headers:
Proxy-Authorization: Basic <creds>(correct per RFC)Authorization: Basic <creds>(what the proxy expects)
✅ Listens on localhost only (127.0.0.1) ✅ Credentials never logged ✅ Uses standard environment variables ✅ No new security exposure (Claude Code already has credentials)
- Pure Python 3 - No dependencies
- Async I/O - Handles CONNECT tunnels correctly
- Production Ready - Tested with 97 tests, 448 assertions
- Works with: Clojure, Maven, Gradle, SBT, Leiningen
Before:
❌ status code: 401, reason phrase: Unauthorized (401)
After:
✅ Downloading: org/clojure/data.json/2.5.0/data.json-2.5.0.pom from central
✅ 97 tests, 448 assertions, 0 failures
Shim won't start: Verify $HTTPS_PROXY is set (Claude Code sets this automatically)
Still getting 401: Check Maven settings point to 127.0.0.1:15080
Shim crashes: Check /tmp/proxy-shim.log for errors
- ✅ Clojure (tools.deps)
- ✅ Maven
- ✅ Gradle
- ✅ Multiple concurrent connections
- ✅ HTTPS CONNECT tunnels
Copy all files from this gist and follow Quick Start above. Should work in < 5 minutes!