Essential information for AI coding agents working in this repository.
Type: Docker-based deployment template for NullClaw AI agent framework
Language: Zig (compiled binary) + Shell scripting (POSIX sh)
Purpose: Deploy containerized AI agents with multiple LLM providers and communication channels
This is not a source code repository. The actual NullClaw application is cloned from https://github.com/nullclaw/nullclaw.git during Docker build and compiled with Zig.
# Build Docker image
docker compose build nullclaw
# Start gateway service (port 3000)
docker compose up -d nullclaw
# Start agent service (CLI mode)
docker compose --profile agent up -d nullclaw-agent
# View logs
docker compose logs -f nullclaw
# Stop services
docker compose downNo automated test framework - this is a deployment template.
# Health check
curl http://localhost:3000/health
# Check container logs
docker compose logs nullclaw
# Verify config generation
docker compose exec nullclaw cat /nullclaw-data/.nullclaw/config.jsoncp .env.example .env
nano .env # Add your API keys- Template:
config.template.jsoncontains placeholders (e.g.,{{PROVIDERS}}) - Generator:
entrypoint.shsubstitutes environment variables at runtime - Output:
/nullclaw-data/.nullclaw/config.json
# At least one provider API key
OPENROUTER_API_KEY= # Recommended (multi-model support)
ANTHROPIC_API_KEY= # Claude
OPENAI_API_KEY= # GPT models
GROQ_API_KEY= # Fast inference
# Port (Railway convention)
PORT=3000# Telegram example
TELEGRAM_BOT_TOKEN=123456:ABCDEF
TELEGRAM_ALLOW_FROM=123456789 # Comma-separated user IDs or "*"See GUIDE_ADD_NEW_CHANNELS.md for detailed instructions.
Use POSIX sh, not bash:
#!/bin/sh
set -e # Exit on error (always include at script start)
# Default values
: "${VARIABLE:=default_value}"
# Check required variables
if [ -z "$REQUIRED_VAR" ]; then
echo "Error: REQUIRED_VAR not set" >&2
exit 1
fi
# String manipulation: comma-separated list to JSON array
echo "$ALLOW_FROM" | sed 's/,/","/g' | sed 's/^/["/' | sed 's/$/"]/'
# Uppercase conversion
key_var=$(echo "$provider" | tr '[:lower:]' '[:upper:]')_API_KEYTemplate placeholders:
{
"models": {
"providers": {
{{PROVIDERS}} // Replaced by entrypoint.sh
}
}
}Valid JSON:
- No trailing commas
- Double quotes only (no single quotes)
- Booleans:
true/false(lowercase) - Numbers: unquoted
Multi-stage builds:
FROM alpine:3.23 AS builder
RUN apk add --no-cache zig
RUN zig build -Doptimize=ReleaseSmall
FROM alpine:3.23 AS release
COPY --from=builder /app/zig-out/bin/app /usr/local/bin/- Edit
config.template.jsonfor new config options - Update
entrypoint.shto handle new environment variables - Document in
.env.example - Test with
docker compose up -d nullclaw
- Check NullClaw's
config.example.jsonfor channel structure - Add environment variables to
.env.example - Update
build_channels()function inentrypoint.sh - Test with appropriate credentials
docker compose logs -f nullclaw
docker compose exec nullclaw cat /nullclaw-data/.nullclaw/config.json
curl -v http://localhost:3000/health
docker compose run --rm nullclaw sh- No source code: This template only contains deployment configuration
- No linting tools: Configuration-driven project with manual validation
- No test suite: Testing via Docker health checks and manual verification
- Environment-first: All configuration via environment variables
- Template substitution:
entrypoint.shgenerates config at runtime, not build time