AI-Dev-IO1 Claude Runner (on vps-i1)

Environment ID: ai-dev-io1 Type: agent-runner Status: active

Purpose

Autonomous Claude Code agent runner hosted on vps-i1 (IONOS). Handles p24-infra monitoring-ops tasks: nightly infra checks, hourly triage, compliance audits, PR reviews, and feature implementation for monitoring stack issues.

Host

Runs on vps-i1 (217.154.82.162 / AlmaLinux 9.7). See docs/environments/vps-i1.md for host hardware specs.

Agent Configuration

FieldValue
GitHub userAI-Dev-IO1
Claude versionv2.1.121 at /usr/bin/claude
Userclaude-runner (dedicated non-root user)
Credentials/home/claude-runner/.claude/.credentials.json
Auth typeOAuth subscription (Claude Max) — not ANTHROPIC_API_KEY
Max parallel agents3
Rolemonitoring-ops
Reposradieu/p24-infra (write), radieu/et-operational-platform (write)

Parallelism Windows

WindowMax agentsUTC hours
Daily scan309:00–22:45
Nightly reviews523:00–01:00

Scheduled Tasks

TaskScheduleDescription
Nightly infra check23:00 UTC dailyChecks VPS health, containers, disk, alerts
Hourly triageEvery hourProcesses new GitHub issues and assigns milestones
Issues reviewOn demand / nightlyRuns worker queue dispatching
HeartbeatEvery 6hReports agent health to Supabase scanner_heartbeat

Environment Sync

The repo is synced to /opt/p24-infra via Ansible claude-env-sync role every 6 hours. The CLAUDE_ENV_LAST_CHANGED timestamp in CLAUDE.md triggers a forced resync when bumped.

Re-auth Procedure

OAuth tokens expire every 8–12 hours. Claude Code auto-refreshes using the refreshToken. When auth expires:

  1. Automated (preferred): Claude attempts Playwright automation to complete the OAuth flow

    • Run reauth script: python d:\tmp\reauth-ionos.py
    • Use Playwright browser MCP to navigate the OAuth URL and capture the code
    • Send code to server tmux session: tmux send-keys -t claude_auth "<code>" Enter
    • Verify: su -s /bin/bash claude-runner -c 'claude -p say-ok'
  2. Human escalation (if Playwright fails twice):

    • Discord alert via P24_DISCORD_INFRA_SCRIPTS_ERRORS_WEBHOOK_URL
    • GitHub issue with human-action label: "CRITICAL: claude-runner auth expired on vps-i1"

Notes

  • Do not use ANTHROPIC_API_KEY for this runner — OAuth subscription provides zero marginal cost per call
  • Never SSH into vps-i1 as claude-runner from an automated context — use the agent session on the server itself
  • The claude-runner user has limited sudo: docker, systemctl, mkdir, chown, cp, tee

Secrets Access

Secret storeAccess methodCan decrypt SOPS?
All secrets/*.env.sops filesage key at /home/claude-runner/.age/keys.txtYes � claude-runner has the age key (verified 2026-06-24)
On-server plaintext fallback/opt/p24-infra/monitoring/.env (deployed by CI)N/A � already plaintext
GitHub Actions secretsNot accessible from VPS directlyN/A

AI-Dev-IO1 (claude-runner on vps-i1) does hold the SOPS age key and can decrypt all SOPS files directly. CI also deploys a plaintext copy to /opt/p24-infra/monitoring/.env on each merge as a fallback.

CLAUDE.md in Effect

The following rule layers are active for every AI-Dev-IO1 session, in priority order (highest first):

SourceFile on VPSKey rules active
Global (user)/home/claude-runner/.claude/CLAUDE.mdUse Bash (not PowerShell); SOPS lookup order; worktree workflow mandatory
Project/opt/p24-infra/CLAUDE.mdStack architecture; error notification standard (Discord + GH issue); EU AI Act compliance
Skills~/.claude/commands/*.md/role-*, /new-issue, /nightly-infra-check, /hourly-devops-triage
Role standards/opt/p24-infra/standards/project-types/sysadmin/*Loaded when P4_CLAUDE_ROLE=monitoring-ops

The global CLAUDE.md (/home/claude-runner/.claude/CLAUDE.md) is sourced from scripts/vps-global-claude.md in this repo and deployed by the claude-env-sync Ansible role.