This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Dify Plugin Daemon is a Go service that manages plugin lifecycle for the Dify platform. It supports three runtime types:
- Local runtime: Runs plugins as subprocesses via STDIN/STDOUT
- Debug runtime: TCP-based debugging connection for plugin development
- Serverless runtime: Deploys to platforms like AWS Lambda via HTTP
# Run the daemon server
go run cmd/server/main.go
# Run tests for a specific package (only when explicitly requested)
go test ./internal/core/plugin_daemon/...
# Run a single test (only when explicitly requested)
go test -run TestSpecificName ./path/to/package
# Generate code from definitions
go run cmd/codegen/main.goDO NOT automatically run tests unless the user explicitly requests it. Tests should only be executed when specifically asked by the user.
# Copy environment template
cp .env.example .env
# Key environment variables to configure:
# - DB_HOST, DB_NAME, DB_USER, DB_PASS: Database connection
# - PYTHON_INTERPRETER_PATH: Python 3.11+ path for plugin SDK
# - S3_USE_AWS: Set to false for non-AWS S3 storage-
Plugin Daemon (
internal/core/plugin_daemon/)- Handles plugin invocation and lifecycle management
agent_service.go: Agent strategy invocation without JSON schema validationtool.gen.go,model.gen.go,oauth.gen.go: Generated service interfacesbackwards_invocation/: Handles callbacks to Dify API server
-
Plugin Manager (
internal/core/plugin_manager/)- Runtime Types:
local_runtime/: Process-based plugin execution with Python environmentdebugging_runtime/: TCP server for plugin development/debuggingserverless_runtime/: Serverless deployment
media_transport/: Handles plugin assets and storage- Plugin installation, uninstallation, and lifecycle management
- Runtime Types:
-
Session Manager (
internal/core/session_manager/)- Manages plugin execution sessions and state
-
Service Layer (
internal/service/)- HTTP handlers and SSE streaming for plugin operations
- Generated service implementations
-
Server (
internal/server/)- HTTP server setup and routing
- Generated routes in
http_server.gen.go
-
Code Generation: Many service files are generated from definitions in
internal/server/controllers/definitions/definitions.go. Files ending in.gen.goare auto-generated. -
Stream-based Communication: Uses custom streaming (
internal/utils/stream/) for real-time plugin communication, especially for SSE responses. -
Plugin Invocation Flow:
- Request → Session Manager → Plugin Daemon → Plugin Manager → Runtime → Plugin Process
- Responses stream back through the same chain
The project includes a CLI tool for plugin development:
cmd/commandline/: Main CLI implementationcmd/commandline/plugin/: Plugin initialization and packagingcmd/commandline/bundle/: Bundle managementcmd/commandline/signature/: Plugin signing and verification
-
Package Organization
- Group imports in order: standard library, external packages, internal packages
- Separate groups with blank lines
- Package comments should start with
// Package <name>for documentation
-
Function and Method Naming
- Public functions:
PascalCase(e.g.,InvokeAgentStrategy) - Private functions:
camelCase(e.g.,bindAgentStrategyValidator) - Receiver methods follow the same pattern based on visibility
- HTTP handlers typically named like
InvokeTool,ValidateToolCredentials
- Public functions:
-
Error Handling
- Always check errors immediately after function calls
- Return early on errors with explicit error messages
- Use
errors.New()for simple error strings - Use
fmt.Errorf()for formatted error messages with context
-
Function Signatures
- Multi-line parameters should each be on their own line
- Return types on the same line if short, otherwise on new line
- Example:
func InvokeAgentStrategy( session *session_manager.Session, r *requests.RequestInvokeAgentStrategy, ) (*stream.Stream[agent_entities.AgentStrategyResponseChunk], error) {
-
Comments
- IMPORTANT: Do NOT add comments unless explicitly requested by the user
- When required, use
//for single-line comments - Function documentation should start with the function name
-
Deferred Functions
- Use
deferfor cleanup operations - Common pattern:
defer response.Close(),defer log.Info(...) - Place defer statements immediately after resource acquisition
- Use
-
Variable Naming
- Use short, descriptive names
- Single letter names (
r,w,c) acceptable for common types (request, writer, context) - Acronyms should be all caps:
HTTP,URL,ID, notHttp,Url,Id
-
Constants and Enums
- Constants use
SCREAMING_SNAKE_CASEwith package prefix - Example:
PLUGIN_ACCESS_TYPE_TOOL,PLUGIN_RUNTIME_TYPE_LOCAL
- Constants use
-
Struct Field Tags
- JSON tags:
json:"field_name" - Validation tags:
validate:"required,min=1,max=256" - URI/form tags for HTTP binding:
uri:"tenant_id",form:"page"
- JSON tags:
-
Goroutines and Concurrency
- Use
go func()for simple async operations - Use
routine.Submit()when tracking is needed (though being phased out) - Always handle channel closes and potential panics
- Use
-
Stream and Channel Patterns
- Close streams/channels in defer statements
- Check for nil before operations
- Use select with default case to avoid blocking
For detailed technical documentation, see the following sub-docs:
- Database Operations - Query builder, models, transactions
- Cache Operations - Redis caching, pub/sub, distributed locks
- Stream Operations - Async producer-consumer patterns, SSE handling
- Generic Types - Type-safe patterns used throughout the codebase
- HTTP Requests - HTTP client utilities and request handling
- UV: Python dependency manager required for plugin management
- Python 3.11+: Required for running Python plugins
- Go 1.23.3: Main language for the daemon
cwd/: Working directory for installed pluginsstorage/plugin_packages/: Packaged plugin storagestorage/assets/: Plugin assets and icons
VSCode launch configuration is provided in .vscode/launch.json for debugging the daemon server.