Skip to content

AI Agents Integration Guide

Pre-installed AI agents in Docker development environment - Complete guide to using Claude Code and Gemini CLI.


Table of Contents


Overview

What Are AI Agents?

AI Agents are command-line tools that provide AI assistance directly in your development environment:

  • Claude Code: Anthropic's AI coding assistant (version 2.0.76)
  • Gemini CLI: Google's AI assistant (version 0.22.2)

Both are pre-installed in the my-dev-env:latest Docker image, so you don't need to install them every time.

Key Benefits

  • Pre-installed: No installation time, ready immediately
  • Secure: API keys loaded from Infisical at runtime
  • Multiple Identities: Switch between personal/edu/work accounts
  • Isolated: Agents run in container, can't access host secrets
  • Consistent: Same tools, same versions across all machines

Architecture

The Three-Layer Model

┌─────────────────────────────────────────────────────┐
│                   HOST (Server)                      │
│  ┌────────────────────────────────────────────────┐ │
│  │ Infisical (secrets.kua.cl)                     │ │
│  │ - ANTHROPIC_API_KEY                            │ │
│  │ - GOOGLE_API_KEY                               │ │
│  │                                                 │ │
│  │ dev() fetches → /tmp/env-$$.list               │ │
│  └────────────────────────────────────────────────┘ │
│                                                      │
│  ┌────────────────────────────────────────────────┐ │
│  │ AI Account Files (Host Storage)                │ │
│  │ ~/.gemini/oauth-edu1.json                      │ │
│  │ ~/.claude/session-personal.json                │ │
│  │ ~/.openai/session-chatgpt.json                 │ │
│  └────────────────────────────────────────────────┘ │
└──────────────────┬───────────────────────────────────┘
                   │ Docker run --env-file + -v mounts
┌─────────────────────────────────────────────────────┐
│          CONTAINER (my-dev-env:latest)               │
│  ┌────────────────────────────────────────────────┐ │
│  │ Pre-installed Tools (Baked into Image)         │ │
│  │ ✅ Claude Code 2.0.76                           │ │
│  │ ✅ Gemini CLI 0.22.2                            │ │
│  │ ❌ NO secrets baked in                          │ │
│  └────────────────────────────────────────────────┘ │
│                                                      │
│  ┌────────────────────────────────────────────────┐ │
│  │ Runtime-Injected (via dev())                   │ │
│  │ Environment Variables:                          │ │
│  │   ANTHROPIC_API_KEY=sk-ant-...                 │ │
│  │   GOOGLE_API_KEY=AIza...                       │ │
│  │                                                 │ │
│  │ Mounted Files (read-only):                     │ │
│  │   /root/.gemini/oauth_creds.json               │ │
│  │   /root/.config/claude/config.json             │ │
│  │   /root/.openai/session.json                   │ │
│  └────────────────────────────────────────────────┘ │
│                                                      │
│  ┌────────────────────────────────────────────────┐ │
│  │ Usage                                           │ │
│  │ $ claude                                        │ │
│  │   → Uses ANTHROPIC_API_KEY from env            │ │
│  │   → Uses session from config.json              │ │
│  │                                                 │ │
│  │ $ gemini                                        │ │
│  │   → Uses GOOGLE_API_KEY from env               │ │
│  │   → Uses OAuth from oauth_creds.json           │ │
│  └────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────┘

Why This Architecture?

Tools in Image, Credentials on Host

  • Security: No secrets baked into Docker image
  • Flexibility: Switch identities without rebuilding image
  • Portability: Same image works across all machines
  • Updates: Update secrets without touching Docker image

Pre-Installed Agents

Claude Code 2.0.76

What it does: AI-powered code assistant from Anthropic

Installation in image:

RUN npm install -g @anthropic-ai/claude-code@2.0.76

Version pinned: Yes (2.0.76) - ensures consistency

Command: claude

Requires: - ANTHROPIC_API_KEY environment variable - Optional: Session file at /root/.config/claude/config.json

Features: - Code generation and editing - Multi-file operations - Git integration - Terminal access - File system operations

Gemini CLI 0.22.2

What it does: AI assistant from Google

Installation in image:

RUN npm install -g @google/gemini-cli@0.22.2

Version pinned: Yes (0.22.2) - ensures consistency

Command: gemini

Requires: - GOOGLE_API_KEY environment variable - OAuth credentials file at /root/.gemini/oauth_creds.json

Features: - Conversational AI assistance - Code analysis and generation - Multi-turn conversations - File operations

Why Pre-Install?

Without pre-installation (old approach):

# Inside container every time
npm install -g @anthropic-ai/claude-code  # 30-60 seconds
npm install -g @google/gemini-cli         # 30-60 seconds
# Total: 1-2 minutes wasted every session

With pre-installation (current approach):

# Tools already there, ready immediately
claude --version  # Works instantly
gemini --version  # Works instantly

Benefits: - ⚡ Instant startup - 🔒 Version consistency (no unexpected updates) - 📦 Smaller node_modules in projects (global install) - 🚀 Faster iteration cycles


How Agents Access Secrets

Environment Variables (API Keys)

AI agents read API keys from environment variables, injected at runtime by dev():

Flow:

# On host
dev my-project

# dev() function does:
infisical export --env=dev --projectId=personal-vault > /tmp/env-$$.list

# File contains:
# ANTHROPIC_API_KEY=sk-ant-api03-...
# GOOGLE_API_KEY=AIza...

# Docker launch:
docker run --env-file /tmp/env-$$.list ...

# Inside container:
$ env | grep API_KEY
ANTHROPIC_API_KEY=sk-ant-api03-...
GOOGLE_API_KEY=AIza...

$ claude
# Claude reads ANTHROPIC_API_KEY automatically

$ gemini
# Gemini reads GOOGLE_API_KEY automatically

Key insight: Agents NEVER ask for API keys - they expect them in the environment.

Session Files (OAuth/State)

Some agents need additional session/OAuth files for authentication:

Gemini OAuth:

# Host: ~/.gemini/oauth-edu1.json
# Container: /root/.gemini/oauth_creds.json (read-only mount)

docker run -v ~/.gemini/oauth-edu1.json:/root/.gemini/oauth_creds.json:ro ...

Claude Session:

# Host: ~/.claude/session-personal.json
# Container: /root/.config/claude/config.json (read-only mount)

docker run -v ~/.claude/session-personal.json:/root/.config/claude/config.json:ro ...

OpenAI Session:

# Host: ~/.openai/session-chatgpt.json
# Container: /root/.openai/session.json (read-only mount)

docker run -v ~/.openai/session-chatgpt.json:/root/.openai/session.json:ro ...

Why read-only (:ro)? - Agents can't modify host credentials - Prevents accidental corruption - Security best practice


Multiple Identity Management

The Problem

You may have multiple AI accounts: - Personal: Your own accounts - Educational: University/school accounts (edu1, edu2, edu3, edu4) - Work: Employer-provided accounts

Challenge: How to switch between them?

The Solution: File-Based Identity Switching

Strategy: Store each identity's credentials in separate files on the host, mount the desired one at runtime.

Directory Structure

~/.gemini/
├── oauth-edu1.json      # Education account 1
├── oauth-edu2.json      # Education account 2
├── oauth-edu3.json      # Education account 3
└── oauth-edu4.json      # Education account 4

~/.claude/
├── session-personal.json  # Personal account
├── session-edu1.json      # Education account 1
├── session-edu2.json      # Education account 2
└── session-work.json      # Work account

~/.openai/
├── session-chatgpt.json   # Personal ChatGPT
├── session-edu1.json      # Education account 1
├── session-edu2.json      # Education account 2
└── session-work.json      # Work account

How dev() Handles Selection

The dev() function prompts you to select which identity to use:

Gemini Account Prompt:

🤖 Select Gemini Account:
   [1] edu1 (default)
   [2] edu2
   [3] edu3
   [4] edu4
👉 Choose (1-4):

Claude Account Prompt:

🧠 Select Claude Account:
   [1] personal (default)
   [2] edu1
   [3] edu2
   [4] work
   [0] Skip (no Claude session)
👉 Choose (0-4):

OpenAI Account Prompt:

🔮 Select OpenAI/ChatGPT Account:
   [1] chatgpt (default)
   [2] edu1
   [3] edu2
   [4] work
   [0] Skip (no OpenAI session)
👉 Choose (0-4):

What happens: 1. You select an identity (e.g., 2 for edu1) 2. dev() sets OAUTH_FILE="$HOME/.gemini/oauth-edu2.json" 3. Docker mounts that specific file: -v "$OAUTH_FILE":/root/.gemini/oauth_creds.json:ro 4. Inside container, Gemini uses that identity

Benefits

  • No rebuilding: Switch identities without rebuilding Docker image
  • Isolated: Each account's credentials stored separately
  • Flexible: Mix and match (Gemini edu1 + Claude personal)
  • Auditable: Know which identity was used for which session

Integration with dev()

Complete Flow

Here's how dev() integrates AI agent selection:

Step-by-step:

  1. Project Selection:

    📂 Select a project: my-app
    

  2. Infisical Selection:

    🔐 Select Infisical project: personal-vault
    🌍 Select environment: dev
    

  3. AI Account Selection (Sequential prompts):

    🤖 Select Gemini Account: edu1
    🧠 Select Claude Account: personal
    🔮 Select OpenAI Account: skip
    

  4. Secrets Fetch:

    infisical export --env=dev --projectId=personal-vault > /tmp/env-$$.list
    

  5. Docker Launch:

    docker run --rm -it \
      --env-file /tmp/env-$$.list \
      -v ~/.gemini/oauth-edu1.json:/root/.gemini/oauth_creds.json:ro \
      -v ~/.claude/session-personal.json:/root/.config/claude/config.json:ro \
      -v ~/Coding:/app \
      -w /app/my-app \
      my-dev-env:latest /bin/bash
    

  6. Inside Container:

    # Agents ready to use
    claude
    gemini
    
    # API keys loaded
    env | grep API_KEY
    

Code Reference

See the complete dev() function implementation in dev-function.md:3


Usage Examples

Example 1: Using Claude for Code Review

# On server
dev my-app

# Prompts:
# Project: my-app
# Infisical: personal-vault / dev
# Gemini: edu1
# Claude: personal
# OpenAI: skip

# Inside container
cd /app/my-app

# Start Claude
claude

# Claude prompt
> Review the authentication logic in src/auth.js and suggest security improvements

What happens: - Claude reads ANTHROPIC_API_KEY from environment - Uses session from /root/.config/claude/config.json - Analyzes src/auth.js - Provides security recommendations

Example 2: Using Gemini for Documentation

# Inside container
gemini

# Gemini prompt
> Generate API documentation for the functions in src/api.js

What happens: - Gemini reads GOOGLE_API_KEY from environment - Uses OAuth from /root/.gemini/oauth_creds.json - Analyzes src/api.js - Generates documentation

Example 3: Switching Identities Mid-Work

Scenario: You started with personal Claude, but need to switch to work account.

Solution: Exit and re-launch with different identity:

# Inside container
exit

# Back on host
dev my-app

# This time select:
# Claude: work (instead of personal)

# Inside new container
claude
# Now using work account


The .ai-context.md Standard

What Is It?

.ai-context.md is a "Constitution" file for AI agents in your project. It defines: - Environment constraints - Security protocols - Tech stack preferences - Coding standards

Location: /app/<project>/.ai-context.md (inside container)

Why It Exists

Without .ai-context.md: - AI agents don't know project constraints - May ask for API keys (violating security protocol) - May use wrong tools or patterns - Inconsistent behavior across sessions

With .ai-context.md: - AI agents self-configure - Follow project standards - Respect security boundaries - Consistent behavior

Template

Every project should have this file:

# AI Development Environment Context

## 1. Environment & Architecture
- **Runtime:** Docker Container (Ubuntu/Debian based).
- **Filesystem:**
  - The host's `~/Coding` directory is mounted to `/app`.
  - Current Project Root: `/app/<project-name>`
- **Identity:**
  - Host `~/.gitconfig` is mounted read-only (Git identity is preserved).
  - Host `~/.ssh` is mounted read-only (SSH keys are available).

## 2. Security & Secrets Protocol
- **Secrets Manager:** Infisical is the Single Source of Truth.
- **Access Method:** Environment Variables (injected at runtime).
- **Rule:** **NEVER** ask the user for API keys, passwords, or secrets.
- **Missing Secrets:** If a required secret (e.g., `DB_PASSWORD`, `OPENAI_API_KEY`) is missing,
  instruct the user to add it to Infisical:
  ```bash
  infisical secrets set KEY_NAME="value" --env=dev --projectId=personal-vault
  ```

## 3. Tooling & Workflow
- **Node.js:** Available (version: detect with `node --version`).
- **Python:** Available (version: detect with `python --version`).
- **Docker:** Container cannot spawn sibling containers unless socket is mounted.
- **Editor:** User edits on Host (VS Code/Cursor), Agent edits inside Container (CLI).

## 4. Coding Standards
- **Style:** Adhere to existing `.eslintrc`, `.prettierrc`, or `flake8` configurations.
- **Tests:** Always run tests after modification if a test script exists.
- **Commits:** Use conventional commit format: `type(scope): message`

## 5. Project-Specific Settings
- **Language:** [Auto-detect or specify: Python, Node.js, Go, etc.]
- **Start Command:** `npm start` / `python main.py` / etc.
- **Test Command:** `npm test` / `pytest` / etc.
- **Build Command:** `npm run build` / `go build` / etc.

How to Use

Creating for new project:

# Inside container
cd /app/my-new-project
cat > .ai-context.md << 'EOF'
# AI Development Environment Context
[... paste template above ...]
EOF

AI agents will read it automatically when they: - Analyze project structure - Need to understand constraints - Make decisions about tools or patterns

Real Example

From /Users/kavi/Coding/.ai-context.md:

# AI Development Environment Context

## 1. Environment & Architecture
- **Runtime:** Docker Container (Ubuntu/Debian based).
- **Filesystem:**
  - The host's `~/Coding` directory is mounted to `/app`.
  - Current Project Root: Determined by the working directory inside `/app`.
- **Identity:**
  - Host `~/.gitconfig` is mounted read-only (Git identity is preserved).
  - Host `~/.ssh` is mounted read-only (SSH keys are available).

## 2. Security & Secrets Protocol
- **Secrets Manager:** Infisical is the Single Source of Truth.
- **Access Method:** Environment Variables (injected at runtime).
- **Rule:** **NEVER** ask the user for API keys, passwords, or secrets.

This ensures AI agents: - Know they're in a Docker container - Understand /app is the project root - NEVER ask for API keys (they're already in environment) - Know to use Infisical for missing secrets


Troubleshooting

"ANTHROPIC_API_KEY not found"

Symptom: Claude says API key is missing

Causes: 1. Secret not in Infisical 2. Wrong Infisical project/environment selected 3. dev() didn't fetch secrets properly

Solution:

# Exit container
exit

# Check Infisical has the key
infisical secrets --env=dev --projectId=personal-vault | grep ANTHROPIC_API_KEY

# If missing, add it:
infisical secrets set ANTHROPIC_API_KEY="sk-ant-..." --env=dev --projectId=personal-vault

# Re-launch
dev my-project

"OAuth file not found" (Gemini)

Symptom: Gemini fails with "oauth_creds.json not found"

Causes: 1. OAuth file doesn't exist on host 2. dev() didn't mount the file 3. Wrong account selected

Solution:

# Check file exists on host
ls -la ~/.gemini/oauth-edu1.json

# If missing, you need to authenticate that account first
# (See Multi-Identity Guide for OAuth setup)

# If file exists, re-run dev() and ensure you select the correct account

"Session expired" (Claude)

Symptom: Claude says session is invalid/expired

Cause: Session file is outdated

Solution:

# Exit container
exit

# On host, re-authenticate Claude
# (This updates the session file)

# Re-launch dev()
dev my-project

Agent installed but won't run

Symptom: claude: command not found or gemini: command not found

Cause: Docker image is outdated (doesn't have agents pre-installed)

Solution:

# Exit container
exit

# Rebuild Docker image with latest version
docker build -t my-dev-env:latest /path/to/dockerfile

# Verify agents are installed
docker run --rm my-dev-env:latest claude --version
docker run --rm my-dev-env:latest gemini --version

# Re-launch
dev my-project

Multiple identities not working

Symptom: Selected edu1 but using personal account

Cause: dev() didn't mount the correct file

Debug:

# Inside container, check which file is mounted
ls -la /root/.gemini/oauth_creds.json
ls -la /root/.config/claude/config.json

# Exit and check dev() function
exit

# Verify dev() script has correct mount logic
grep -A5 "OAUTH_FILE" ~/.zshrc  # or ~/.bashrc


Summary

AI Agents Integration: - ✅ Claude Code and Gemini CLI pre-installed in Docker image - ✅ API keys loaded from Infisical at runtime (environment variables) - ✅ Multiple identities via file-based switching (OAuth/session files) - ✅ Seamless integration with dev() function - ✅ Security via read-only mounts and no secrets in image - ✅ Consistency via .ai-context.md standard

Key Principles: 1. Tools in image, credentials on host - separation of concerns 2. Never ask for secrets - agents expect them in environment 3. Identity files on host - mount at runtime for flexibility 4. Version pinning - consistent behavior across machines 5. .ai-context.md - project-specific rules and constraints

What's Next: - Learn about Multi-Identity Management - detailed OAuth/session setup - Learn about .ai-context.md Standard - complete guide - Learn about dev() Function - how orchestration works - Learn about Docker Environment - image architecture