.claude/skills/add-new-feature/SKILL.md
This skill should be used when the user asks to "add a feature", "implement a new command", "add a new platform", "add a new agent", "create a new module", "extend the engine", "add i18n strings", "add cross-cutting functionality", or needs guidance on the cc-connect project architecture, coding conventions, and development workflow.
npx skillsauth add liuyu520/cc-connect-fork add-new-featureInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Provide procedural guidance for implementing new features in cc-connect, ensuring adherence to the plugin architecture, dependency rules, and coding conventions documented in CLAUDE.md.
cmd/cc-connect/ → entry point, CLI, wiring
config/ → TOML config parsing
core/ → engine, interfaces, i18n, cards, sessions, registry
agent/X/ → per-agent adapter (claudecode, codex, gemini, ...)
platform/X/ → per-platform adapter (feishu, telegram, discord, ...)
daemon/ → systemd/launchd service management
The Engine logic is split across multiple files for maintainability:
| File | Content |
|------|---------|
| core/engine.go | Engine struct, NewEngine(), Set*() methods, lifecycle (Start/Stop), handleMessage() entry point |
| core/engine_commands.go | Command registry (builtinCommandNames, builtinCommandDef, initBuiltinCommands()), handleCommand() dispatch, all cmd*() handlers, GetAllCommands() |
| core/engine_cards.go | handleCardNav(), executeCardAction(), all render*Card() functions, delete mode, help card groups |
| core/engine_session.go | Type definitions (interactiveState, pendingPermission, queuedMessage), session management (processInteractiveMessage, getOrCreateInteractiveStateWith, etc.) |
| core/engine_events.go | processInteractiveEvents() event loop, drainPendingMessages() |
| core/engine_util.go | send(), reply(), sendPermissionPrompt(), HandleRelay(), splitMessage(), message utilities |
| core/engine_workspace.go | buildSenderPrompt(), commandContext(), resolveWorkspace(), workspace helpers |
cmd/ → config/, core/, agent/*, platform/*
agent/* → core/ (NEVER other agents or platforms)
platform/* → core/ (NEVER other platforms or agents)
core/ → stdlib (NEVER agent/ or platform/)
Agents and platforms register via init() in their packages:
func init() {
core.RegisterAgent("myagent", func(opts map[string]any) (core.Agent, error) { ... })
core.RegisterPlatform("myplatform", func(opts map[string]any) (core.Platform, error) { ... })
}
Import controlled by build-tag files in cmd/cc-connect/plugin_*.go.
Determine which layer the feature touches:
| Scope | Files to modify |
|-------|----------------|
| New slash command | core/engine_commands.go (handler + initBuiltinCommands + builtinCommandNames) |
| New i18n strings | core/i18n.go (MsgKey + 5 translations) |
| New platform | platform/X/, cmd/cc-connect/plugin_platform_X.go, Makefile |
| New agent | agent/X/, cmd/cc-connect/plugin_agent_X.go, Makefile |
| New optional capability | core/interfaces.go (interface), implementing packages |
| Cross-cutting concern | core/ (new file), cmd/cc-connect/main.go (wiring) |
| Engine behavior change | core/engine.go or relevant engine_*.go, core/engine_test.go |
| Card rendering | core/engine_cards.go |
| Session/event logic | core/engine_session.go or core/engine_events.go |
| WebUI / Vibe Coding | core/webui.go, web/src/pages/VibeCoding/, config/config.go |
| Management API field | core/management.go (handleProjects / handleProjectDetail), web/src/api/projects.ts |
Never hardcode platform or agent names in core/. Use capability interfaces:
// BAD — hardcodes platform knowledge in core
if p.Name() == "feishu" { ... }
// GOOD — capability-based check
if sender, ok := p.(InlineButtonSender); ok { ... }
To add a new optional capability:
core/interfaces.goAll user-facing text must go through core/i18n.go:
MsgKey constant after existing constantsmessages map for all 5 languages:
LangEnglish, LangChinese, LangTraditionalChinese, LangJapanese, LangSpanishe.i18n.T(MsgKey) or e.i18n.Tf(MsgKey, args...) in engine codeFor cross-cutting features (like ProjectRouter):
config/config.goFor per-engine features:
Set*() method on EnginereloadConfig() if hot-reloadableFollow existing test patterns in core/engine_test.go:
stubPlatformEngine for basic platform stubsstubInlineButtonPlatform for button-capable platformsstubAgent / stubAgentSession for agent stubsnewResultAgentSession(result) for sessions that return a specific resultcore package (internal, can access unexported fields)Test naming convention: TestFeatureName_ScenarioDescription
go build ./... # compilation
go test ./... # all tests pass
go test ./core/ -v -run "TestMyFeature" # specific tests
Only 2 places to modify (previously 3 with the old switch-case pattern):
Add entry in initBuiltinCommands() (in core/engine_commands.go):
{names: []string{"mycommand", "alias"}, id: "mycommand", handler: e.cmdMyCommand},
privileged: true if admin authorization requiredcommandHandlerAdd entry in builtinCommandNames (same file, package-level var):
{[]string{"mycommand", "alias"}, "mycommand"},
Implement handler func (e *Engine) cmdMyCommand(p Platform, msg *Message, args []string)
Add i18n: MsgBuiltinCmdMyCommand MsgKey = "mycommand" constant + 5-language translations
Add tests
See slash-command-system skill for the full registry pattern, closure adapters,
and composite command examples.
// 1. Add field to Engine struct (in engine.go)
type Engine struct {
myFeatureEnabled bool
// ...
}
// 2. Add setter (in engine.go)
func (e *Engine) SetMyFeature(enabled bool) {
e.myFeatureEnabled = enabled
}
// 3. Wire in main.go engine loop
engine.SetMyFeature(proj.MyFeature)
// 4. Add to reloadConfig() if hot-reloadable
New card rendering functions go in core/engine_cards.go:
func (e *Engine) renderMyCard(sessionKey string) *Card {
// Use listSessionsCached() for session data in card callbacks (3s timeout!)
// Use NewCard() builder for card construction
}
Remember the card callback performance constraint — see card-callback-performance skill.
core/ (e.g., core/my_feature.go)New*(), Start(), Stop()main.gocore/my_feature_test.go with dedicated stubsWhen the frontend needs data from config/engine (e.g., project work_dir):
core/management.go): Add field to handleProjects() or
handleProjectDetail() response map, using capability interface check:
workDir := ""
if wd, ok := e.agent.(interface{ GetWorkDir() string }); ok {
workDir = wd.GetWorkDir()
}
projects = append(projects, map[string]any{
"work_dir": workDir,
// ... existing fields ...
})
web/src/api/projects.ts): Add field to ProjectSummary
or ProjectDetail interfaceweb/src/pages/*/): Call API via listProjects() or
getProject(), render the dataSee webui-vibe-coding skill for a complete worked example (project dropdown).
fmt.Errorf("feishu: reply card: %w", err)slog.Error / slog.Warn for logging (never log.Printf)core.RedactToken(token)sync.Mutex or sync.RWMutexcontext.Context for cancellationsync.Once for one-time teardownreferences/interfaces.md — Complete list of core interfaces and when to use themsession-key-architecture — How session keys are constructed across platformsproject-router — Multi-project shared platform routing systemmessage-flow-architecture — End-to-end message processing pipeline, stdio protocol, authslash-command-system — Command registry pattern, routing, dispatch, closure adapterscard-callback-performance — IM card callback 3s timeout constraint and caching patternwebui-vibe-coding — Browser-based Vibe Coding interface (WebSocket protocol, Go backend, React frontend)tools
This skill should be used when the user asks about "webui", "web ui", "vibe coding", "WebUIServer", "web interface", "browser Claude Code", "web frontend", "React admin dashboard", "web/src", "VibeCoding page", "WebSocket /api/vibe/ws", "webui config", "port 9830", "static file serving", "webuiSession", "claude code subprocess from web", "project dropdown", "work dir select", "listProjects", "Management API frontend", "multi tab vibe", "TabBar", "VibeSession component", "copy work dir", "clipboard copy", "disconnect confirm", "断开确认", "复制路径", "copyWorkDir", "AgentSystemPrompt", "project awareness", "/project command in agent", "attachment upload", "sendWithAttachments", "file upload vibe", "image upload vibe", "drag drop vibe", "paste image vibe", or needs to debug, extend, or understand the browser-based Vibe Coding interface and its Go backend.
tools
This skill should be used when the user asks about "permission request", "control_request", "control_response", "permission prompt tool", "permission-prompt-tool stdio", "permission popup not showing", "permission dialog missing", "authorize tool use", "allow deny button", "webuiSession permission", "respondPermission", "updatedInput", "control_cancel_request", "permission cancelled", "permission_cancelled", "pendingInputs", "permission flow webui", "vibe permission", "前端没有弹出授权", "权限请求不显示", "权限弹窗", "webuiSession vs claudeSession", "webui parity", or needs to debug, extend, or understand how tool permission requests flow between Claude Code CLI, the Go WebUI backend, and the React frontend.
tools
This skill should be used when the user asks about "export markdown", "export chat", "download markdown", "export conversation", "导出 Markdown", "导出聊天记录", "ExportRequest", "ExportMessage", "handleVibeExportMarkdown", "buildExportMarkdown", "POST /api/vibe/export", "exportVibeSession", "chat export", "markdown download", "sanitizeFilename", "Content-Disposition attachment", "export button vibe", "history export", "tool_use in export", "message type mapping export", or needs to debug, extend, or understand the chat history Markdown export feature including the full-stack data flow from frontend trigger to file download.
tools
This skill should be used when the user asks about "attachment upload", "file upload", "image upload", "paste image", "drag drop file", "vibe attachment", "pendingAttachments", "sendWithAttachments", "fileToAttachment", "AttachmentItem", "base64 attachment", "WebSocket attachment protocol", "multimodal content", "image content block", "file content block", "clipboard paste image", "drag and drop upload", "attachment preview", "file size limit", "10MB limit", "ExtFromMime", "附件上传", "图片上传", "拖拽上传", "粘贴图片", "附件预览", "文件大小限制", or needs to debug, extend, or understand the WebUI attachment upload feature including the full-stack data flow from browser to Claude Code CLI.