System Design
The self-hosted dev platform is built around three integration pillars — YouTrack (issue tracking), Gitea (source control and CI/CD), and Discord (notifications) — glued together by the devops-plugin Claude Code plugin running in the ai-workspace repository.
Component overview
flowchart TB
%% Top-level system component overview
subgraph Cloud["Linode Cloud"]
NB[NodeBalancer\n:80 / :443]
subgraph K3s["K3s Cluster"]
Traefik[Traefik Ingress\nTLS termination]
Gitea[Gitea\nSource Control + CI]
YouTrack[YouTrack\nIssue Tracking]
DocSite[Doc Site\ndoc.davidhsaiou.com]
Shop[Online Shop\nBlazor + .NET API]
end
end
subgraph WorkstationOrCI["Workstation / CI Runner"]
CCW[Claude Code\nai-workspace]
Plugin[devops-plugin\nAgents + Skills]
CCW --> Plugin
end
Users([Users]) --> NB
Devs([Developers]) --> NB
NB --> Traefik
Traefik --> Gitea
Traefik --> YouTrack
Traefik --> DocSite
Traefik --> Shop
Plugin -->|MCP| YouTrack
Plugin -->|MCP| Gitea
Plugin -->|webhook| Discord[(Discord)]
Gitea -->|Actions runners| CCW
Key design decisions
Claude Code as the orchestration layer
All automation runs inside Claude Code sessions. The devops-plugin provides agents and skills as Markdown definitions — no compiled binary, no separate service. This means:
- Zero additional infrastructure: automation runs on the same workstation or CI runner where Claude Code is installed.
- Agent logic is readable and version-controlled alongside the code it manages.
- Skills wrap single MCP tool calls, keeping them auditable and easy to test in isolation.
MCP for external system access
Agents interact with YouTrack, Gitea, and Discord exclusively through MCP (Model Context Protocol) tool calls. This provides:
- Authenticated API access without agents ever reading or constructing tokens.
- A consistent permission model:
settings.jsonindevops-plugin/defines the allow-list;settings.local.jsonin the workspace carries local overrides. - A clear audit trail: every MCP call is logged in the Claude Code session transcript.
Git worktrees for isolation
The dispatcher creates a separate git worktree for each task:
ai-workspace/
worktrees/<repo-name>/ ← reference clone (shared, never modified directly)
.claude/worktrees/
<repo-name>--<issue-id>/ ← per-task worktree (isolated, cleaned after run)
Two concurrent agents targeting the same repo never share a working directory.
YouTrack as the state machine
Pipeline state lives in YouTrack custom fields — not in any local file or database. This means the pipeline is fully restartable: if a run fails mid-way, re-dispatching the issue picks up from the correct state.
Plugin metadata
The devops-plugin plugin is registered in two files:
| File | Purpose |
|---|---|
devops-plugin/.claude-plugin/plugin.json |
Plugin identity, version (1.17.2), author, and repository URL |
.claude-plugin/marketplace.json |
Marketplace index pointing to devops-plugin/ |
Version follows semver: patch for fixes, minor for new features, major for breaking changes. Both files must be bumped together.