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
+13
View File
@@ -0,0 +1,13 @@
/* Claude management page. The shell (sidebar, banners, store) comes from the root
* layout; this route contributes only its section, in the shared scroll frame. */
"use client";
import { ClaudeSection } from "@/components/sections/ClaudeSection";
export default function ClaudePage() {
return (
<div className="main-scroll">
<ClaudeSection />
</div>
);
}
+10 -9
View File
@@ -1,13 +1,14 @@
/* Claude Login page. The shell (sidebar, banners, store) comes from the root layout; this
* route contributes only its section, in the shared scroll frame. */
/* The old Claude Login route. The login flow now lives on the Claude management page
* (/claude, Account tab); this stub only redirects old bookmarks there. */
"use client";
import { LoginSection } from "@/components/sections/LoginSection";
import { useEffect } from "react";
import { useRouter } from "next/navigation";
export default function LoginPage() {
return (
<div className="main-scroll">
<LoginSection />
</div>
);
export default function LoginRedirect() {
const router = useRouter();
useEffect(() => {
router.replace("/claude");
}, [router]);
return null;
}