Back to Projects

Karna: For Programmers who like to touch grass

Create tasks on a kanban board. An AI agent plans the approach, implements the code, and opens PRs on GitHub. You review plans and PRs on your own time, leave feedback, and the agent iterates until it's right.

Agents
Karna: For Programmers who like to touch grass

Tech Stack

RustAxumNext.jsReactTypeScriptPostgresRedis

About This Project

Quick Start

One command — it clones the repo, asks for your tokens, configures everything, and starts the server:

curl -fsSL https://raw.githubusercontent.com/Warlord-K/karna/main/install.sh | bash

You'll need:

  • A GitHub PAT with repo + workflow scopes (create one)

  • A Claude Code OAuth token (npm install -g @anthropic-ai/claude-code && claude setup-token)

That's it. Open localhost:3000 and create your first task.


Manual setup

git clone https://github.com/Warlord-K/karna.git
cd karna
cp .env.example .env
cp config.example.yaml config.yaml

Add your tokens to .env:

GITHUB_TOKEN=ghp_...
CLAUDE_CODE_OAUTH_TOKEN=...
AUTH_SECRET=$(openssl rand -hex 32)

Add repos to config.yaml:

repos:
  - repo: you/my-app
    branch: main
docker compose up

How It Works

┌──────────────┐     ┌──────────────┐     ┌──────────────┐
│   Frontend   │────▶│   Postgres   │◀────│  Rust Agent  │
│  Next.js     │     │   + Redis    │     │  polls every │
│  :3000       │     │              │     │  30 seconds  │
└──────────────┘     └──────────────┘     └──────┬───────┘
                                                  │
                                       ┌──────────┼──────────┐
                                       ▼          ▼          ▼
                                  Claude Code   git/gh    Resend
                                  or Codex      (PRs)     (email)

Task lifecycle:

StatusWhat happensTodoYou create a task with title, description, repo, priorityPlanningAgent picks it up, explores the codebase, writes a planPlan ReviewYou read the plan, approve or request changesIn ProgressAgent implements the approved planReviewAgent opens a PR on GitHubDoneYou merge the PR

You can send feedback at any stage — the agent re-plans or updates the PR.

Multi-Repo Tasks

Tasks can span multiple repositories. Create a task without selecting a specific repo and the agent will:

  1. Explore all configured repos and generate a plan with per-repo subtasks

  2. You approve the plan — subtasks are created automatically

  3. Each subtask goes through the normal lifecycle independently

  4. Parent task auto-completes when all subtasks finish

CLI Backends

Tasks can use either Claude Code or OpenAI Codex as the AI backend. Pick the CLI and model when creating a task.

Scaling

Run multiple agents in parallel:

docker compose up --scale agent=3

Each agent competes for tasks via Redis distributed locks. No double-work. Dead workers auto-release after 30 minutes.

Repo Onboarding

When repos are added, the agent automatically profiles them — detecting language, framework, test commands, build tools, and key directories. These profiles power smarter planning for multi-repo tasks. Manage repos from the UI or config.yaml.

Schedules

Automated agent runs on a cron or one-shot basis. The agent explores your repos and optionally creates tasks on the board.

Two built-in schedules ship disabled by default:

ScheduleCronWhat it doesBug HunterEvery 6 hoursScans for bugs, security issues, race conditionsFeature ScoutMonday 9amFinds TODOs, dead code, performance bottlenecks

Create custom schedules from the UI or config.yaml. Each run gets its own logs and can auto-create tasks with configurable limits.

Skills

9 built-in skills ship in skills/ (auto-loaded):

SkillWhat it doestestAuto-detect test framework, run testslintAuto-detect linter, run with auto-fixtypecheckRun static type checkingcommitConventional commit formatreviewSelf-review checklist before PRbuildAuto-detect build system, verify buildmigrateDatabase migration guidancesecuritySecurity scan + dependency auditadd-repoOnboard a repository — explore and generate profile

Add custom skills — drop a markdown file in skills/:

---
description: Deploy to staging
command: gh workflow run deploy.yml -f environment=staging
phase: implement
---
Run this after all tests pass to deploy the changes.

Repos can also ship their own skills/ directory — auto-discovered when the agent clones them.

MCP Servers

5 MCP servers are enabled by default (no API keys needed):

ServerPurposefetchRead any URL as markdowncontext7Up-to-date library documentationmemoryPersistent knowledge graph across taskssequential-thinkingStructured reasoninggithubFull GitHub API (uses your GITHUB_TOKEN)

Add more in config.yaml — Sentry, Linear, Slack, Postgres, Supabase, Notion, Brave Search, and Playwright are preconfigured and just need API keys.

Repos can provide .mcp.json at their root — auto-discovered and merged at runtime.

Agent Instructions

Give the agent persistent context across all tasks with a markdown instructions file:

agent:
  instructions: instructions.md

Use this for agent identity, a map of your repos, cross-repo conventions, and architectural context. See instructions.example.md for the recommended format.

Self-Iteration

Karna can manage its own repository — modifying config, skills, instructions, and its own code:

repos:
  - repo: user/karna-fork
    branch: main
    self: true

The agent implements changes and opens PRs like any other task. Config and skill changes hot-reload instantly. Code changes trigger an automatic rebuild with graceful drain (no mid-task interruption).

GitHub Webhooks

Connect GitHub webhooks so the agent picks up PR reviews and comments in real-time.

Setup: Make the agent reachable from GitHub (Cloudflare Tunnel, public IP, or ngrok), then set AGENT_WEBHOOK_URL or TUNNEL_AGENT_HOSTNAME in .env. Webhooks are auto-registered on repos during onboarding. Optionally set GITHUB_WEBHOOK_SECRET for HMAC-SHA256 signature verification.

You do this on GitHubAgent does thisRequest changes on a PRReads your review, pushes fixesComment on a PRAddresses your feedbackApprove + merge a PRMarks the task as done

Without webhooks: Post feedback through the Activity tab in the UI. The agent also gathers PR comments via gh pr view when it starts working on feedback.

Commit Signing

Sign agent commits with an SSH key so they show as "Verified" on GitHub:

mkdir -p signing
cp ~/.ssh/id_ed25519 signing/signing_key

Add the public key to GitHub SSH settings as a "Signing Key". The agent auto-detects keys in signing/ at startup. If empty, signing is skipped.

Public Access (Cloudflare Tunnel)

Expose your instance to the internet without port forwarding:

Token-based (routes managed in CF dashboard):

CLOUDFLARE_TUNNEL_TOKEN=your-token
docker compose --profile tunnel up

Credentials-based (routes defined locally):

cloudflared tunnel create karna
cloudflared tunnel route dns karna app.yourdomain.com
cloudflared tunnel route dns karna code.yourdomain.com

# Add to .env:
CLOUDFLARE_TUNNEL_ID=...
CLOUDFLARE_TUNNEL_CREDENTIALS=...   # base64 of ~/.cloudflared/<TUNNEL_ID>.json
TUNNEL_FRONTEND_HOSTNAME=app.yourdomain.com
TUNNEL_CODE_SERVER_HOSTNAME=code.yourdomain.com

CLI

./karna start      # Start all services + background auto-updater
./karna stop       # Graceful shutdown (10min drain)
./karna restart    # Stop + start
./karna update     # Manual update check
./karna status     # Service health + updater state
./karna setup      # Validate config, test connections
./karna logs       # Tail logs (optionally: ./karna logs agent)

Configuration Reference

config.yaml

repos:
  - repo: you/backend
    branch: main
  - repo: you/frontend
    branch: main

agent:
  max_turns: 100              # Max CLI turns per invocation
  poll_interval_secs: 30      # Task polling frequency
  max_concurrent_tasks: 1     # Per worker (increase with --scale)
  instructions: instructions.md  # Optional system prompt file

  backends:
    claude:
      models: [opus, sonnet, haiku]
      default_model: sonnet
    codex:
      models: [gpt-5.4, gpt-5.4-mini, gpt-5.3-codex]
      default_model: gpt-5.4

notifications:
  email: you@example.com

Development

# Infrastructure only
docker compose up -d postgres redis

# Frontend (hot reload)
cd frontend && npm install && npm run setup && npm run dev

# Agent
cd agent
export DATABASE_URL="postgres://karna:karna@localhost:5432/karna"
export REDIS_URL="redis://localhost:6379"
export CONFIG_PATH="../config.yaml"
export REPOS_DIR="$HOME/karna-repos"
export WORKSPACES_DIR="$HOME/karna-workspaces"
cargo run

CI runs on all PRs: cargo check + cargo clippy for the agent, npm run build for the frontend, and Docker build verification.

Architecture

docker-compose.yml
├── postgres:16       — Auth sessions + tasks + logs
├── redis:7           — Task queue + distributed locks
├── agent (Rust)      — Polls DB, invokes Claude Code or Codex CLI, git/gh operations
├── frontend (Next.js)— Kanban board, Auth.js with credentials auth
├── code-server       — Browser IDE to watch agent edit files
├── tunnel            — Optional Cloudflare Tunnel for public access
└── autoheal          — Auto-restarts unhealthy containers