From kastell
Provides Kastell CLI architecture overview, patterns, anti-patterns, decision trees, layer rules, and adapters for codebase work or server infrastructure, provisioning, security audits, hardening.
npx claudepluginhub kastelldev/kastellThis skill is limited to using the following tools:
Kastell is a CLI toolkit for provisioning, securing, and managing self-hosted servers. TypeScript, ESM, strict mode. 31 CLI commands, 13 MCP tools, 4 cloud providers (hetzner, digitalocean, vultr, linode), 2 platform adapters (coolify, dokploy).
Explores Kastell codebase read-only with Read, Grep, Glob tools for tracing bugs across files, mapping callsites before refactoring, and investigating subsystems.
Initializes Turborepo monorepos for enterprise systems with microservices (FastAPI), Kubernetes/Terraform infra, docs, and AI Native dev guides/help. For large-scale ops.
Guides 12-Factor methodology for scalable cloud-native apps. Use for microservices design, container config, Kubernetes deployment, CI/CD pipelines, and environment management.
Share bugs, ideas, or general feedback.
Kastell is a CLI toolkit for provisioning, securing, and managing self-hosted servers. TypeScript, ESM, strict mode. 31 CLI commands, 13 MCP tools, 4 cloud providers (hetzner, digitalocean, vultr, linode), 2 platform adapters (coolify, dokploy).
Version: !node -e "import('fs').then(f=>console.log(JSON.parse(f.readFileSync('package.json','utf8')).version)).catch(()=>console.log('unknown'))"
Registered servers:
!kastell list 2>/dev/null || echo "No servers registered"
src/
commands/ # 31 thin CLI wrappers (parse args + delegate only)
core/ # Business logic (ALL computation here)
providers/ # Cloud API: hetzner, digitalocean, vultr, linode
adapters/ # Platform abstraction: coolify, dokploy
interface.ts # PlatformAdapter contract
factory.ts # getAdapter(), detectPlatform(), resolvePlatform()
mcp/
server.ts # 13 tool registrations
tools/ # Handler files (Zod schema + handler per tool)
utils/ # ssh, config, cloudInit, modeGuard, migration
types/ # ServerMode, ServerRecord, Platform
constants.ts # PROVIDER_REGISTRY (single source of truth)
index.ts # CLI entry point
| Layer | Path | Responsibility | Rule |
|---|---|---|---|
| Commands | src/commands/ | Parse CLI args, call core, display output | ZERO business logic |
| Core | src/core/ | All business logic, orchestration | No UI/chalk/ora imports |
| Providers | src/providers/ | Cloud API calls per provider | Implements cloud CRUD |
| Adapters | src/adapters/ | Platform-specific ops (Coolify/Dokploy) | Via PlatformAdapter interface |
| MCP | src/mcp/ | MCP server + tool handlers | Delegates to core |
| Utils | src/utils/ | SSH, config, modeGuard, errorMapper | Shared infrastructure |
Access adapters via getAdapter(platform) from src/adapters/factory.ts. Never import CoolifyAdapter or DokployAdapter directly in commands.
interface PlatformAdapter {
readonly name: string; // "coolify" | "dokploy"
readonly port: number; // 8000 (Coolify) | 3000 (Dokploy)
readonly defaultLogService: string; // matches platform name
readonly platformPorts: readonly number[]; // ports protected from firewall removal
getCloudInit(serverName: string): string;
healthCheck(ip: string, domain?: string): Promise<HealthResult>;
createBackup(ip: string, serverName: string, provider: string): Promise<PlatformBackupResult>;
getStatus(ip: string): Promise<PlatformStatusResult>;
update(ip: string): Promise<UpdateResult>;
restoreBackup?(ip, backupPath, manifest): Promise<PlatformRestoreResult>; // optional
}
Factory exports: getAdapter(platform), detectPlatform(ip), resolvePlatform(server)
| Provider | Env Key | Display Name |
|---|---|---|
| hetzner | HETZNER_TOKEN | Hetzner Cloud |
| digitalocean | DIGITALOCEAN_TOKEN | DigitalOcean |
| vultr | VULTR_TOKEN | Vultr |
| linode | LINODE_TOKEN | Linode (Akamai) |
PROVIDER_REGISTRY in src/constants.ts is the single source of truth for providers.
src/commands/<name>.ts — thin wrapper (parse + delegate, no logic)src/core/<name>.ts — all business logic heresrc/index.ts — register with programsrc/__tests__/ — test core, not commandsrc/core/audit/<category>/ — add to existing categorysrc/core/audit/catalog.tskastell auditsrc/providers/<name>.ts — implements base.ts contractsrc/constants.ts — add to PROVIDER_REGISTRYsrc/mcp/tools/server<Name>.ts — Zod schema + handlersrc/mcp/server.ts — import + registerTool()readOnlyHint / destructiveHint / idempotentHint"type": "module") — import, not requireKASTELL_SAFE_MODE + isSafeMode() = destructive operation guardassertValidIp() before every SSH operationsanitizedEnv for subprocess callssanitizeResponseData() whitelist approach for API error responseskastell/ directory (auto-migrated from legacy name)PROVIDER_REGISTRY = single source of truth for providerswithProviderErrorHandling HOF for consistent provider error handlingdescribe.each with jest.resetAllMocks() (not clearAllMocks())Run without LLM — deterministic analysis scripts:
# Parse audit JSON into 5 security domain summaries
kastell audit --server myserver --json > /tmp/audit.json
scripts/parse_audit.sh /tmp/audit.json
# Generate fleet-wide server score table
kastell fleet --json > /tmp/fleet.json
scripts/fleet_report.sh /tmp/fleet.json
# Compare audit check count vs test coverage
scripts/check_coverage.sh