Skip to content

Instantly share code, notes, and snippets.

@floscr
Last active January 5, 2026 06:59
Show Gist options
  • Select an option

  • Save floscr/566fbecee51bbfaadb6d927ed161c58e to your computer and use it in GitHub Desktop.

Select an option

Save floscr/566fbecee51bbfaadb6d927ed161c58e to your computer and use it in GitHub Desktop.
Containerized AI agent

A containerized claude tui, to spawn claude "agents" tui in

Simply run ./run.sh . "Run ls" to spawn the agent.

# AI Agent Container - Secure isolated environment for LLM-driven code changes
FROM ubuntu:22.04
# Prevent interactive prompts during package installation
ENV DEBIAN_FRONTEND=noninteractive
# Install system dependencies and development tools
RUN apt-get update && apt-get install -y \
curl \
git \
bash \
ca-certificates \
build-essential \
jq \
&& rm -rf /var/lib/apt/lists/*
# Install Node.js 20 LTS
RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - && \
apt-get install -y nodejs && \
rm -rf /var/lib/apt/lists/*
# Install Python 3 (for projects that need it)
RUN apt-get update && apt-get install -y \
python3 \
python3-pip \
&& rm -rf /var/lib/apt/lists/*
# Install Claude Code CLI via npm
RUN npm install -g @anthropic-ai/claude-code
# Create non-root user for security
RUN useradd -m -s /bin/bash -u 1000 llmuser
# Add Claude Agent node script
COPY claude-agent.mjs /usr/local/bin/claude-agent.mjs
RUN chmod +x /usr/local/bin/claude-agent.mjs
# Security: run as non-root user
USER llmuser
# Set working directory
WORKDIR /workspace
# Default entrypoint - run Claude directly
ENTRYPOINT ["claude", "--dangerously-skip-permissions"]
{
"mcpServers": {
"chrome-devtools": {
"command": "npx",
"args": [
"-y",
"chrome-devtools-mcp",
"--browserUrl",
"http://host.docker.internal:9222"
]
}
}
}
#!/usr/bin/env bash
# AI Agent - Secure container-based autonomous code modification
set -e
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Helper functions
info() {
echo -e "${GREEN}✓${NC} $1"
}
warn() {
echo -e "${YELLOW}⚠${NC} $1"
}
error() {
echo -e "${RED}✗${NC} $1"
}
# Find the script directory
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd)"
# Parse arguments
show_help() {
cat << EOF
AI Agent - Secure container-based autonomous code modification
Usage:
ai_agent <directory> <prompt>
ai_agent [options]
Arguments:
<directory> Target directory (default: current directory)
<prompt> Task prompt for Claude
Options:
-h, --help Show this help message
--memory SIZE Memory limit (default: 4g)
--cpus NUM CPU limit (default: 2)
--rebuild Force rebuild the container image
Examples:
ai_agent . "Add error handling to all API endpoints"
ai_agent ~/Code/MyProject "Refactor database layer"
ai_agent --memory 8g . "Add comprehensive tests"
Prerequisites:
1. Docker installed and running
2. Authentication: ai_auth login <profile>
EOF
}
# Default values
MEMORY="4g"
CPUS="2"
REBUILD=false
TARGET_DIR=""
PROMPT=""
# Parse options
while [[ $# -gt 0 ]]; do
case $1 in
-h|--help)
show_help
exit 0
;;
--memory)
MEMORY="$2"
shift 2
;;
--cpus)
CPUS="$2"
shift 2
;;
--rebuild)
REBUILD=true
shift
;;
*)
if [ -z "$TARGET_DIR" ]; then
TARGET_DIR="$1"
else
# Everything else is part of the prompt
PROMPT="$PROMPT $1"
fi
shift
;;
esac
done
# Trim whitespace from prompt
PROMPT=$(echo "$PROMPT" | xargs)
# Validate arguments
if [ -z "$TARGET_DIR" ]; then
error "No target directory specified"
echo ""
show_help
exit 1
fi
if [ -z "$PROMPT" ]; then
error "No prompt specified"
echo ""
show_help
exit 1
fi
# Resolve absolute path
TARGET_DIR=$(cd "$TARGET_DIR" && pwd)
# Verify directory exists
if [ ! -d "$TARGET_DIR" ]; then
error "Directory not found: $TARGET_DIR"
exit 1
fi
# Find git root if we're in a git repository
GIT_ROOT="$TARGET_DIR"
if [ -d "$TARGET_DIR/.git" ]; then
GIT_ROOT="$TARGET_DIR"
else
# Try to find git root from target directory
cd "$TARGET_DIR"
if git rev-parse --git-dir > /dev/null 2>&1; then
GIT_ROOT=$(git rev-parse --show-toplevel)
info "Found git root: $GIT_ROOT"
fi
cd - > /dev/null
fi
echo ""
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo -e "${BLUE}🤖 AI Agent - Autonomous Code Modification${NC}"
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo ""
info "Working directory: $GIT_ROOT"
if [ "$GIT_ROOT" != "$TARGET_DIR" ]; then
info "Target directory: $TARGET_DIR"
fi
info "Prompt: $PROMPT"
echo ""
# Get authentication from ai_auth
echo "Fetching authentication..."
AUTH_TOKEN=$(bb -cp "$PROJECT_ROOT/src" -e "(require '[common.auth.profiles :as p]) (let [auth (p/get-current-auth)] (or (:session-key auth) (:api-key auth)))" 2>/dev/null)
if [ -z "$AUTH_TOKEN" ] || [ "$AUTH_TOKEN" = "nil" ]; then
error "No authentication found"
echo "Run: ai_auth login <profile>"
exit 1
fi
info "Authentication found"
echo ""
# Check if git repo exists
if [ -d "$GIT_ROOT/.git" ] || (cd "$GIT_ROOT" && git rev-parse --git-dir > /dev/null 2>&1); then
info "Git repository detected"
# Check for uncommitted changes
cd "$GIT_ROOT"
if ! git diff-index --quiet HEAD -- 2>/dev/null; then
warn "Uncommitted changes detected"
echo " Consider committing before running"
fi
cd - > /dev/null
else
warn "Not a git repository - changes won't be tracked"
fi
echo ""
# Build or rebuild container image
IMAGE_NAME="ai-agent:latest"
if [ "$REBUILD" = true ] || ! docker images | grep -q "ai-agent"; then
echo "Building container image..."
docker build -t "$IMAGE_NAME" -f "$SCRIPT_DIR/Dockerfile" "$SCRIPT_DIR"
info "Container image ready"
echo ""
fi
# Check for AGENTS.md at git root and prepend instruction to read it
if [ -f "$GIT_ROOT/AGENTS.md" ]; then
info "Found AGENTS.md - instructing Claude to read it"
PROMPT="Read and follow the instructions in AGENTS.md first, then: $PROMPT"
fi
# Run container
echo "Launching container..."
echo ""
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo ""
docker run --rm \
-it \
-v "$GIT_ROOT:/workspace" \
-v "$HOME/.claude:/home/llmuser/.claude" \
-v "$HOME/.claude.json:/home/llmuser/.claude.json" \
-v "$SCRIPT_DIR/mcp-config.json:/home/llmuser/.claude/mcp-config.json:ro" \
-e "CLAUDE_SESSION_KEY=$AUTH_TOKEN" \
--memory "$MEMORY" \
--cpus "$CPUS" \
--user llmuser \
--add-host=host.docker.internal:host-gateway \
"$IMAGE_NAME" \
"$PROMPT"
EXIT_CODE=$?
echo ""
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo ""
if [ $EXIT_CODE -eq 0 ]; then
info "Agent completed successfully"
echo ""
echo "Review changes:"
echo " cd $GIT_ROOT"
echo " git diff HEAD~1"
echo ""
echo "Rollback if needed:"
echo " git reset --hard HEAD~1"
else
error "Agent failed with exit code $EXIT_CODE"
exit $EXIT_CODE
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment