feat: CodePilot - desktop GUI for Claude Code

Full-featured desktop application built with Next.js + Electron:
- Streaming chat with Claude Code via Agent SDK
- Session management with SQLite persistence
- Project file tree and file preview
- MCP server and custom skills management
- Permission controls with Code/Plan/Ask modes
- Dark/light theme, token tracking
- macOS DMG packaging with electron-builder

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
7418andClaude Opus 4.6 committed 2026-02-06 21:04:05 +08:00
1 parent 6776cc6297
commit ff1fb38735
149 files changed
+31117 -122

No files matched your search

+63
View File
@@ -0,0 +1,63 @@
'use client';
import { useState, useEffect } from 'react';
import { Textarea } from '@/components/ui/textarea';
import { Button } from '@/components/ui/button';
import { Label } from '@/components/ui/label';
interface ConfigEditorProps {
value: string;
onSave: (value: string) => void;
label?: string;
}
export function ConfigEditor({ value, onSave, label }: ConfigEditorProps) {
const [text, setText] = useState(value);
const [error, setError] = useState<string | null>(null);
useEffect(() => { setText(value); }, [value]);
function handleSave() {
try {
JSON.parse(text);
setError(null);
onSave(text);
} catch (e) {
setError(e instanceof Error ? e.message : 'Invalid JSON');
}
}
function handleFormat() {
try {
const parsed = JSON.parse(text);
setText(JSON.stringify(parsed, null, 2));
setError(null);
} catch (e) {
setError(e instanceof Error ? e.message : 'Invalid JSON');
}
}
return (
<div className="space-y-2">
{label && <Label>{label}</Label>}
<Textarea
value={text}
onChange={(e) => {
setText(e.target.value);
setError(null);
}}
className="font-mono text-sm min-h-[200px]"
placeholder="{}"
/>
{error && <p className="text-xs text-destructive">{error}</p>}
<div className="flex gap-2">
<Button size="sm" onClick={handleSave}>
Save
</Button>
<Button size="sm" variant="outline" onClick={handleFormat}>
Format
</Button>
</div>
</div>
);
}