Turn the Claude Login page into a full Claude management page

The dashboard's Claude page now manages the whole Claude Code install agents
run on, not just the account login:

- Skills: operator-authored SKILL.md rows, synced to each worker's user-level
  ~/.claude/skills at every launch. Managed dirs carry a .handler-managed
  marker so deletions in the UI propagate while hand-installed skills survive.
- Connectors: MCP servers (stdio/http/sse) written per-launch as
  .claude/mcp-servers.json and passed to claude via --mcp-config, so nothing
  lands in the managed repo's tracked tree.
- Plugins: marketplace-pinned plugins folded into generated settings as
  extraKnownMarketplaces + enabledPlugins, installing on boot of headless runs.
- Permissions: defaultMode override plus allow/deny/ask rules merged over the
  env baseline into every generated settings.json.

All of it is plain DB state (new claude_skills / claude_connectors /
claude_plugins / claude_config tables, migration 0010) edited through the new
admin-gated /claude/* API routes and applied by the control container at spawn
and resume — changes reach the next launch of every agent with no redeploy.

The login flow moved into the page's Account tab unchanged; /login redirects
to /claude for old bookmarks.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019f42XmjtVsc3zQ9Dhn6DqZ
This commit is contained in:
Claude
2026-07-23 13:32:41 +00:00
parent 301a697e74
commit 07d8c3aa19
65 changed files with 2240 additions and 99 deletions
+46
View File
@@ -140,6 +140,52 @@ export interface Schedule {
created_at: string;
}
/* ---- Claude management (the dashboard's Claude page) ---- */
export interface ClaudeSkill {
id: number;
name: string;
description?: string | null;
content: string;
enabled: boolean;
created_at: string;
updated_at: string;
}
export type McpTransport = "stdio" | "http" | "sse";
export interface ClaudeConnector {
id: number;
name: string;
transport: McpTransport;
command?: string | null;
args?: string[] | null;
env?: Record<string, string> | null;
url?: string | null;
headers?: Record<string, string> | null;
enabled: boolean;
created_at: string;
}
export interface ClaudePlugin {
id: number;
name: string;
marketplace: string;
marketplace_repo: string;
enabled: boolean;
created_at: string;
}
/* Stored overrides + the env baseline they merge over at launch (read-only here). */
export interface ClaudePermissions {
default_mode?: string | null;
allow: string[];
deny: string[];
ask: string[];
base_mode: string;
base_allow: string[];
}
export interface SharedContext {
key: string;
value: string;