spacehub

surshar / claude-code

Claude Code is an agentic coding tool that lives in your terminal, understands your codebase, and helps you code faster by executing routine tasks, explaining complex code, and handling git workflows - all through natural language commands.

Built by Anthropic · github.com/anthropics

docs: add best practices for robust apiKeyHelper scriptsBrowse files
Add comprehensive guidance for writing reliable helper scripts that avoid
infinite retry loops when VPN or network-dependent credential helpers fail.

Includes:
- TTL configuration documentation (CLAUDE_CODE_API_KEY_HELPER_TTL_MS)
- Timeout best practices for network operations
- VPN-aware connectivity checks
- Local token caching patterns
- Troubleshooting guide for common issues

Addresses feedback from New Relic about apiKeyHelper retry loop behavior.
Claude authored on Dec 20, 2025 parent d213a74 · commit e9e5f0c53dcd
1 changed file+133 -0compared with d213a74
Mplugins/plugin-dev/skills/mcp-integration/references/authentication.md
@@ -264,6 +264,139 @@
264264 - Time-based authentication
265265 - Dynamic tenant/workspace selection
266266
267+### TTL Configuration
268+
269+By default, dynamically generated API keys are cached for 5 minutes. Configure the TTL with:
270+
271+```bash
272+export CLAUDE_CODE_API_KEY_HELPER_TTL_MS=300000 # 5 minutes (default)
273+```
274+
275+### Writing Robust Helper Scripts
276+
277+Helper scripts can cause issues if they hang or fail repeatedly. Follow these best practices to prevent infinite retry loops and connection hangs:
278+
279+**1. Always set timeouts on network operations:**
280+```bash
281+#!/bin/bash
282+# get-token.sh - Robust token fetcher
283+
284+# Set a timeout for the entire script
285+TIMEOUT_SECONDS=10
286+
287+# Use timeout for network calls
288+TOKEN=$(timeout ${TIMEOUT_SECONDS}s curl -s --max-time ${TIMEOUT_SECONDS} \
289+ "https://auth.example.com/token" 2>/dev/null)
290+
291+if [ -z "$TOKEN" ] || [ "$TOKEN" = "null" ]; then
292+ # Exit with error - don't output invalid JSON
293+ echo "Failed to fetch token" >&2
294+ exit 1
295+fi
296+
297+echo "{\"Authorization\": \"Bearer $TOKEN\"}"
298+```
299+
300+**2. Handle VPN/network dependency failures:**
301+```bash
302+#!/bin/bash
303+# get-headers.sh - VPN-aware token fetcher
304+
305+# Quick connectivity check before attempting auth
306+if ! timeout 2s ping -c 1 vpn-dependent-service.internal >/dev/null 2>&1; then
307+ echo "VPN not connected or service unreachable" >&2
308+ exit 1
309+fi
310+
311+# Proceed with token fetch (with timeout)
312+TOKEN=$(timeout 10s get-token-from-vpn-service)
313+
314+if [ $? -ne 0 ] || [ -z "$TOKEN" ]; then
315+ echo "Token fetch failed" >&2
316+ exit 1
317+fi
318+
319+echo "{\"Authorization\": \"Bearer $TOKEN\"}"
320+```
321+
322+**3. Cache tokens locally to reduce network calls:**
323+```bash
324+#!/bin/bash
325+# get-headers-cached.sh - Token fetcher with local caching
326+
327+CACHE_FILE="${HOME}/.cache/my-api-token"
328+CACHE_MAX_AGE=240 # seconds (refresh before 5min TTL)
329+
330+# Check cache validity
331+if [ -f "$CACHE_FILE" ]; then
332+ CACHE_AGE=$(($(date +%s) - $(stat -c %Y "$CACHE_FILE" 2>/dev/null || stat -f %m "$CACHE_FILE")))
333+ if [ "$CACHE_AGE" -lt "$CACHE_MAX_AGE" ]; then
334+ cat "$CACHE_FILE"
335+ exit 0
336+ fi
337+fi
338+
339+# Fetch new token with timeout
340+TOKEN=$(timeout 10s fetch-new-token 2>/dev/null)
341+
342+if [ -z "$TOKEN" ]; then
343+ # If fetch fails, try to use expired cache as fallback
344+ if [ -f "$CACHE_FILE" ]; then
345+ echo "Warning: Using expired cached token" >&2
346+ cat "$CACHE_FILE"
347+ exit 0
348+ fi
349+ echo "Failed to fetch token and no cache available" >&2
350+ exit 1
351+fi
352+
353+# Update cache
354+mkdir -p "$(dirname "$CACHE_FILE")"
355+echo "{\"Authorization\": \"Bearer $TOKEN\"}" > "$CACHE_FILE"
356+cat "$CACHE_FILE"
357+```
358+
359+**4. Fail fast with clear error messages:**
360+```bash
361+#!/bin/bash
362+set -e # Exit on any error
363+
364+# Check prerequisites before attempting network calls
365+if [ -z "$API_SECRET" ]; then
366+ echo "API_SECRET environment variable not set" >&2
367+ exit 1
368+fi
369+
370+# Use short timeouts to fail fast
371+TOKEN=$(timeout 5s curl -sf --max-time 5 \
372+ -H "X-Secret: $API_SECRET" \
373+ "https://auth.example.com/token") || {
374+ echo "Token request failed or timed out" >&2
375+ exit 1
376+}
377+
378+echo "{\"Authorization\": \"Bearer $TOKEN\"}"
379+```
380+
381+### Troubleshooting Helper Scripts
382+
383+**Infinite retry loop / hanging:**
384+- Add timeouts to all network operations
385+- Use `set -e` to exit on errors
386+- Check VPN/network connectivity before making requests
387+- Ensure script outputs valid JSON or exits with error code
388+
389+**Script takes too long:**
390+- Use `timeout` command wrapper
391+- Set `--max-time` on curl requests
392+- Consider caching tokens locally
393+- Reduce TTL if tokens refresh too slowly
394+
395+**VPN-dependent helpers failing:**
396+- Add connectivity check at start of script
397+- Implement graceful degradation with cached tokens
398+- Log clear error messages to stderr
399+
267400 ## Security Best Practices
268401
269402 ### DO