You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@skywalking.apache.org by wu...@apache.org on 2026/01/20 11:45:41 UTC
(skywalking-java) branch add-claude-md created (now e196083d02)
This is an automated email from the ASF dual-hosted git repository.
wusheng pushed a change to branch add-claude-md
in repository https://gitbox.apache.org/repos/asf/skywalking-java.git
at e196083d02 Add CLAUDE.md for AI assistant guidance
This branch includes the following new commits:
new e196083d02 Add CLAUDE.md for AI assistant guidance
The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
(skywalking-java) 01/01: Add CLAUDE.md for AI assistant guidance
Posted by wu...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
wusheng pushed a commit to branch add-claude-md
in repository https://gitbox.apache.org/repos/asf/skywalking-java.git
commit e196083d02ddf19af9908addbc163ed0ee9db825
Author: Wu Sheng <wu...@foxmail.com>
AuthorDate: Tue Jan 20 17:18:27 2026 +0800
Add CLAUDE.md for AI assistant guidance
Add a comprehensive guide for AI assistants working with the SkyWalking Java Agent codebase, including:
- Project overview and repository structure
- Build system and commands
- Plugin development with V2 API (recommended) vs V1 API (legacy)
- Plugin development rules and dependency management
- Tracing concepts and meter APIs
- Plugin test framework documentation
- Code style and conventions
- PR guidelines and templates
---
CHANGES.md | 1 +
CLAUDE.md | 697 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 698 insertions(+)
diff --git a/CHANGES.md b/CHANGES.md
index 54f75eeb97..979502ce7a 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -5,6 +5,7 @@ Release Notes.
9.6.0
------------------
+* Add CLAUDE.md for AI assistant guidance.
* Bump up agent-oap protocol to latest(16c51358ebcf42629bf4ffdf952253971f20eb25).
* Bump up gRPC to v1.74.0.
* Bump up netty to v4.1.124.Final.
diff --git a/CLAUDE.md b/CLAUDE.md
new file mode 100644
index 0000000000..90e3bf0f6c
--- /dev/null
+++ b/CLAUDE.md
@@ -0,0 +1,697 @@
+# CLAUDE.md - AI Assistant Guide for Apache SkyWalking Java Agent
+
+This file provides guidance for AI assistants working with the Apache SkyWalking Java Agent codebase.
+
+## Project Overview
+
+Apache SkyWalking Java Agent is a Java-based APM (Application Performance Monitoring) agent designed for microservices, cloud-native, and container-based architectures. It provides automatic instrumentation for distributed tracing, performance metrics collection, and context propagation across service boundaries using bytecode manipulation via ByteBuddy.
+
+## Repository Structure
+
+```
+skywalking-java/
+├── apm-commons/ # Shared utilities and libraries
+│ ├── apm-datacarrier/ # Data buffering and transport
+│ └── apm-util/ # Common utilities
+├── apm-protocol/ # Protocol definitions
+│ └── apm-network/ # gRPC protocol (submodule: skywalking-data-collect-protocol)
+├── apm-sniffer/ # Core agent and plugins (MAIN MODULE)
+│ ├── apm-agent/ # Main agent bootstrap and premain entry
+│ ├── apm-agent-core/ # Core agent logic, instrumentation engine
+│ ├── apm-sdk-plugin/ # Standard SDK plugins (70+ plugins)
+│ ├── bootstrap-plugins/ # Bootstrap-level plugins (JDK-level)
+│ ├── optional-plugins/ # Optional framework plugins
+│ ├── optional-reporter-plugins/ # Reporter plugins (Kafka, etc.)
+│ ├── apm-toolkit-activation/ # Toolkit activations
+│ ├── apm-test-tools/ # Testing utilities
+│ ├── bytebuddy-patch/ # ByteBuddy patches
+│ └── config/ # Default agent configurations
+├── apm-application-toolkit/ # Public API for applications
+│ ├── apm-toolkit-trace/ # Tracing API
+│ ├── apm-toolkit-log4j-1.x/ # Log4j 1.x integration
+│ ├── apm-toolkit-log4j-2.x/ # Log4j 2.x integration
+│ ├── apm-toolkit-logback-1.x/ # Logback integration
+│ ├── apm-toolkit-meter/ # Meter API
+│ └── apm-toolkit-opentracing/ # OpenTracing API
+├── apm-checkstyle/ # Code style configuration
+│ ├── checkStyle.xml # Checkstyle rules
+│ └── importControl.xml # Import control rules
+├── test/ # Testing infrastructure
+│ ├── plugin/ # Plugin E2E tests
+│ │ ├── scenarios/ # Test scenarios (100+ scenarios)
+│ │ ├── agent-test-tools/ # Mock collector, test utilities
+│ │ ├── runner-helper/ # Test runner
+│ │ └── containers/ # Docker test containers
+│ └── e2e/ # End-to-end tests
+├── docs/ # Documentation
+├── tools/ # Build and utility tools
+├── skywalking-agent/ # Built agent distribution output
+├── changes/ # Changelog
+└── dist-material/ # Distribution materials
+```
+
+## Build System
+
+### Prerequisites
+- JDK 8, 11, 17, 21, or 25
+- Maven 3.6+
+- Git (with submodule support)
+
+### Common Build Commands
+
+```bash
+# Clone with submodules
+git clone --recurse-submodules https://github.com/apache/skywalking-java.git
+
+# Or initialize submodules after clone
+git submodule init && git submodule update
+
+# Full build with tests
+./mvnw clean install
+
+# Build without tests (recommended for development)
+./mvnw clean package -Dmaven.test.skip=true
+
+# CI build with javadoc verification
+./mvnw clean verify install javadoc:javadoc
+
+# Run checkstyle only
+./mvnw checkstyle:check
+
+# Build with submodule update
+./mvnw clean package -Pall
+
+# Docker build
+make build
+make docker
+```
+
+### Maven Profiles
+- `all`: Includes git submodule update for protocol definitions
+
+### Key Build Properties
+- ByteBuddy: 1.17.6 (bytecode manipulation)
+- gRPC: 1.74.0 (communication protocol)
+- Netty: 4.1.124.Final (network framework)
+- Protobuf: 3.25.5 (protocol buffers)
+- Lombok: 1.18.42 (annotation processing)
+
+## Architecture & Key Concepts
+
+### Agent Architecture
+The agent uses ByteBuddy for bytecode manipulation at runtime:
+
+1. **Premain Entry**: `apm-agent/` contains the agent bootstrap via Java's `-javaagent` mechanism
+2. **Instrumentation Engine**: `apm-agent-core/` handles class transformation and plugin loading
+3. **Plugins**: Define which classes/methods to intercept and how to collect telemetry
+
+### Plugin Categories
+
+**1. SDK Plugins** (`apm-sniffer/apm-sdk-plugin/`)
+- Framework-specific instrumentations (70+ plugins)
+- Examples: grpc-1.x, spring, dubbo, mybatis, mongodb, redis, etc.
+- Pattern: One directory per library/framework version
+
+**2. Bootstrap Plugins** (`apm-sniffer/bootstrap-plugins/`)
+- Load at JVM bootstrap phase for JDK-level instrumentation
+- Examples: jdk-threading, jdk-http, jdk-httpclient, jdk-virtual-thread-executor
+
+**3. Optional Plugins** (`apm-sniffer/optional-plugins/`)
+- Not included by default, user must copy to plugins directory
+
+**4. Optional Reporter Plugins** (`apm-sniffer/optional-reporter-plugins/`)
+- Alternative data collection backends (e.g., Kafka)
+
+### Plugin Instrumentation APIs (v1 vs v2)
+
+The agent provides two instrumentation APIs. **V2 is recommended** for all new plugins; v1 is legacy and should only be used for maintaining existing plugins.
+
+#### V2 API (Recommended)
+
+V2 provides a `MethodInvocationContext` that is shared across all interception phases (`beforeMethod`, `afterMethod`, `handleMethodException`), allowing you to pass data (e.g., spans) between phases.
+
+**Instrumentation class (extends `ClassEnhancePluginDefineV2`):**
+```java
+public class XxxInstrumentation extends ClassInstanceMethodsEnhancePluginDefineV2 {
+ @Override
+ protected ClassMatch enhanceClass() {
+ return NameMatch.byName("target.class.Name");
+ }
+
+ @Override
+ public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
+ return new ConstructorInterceptPoint[] { ... };
+ }
+
+ @Override
+ public InstanceMethodsInterceptV2Point[] getInstanceMethodsInterceptV2Points() {
+ return new InstanceMethodsInterceptV2Point[] {
+ new InstanceMethodsInterceptV2Point() {
+ @Override
+ public ElementMatcher<MethodDescription> getMethodsMatcher() {
+ return named("targetMethod");
+ }
+
+ @Override
+ public String getMethodsInterceptorV2() {
+ return "org.apache.skywalking.apm.plugin.xxx.XxxInterceptor";
+ }
+
+ @Override
+ public boolean isOverrideArgs() {
+ return false;
+ }
+ }
+ };
+ }
+}
+```
+
+**Interceptor class (implements `InstanceMethodsAroundInterceptorV2`):**
+```java
+public class XxxInterceptor implements InstanceMethodsAroundInterceptorV2 {
+ @Override
+ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments,
+ Class<?>[] argumentsTypes, MethodInvocationContext context) {
+ // Create span and store in context for later use
+ AbstractSpan span = ContextManager.createLocalSpan("operationName");
+ context.setContext(span); // Pass to afterMethod/handleMethodException
+ }
+
+ @Override
+ public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments,
+ Class<?>[] argumentsTypes, Object ret, MethodInvocationContext context) {
+ // Retrieve span from context
+ AbstractSpan span = (AbstractSpan) context.getContext();
+ span.asyncFinish();
+ return ret;
+ }
+
+ @Override
+ public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
+ Class<?>[] argumentsTypes, Throwable t, MethodInvocationContext context) {
+ AbstractSpan span = (AbstractSpan) context.getContext();
+ span.log(t);
+ }
+}
+```
+
+**Key V2 classes:**
+- `ClassEnhancePluginDefineV2` - Base class for plugins with both instance and static methods
+- `ClassInstanceMethodsEnhancePluginDefineV2` - For instance methods only
+- `ClassStaticMethodsEnhancePluginDefineV2` - For static methods only
+- `InstanceMethodsAroundInterceptorV2` - Interceptor interface with `MethodInvocationContext`
+- `StaticMethodsAroundInterceptorV2` - Static method interceptor with context
+
+#### V1 API (Legacy)
+
+V1 uses `MethodInterceptResult` only in `beforeMethod` and has no shared context between phases. **Only use for maintaining existing legacy plugins.**
+
+**Key V1 classes (legacy):**
+- `ClassEnhancePluginDefine`
+- `ClassInstanceMethodsEnhancePluginDefine`
+- `ClassStaticMethodsEnhancePluginDefine`
+- `InstanceMethodsAroundInterceptor`
+- `StaticMethodsAroundInterceptor`
+
+### Plugin Development Rules
+
+#### Class Matching Restrictions
+
+**CRITICAL: Never use `.class` references in instrumentation definitions:**
+```java
+// WRONG - will break the agent if ThirdPartyClass doesn't exist
+takesArguments(ThirdPartyClass.class)
+byName(ThirdPartyClass.class.getName())
+
+// CORRECT - use string literals
+takesArguments("com.example.ThirdPartyClass")
+byName("com.example.ThirdPartyClass")
+```
+
+**ClassMatch options:**
+- `byName(String)`: Match by full class name (package + class name) - **preferred**
+- `byClassAnnotationMatch`: Match classes with specific annotations (does NOT support inherited annotations)
+- `byMethodAnnotationMatch`: Match classes with methods having specific annotations
+- `byHierarchyMatch`: Match by parent class/interface - **avoid unless necessary** (performance impact)
+
+#### Witness Classes/Methods
+
+Use witness classes/methods to activate plugins only for specific library versions:
+```java
+@Override
+protected String[] witnessClasses() {
+ return new String[] { "com.example.VersionSpecificClass" };
+}
+
+@Override
+protected List<WitnessMethod> witnessMethods() {
+ return Collections.singletonList(
+ new WitnessMethod("com.example.SomeClass", ElementMatchers.named("specificMethod"))
+ );
+}
+```
+
+#### Bootstrap Instrumentation
+
+For JDK core classes (rt.jar), override `isBootstrapInstrumentation()`:
+```java
+@Override
+public boolean isBootstrapInstrumentation() {
+ return true;
+}
+```
+**WARNING**: Use bootstrap instrumentation only where absolutely necessary.
+
+#### Plugin Configuration
+
+Use `@PluginConfig` annotation for custom plugin settings:
+```java
+public class MyPluginConfig {
+ public static class Plugin {
+ @PluginConfig(root = MyPluginConfig.class)
+ public static class MyPlugin {
+ public static boolean SOME_SETTING = false;
+ }
+ }
+}
+```
+Config key becomes: `plugin.myplugin.some_setting`
+
+#### Dependency Management
+
+**Plugin dependencies must use `provided` scope:**
+```xml
+<dependency>
+ <groupId>com.example</groupId>
+ <artifactId>target-library</artifactId>
+ <version>${version}</version>
+ <scope>provided</scope>
+</dependency>
+```
+
+**Agent core dependency policy:**
+- New dependencies in agent core are treated with extreme caution
+- Prefer using existing imported libraries already in the project
+- Prefer JDK standard libraries over third-party libraries
+- Plugins should rely on the target application's libraries (provided scope), not bundle them
+
+### Tracing Concepts
+
+#### Span Types
+- **EntrySpan**: Service provider/endpoint (HTTP server, MQ consumer)
+- **LocalSpan**: Internal method (no remote calls)
+- **ExitSpan**: Client call (HTTP client, DB access, MQ producer)
+
+#### SpanLayer (required for EntrySpan/ExitSpan)
+- `DB`: Database access
+- `RPC_FRAMEWORK`: RPC calls (not ordinary HTTP)
+- `HTTP`: HTTP calls
+- `MQ`: Message queue
+- `UNKNOWN`: Default
+
+#### Context Propagation
+- **ContextCarrier**: Cross-process propagation (serialize to headers/attachments)
+- **ContextSnapshot**: Cross-thread propagation (in-memory, no serialization)
+
+#### Required Span Attributes
+For EntrySpan and ExitSpan, always set:
+```java
+span.setComponent(ComponentsDefine.YOUR_COMPONENT);
+span.setLayer(SpanLayer.HTTP); // or DB, MQ, RPC_FRAMEWORK
+```
+
+#### Special Tags for OAP Analysis
+| Tag | Purpose |
+|-----|---------|
+| `http.status_code` | HTTP response code (integer) |
+| `db.type` | Database type (e.g., "sql", "redis") |
+| `db.statement` | SQL/query statement (enables slow query analysis) |
+| `cache.type`, `cache.op`, `cache.cmd`, `cache.key` | Cache metrics |
+| `mq.queue`, `mq.topic` | MQ metrics |
+
+### Meter Plugin APIs
+
+For collecting numeric metrics (alternative to tracing):
+```java
+// Counter
+Counter counter = MeterFactory.counter("metric_name")
+ .tag("key", "value")
+ .mode(Counter.Mode.INCREMENT)
+ .build();
+counter.increment(1d);
+
+// Gauge
+Gauge gauge = MeterFactory.gauge("metric_name", () -> getValue())
+ .tag("key", "value")
+ .build();
+
+// Histogram
+Histogram histogram = MeterFactory.histogram("metric_name")
+ .steps(Arrays.asList(1, 5, 10))
+ .build();
+histogram.addValue(3);
+```
+
+### Data Flow
+1. Agent attaches to JVM via `-javaagent` flag
+2. ByteBuddy transforms target classes at load time
+3. Interceptors collect span/trace data on method entry/exit
+4. Data is buffered via DataCarrier
+5. gRPC reporter sends data to OAP backend
+
+## Code Style & Conventions
+
+### Checkstyle Rules (enforced via `apm-checkstyle/checkStyle.xml`)
+
+**Prohibited patterns:**
+- No `System.out.println` - use proper logging
+- No `@author` tags - ASF projects don't use author annotations
+- No Chinese characters in source files
+- No tab characters (use 4 spaces)
+- No star imports (`import xxx.*`)
+- No unused or redundant imports
+
+**Required patterns:**
+- `@Override` annotation required for overridden methods
+- `equals()` and `hashCode()` must be overridden together
+- Apache 2.0 license header on all source files
+
+**Naming conventions:**
+- Constants/static variables: `UPPER_CASE_WITH_UNDERSCORES`
+- Package names: `org.apache.skywalking.apm.*` or `test.apache.skywalking.apm.*`
+- Type names: `PascalCase`
+- Local variables/parameters/members: `camelCase`
+- Plugin directories: `{framework}-{version}-plugin`
+- Instrumentation classes: `*Instrumentation.java`
+- Interceptor classes: `*Interceptor.java`
+
+**File limits:**
+- Max file length: 3000 lines
+
+### Lombok Usage
+Use Lombok annotations for boilerplate code:
+- `@Getter`, `@Setter`, `@Data`
+- `@Builder`
+- `@Slf4j` for logging
+
+## Testing
+
+### Test Frameworks
+- JUnit 4.12 for unit tests
+- Mockito 5.0.0 for mocking
+
+### Test Categories
+
+**Unit Tests** (in each module's `src/test/java`)
+- Standard JUnit tests
+- Pattern: `*Test.java`
+
+**Plugin E2E Tests** (`test/plugin/scenarios/`)
+- 100+ test scenarios for plugin validation
+- Docker-based testing with actual frameworks
+- Pattern: `{framework}-{version}-scenario`
+
+**End-to-End Tests** (`test/e2e/`)
+- Full system integration testing
+
+### Running Tests
+```bash
+# Unit tests
+./mvnw test
+
+# Full verification including checkstyle
+./mvnw clean verify
+
+# Skip tests during build
+./mvnw package -Dmaven.test.skip=true
+```
+
+### Plugin Test Framework
+
+The plugin test framework verifies plugin functionality using Docker containers with real services and a mock OAP backend.
+
+#### Environment Requirements
+- MacOS/Linux
+- JDK 8+
+- Docker & Docker Compose
+
+#### Test Case Structure
+
+**JVM-container (preferred):**
+```
+{scenario}-scenario/
+├── bin/
+│ └── startup.sh # JVM startup script (required)
+├── config/
+│ └── expectedData.yaml # Expected trace/meter/log data
+├── src/main/java/... # Test application code
+├── pom.xml
+├── configuration.yml # Test case configuration
+└── support-version.list # Supported versions (one per line)
+```
+
+**Tomcat-container:**
+```
+{scenario}-scenario/
+├── config/
+│ └── expectedData.yaml
+├── src/main/
+│ ├── java/...
+│ └── webapp/WEB-INF/web.xml
+├── pom.xml
+├── configuration.yml
+└── support-version.list
+```
+
+#### Key Configuration Files
+
+**configuration.yml:**
+```yaml
+type: jvm # or tomcat
+entryService: http://localhost:8080/case # Entry endpoint (GET)
+healthCheck: http://localhost:8080/health # Health check endpoint (HEAD)
+startScript: ./bin/startup.sh # JVM-container only
+runningMode: default # default|with_optional|with_bootstrap
+withPlugins: apm-spring-annotation-plugin-*.jar # For optional/bootstrap modes
+environment:
+ - KEY=value
+dependencies: # External services (docker-compose style)
+ mysql:
+ image: mysql:8.0
+ hostname: mysql
+ environment:
+ - MYSQL_ROOT_PASSWORD=root
+```
+
+**support-version.list:**
+```
+# One version per line, use # for comments
+# Only include ONE version per minor version (not all patch versions)
+4.3.6
+4.4.1
+4.5.0
+```
+
+**expectedData.yaml:**
+
+Trace and meter expectations are typically in separate scenarios.
+
+*For tracing plugins:*
+```yaml
+segmentItems:
+ - serviceName: your-scenario
+ segmentSize: ge 1 # Operators: eq, ge, gt, nq
+ segments:
+ - segmentId: not null
+ spans:
+ - operationName: /your/endpoint
+ parentSpanId: -1 # -1 for root span
+ spanId: 0
+ spanLayer: Http # Http, DB, RPC_FRAMEWORK, MQ, CACHE, Unknown
+ spanType: Entry # Entry, Exit, Local
+ startTime: nq 0
+ endTime: nq 0
+ componentId: 1
+ isError: false
+ peer: '' # Empty string for Entry/Local, required for Exit
+ skipAnalysis: false
+ tags:
+ - {key: url, value: not null}
+ - {key: http.method, value: GET}
+ - {key: http.status_code, value: '200'}
+ logs: []
+ refs: [] # SegmentRefs for cross-process/cross-thread
+```
+
+*For meter plugins:*
+```yaml
+meterItems:
+ - serviceName: your-scenario
+ meterSize: ge 1
+ meters:
+ - meterId:
+ name: test_counter
+ tags:
+ - {name: key1, value: value1} # Note: uses 'name' not 'key'
+ singleValue: gt 0 # For counter/gauge
+ - meterId:
+ name: test_histogram
+ tags:
+ - {name: key1, value: value1}
+ histogramBuckets: # For histogram
+ - 0.0
+ - 1.0
+ - 5.0
+ - 10.0
+```
+
+**startup.sh (JVM-container):**
+```bash
+#!/bin/bash
+home="$(cd "$(dirname $0)"; pwd)"
+# ${agent_opts} is REQUIRED - contains agent parameters
+java -jar ${agent_opts} ${home}/../libs/your-scenario.jar &
+```
+
+#### Running Plugin Tests Locally
+
+```bash
+# Run a specific scenario
+bash ./test/plugin/run.sh -f {scenario_name}
+
+# IMPORTANT: Rebuild agent if apm-sniffer code changed
+./mvnw clean package -DskipTests -pl apm-sniffer
+
+# Use generator to create new test case
+bash ./test/plugin/generator.sh
+```
+
+#### Adding Tests to CI
+
+Add scenario to the appropriate `.github/workflows/` file:
+- Use `python3 tools/select-group.py` to find the file with fewest cases
+- **JDK 8 tests**: `plugins-test.<n>.yaml`
+- **JDK 17 tests**: `plugins-jdk17-test.<n>.yaml`
+- **JDK 21 tests**: `plugins-jdk21-test.<n>.yaml`
+- **JDK 25 tests**: `plugins-jdk25-test.<n>.yaml`
+
+```yaml
+matrix:
+ case:
+ - your-scenario-scenario
+```
+
+#### Test Code Package Naming
+- Test code: `org.apache.skywalking.apm.testcase.*`
+- Code to be instrumented: `test.org.apache.skywalking.apm.testcase.*`
+
+## Git Submodules
+
+The project uses submodules for protocol definitions:
+- `apm-protocol/apm-network/src/main/proto` - skywalking-data-collect-protocol
+
+Always use `--recurse-submodules` when cloning or update submodules manually:
+```bash
+git submodule init && git submodule update
+```
+
+## IDE Setup (IntelliJ IDEA)
+
+1. Import as Maven project
+2. Run `./mvnw compile -Dmaven.test.skip=true` to generate protobuf sources
+3. Mark generated source folders:
+ - `*/target/generated-sources/protobuf/java`
+ - `*/target/generated-sources/protobuf/grpc-java`
+4. Enable annotation processing for Lombok
+
+## Key Files for Understanding the Codebase
+
+- `apm-sniffer/apm-agent/` - Agent entry point (premain)
+- `apm-sniffer/apm-agent-core/src/main/java/.../enhance/` - Instrumentation engine
+- `apm-sniffer/apm-agent-core/src/main/java/.../plugin/` - Plugin loading system
+- `apm-sniffer/apm-sdk-plugin/` - All standard plugins (reference implementations)
+- `apm-sniffer/config/agent.config` - Default agent configuration
+
+## Common Development Tasks
+
+### Adding a New Plugin
+1. Create directory in `apm-sniffer/apm-sdk-plugin/{framework}-{version}-plugin/`
+2. Implement instrumentation class using **V2 API** (e.g., extend `ClassInstanceMethodsEnhancePluginDefineV2`)
+3. Implement interceptor class using **V2 API** (e.g., implement `InstanceMethodsAroundInterceptorV2`)
+4. Register plugin in `skywalking-plugin.def` file
+5. Add test scenario in `test/plugin/scenarios/`
+
+### Adding an Optional Plugin
+1. Create in `apm-sniffer/optional-plugins/`
+2. Update documentation in `docs/en/setup/service-agent/java-agent/Optional-plugins.md`
+
+### Modifying Agent Configuration
+1. Edit `apm-sniffer/config/agent.config`
+2. Update documentation if adding new options
+
+## Documentation
+
+- `docs/en/setup/service-agent/java-agent/` - Main agent documentation
+- `docs/en/setup/service-agent/java-agent/Plugin-list.md` - Complete plugin list
+- `docs/en/setup/service-agent/java-agent/Optional-plugins.md` - Optional plugins guide
+- `CHANGES.md` - Changelog (update when making changes)
+
+## Community
+
+- GitHub Issues: https://github.com/apache/skywalking-java/issues
+- Mailing List: dev@skywalking.apache.org
+- Slack: #skywalking channel at Apache Slack
+
+## Submitting Pull Requests
+
+### Branch Strategy
+- **Never work directly on main branch**
+- Create a new branch for your changes
+
+### PR Template
+Follow `.github/PULL_REQUEST_TEMPLATE` based on change type:
+- **Bug fix**: Add unit test, explain bug cause and fix
+- **New plugin**: Add test case, component ID in OAP, logo in UI repo
+- **Performance improvement**: Add benchmark with results, link to theory/discussion
+- **New feature**: Link design doc if non-trivial, update docs, add tests
+
+### PR Requirements
+- Follow Apache Code of Conduct
+- Include updated documentation for new features
+- Include tests for new functionality
+- Reference original issue (e.g., "Resolves #123")
+- Update `CHANGES.md` for user-facing changes
+- Pass all CI checks (checkstyle, tests, license headers)
+
+### PR Description
+- Bug fixes: Explain the bug and how it's fixed, add regression test
+- New features: Link to design doc if non-trivial, update docs, add tests
+- Do NOT add AI assistant as co-author
+
+## CI/CD
+
+GitHub Actions workflows:
+- **CI**: Multi-OS (Ubuntu, macOS, Windows), Multi-Java (8, 11, 17, 21, 25)
+- **Plugin Tests**: Parallel E2E tests for all plugins
+- **E2E Tests**: Full system integration
+- **Docker Publishing**: Multi-variant images
+
+## Tips for AI Assistants
+
+1. **Use V2 instrumentation API**: Always use V2 classes (`ClassEnhancePluginDefineV2`, `InstanceMethodsAroundInterceptorV2`) for new plugins; V1 is legacy
+2. **NEVER use `.class` references**: In instrumentation definitions, always use string literals for class names (e.g., `byName("com.example.MyClass")` not `byName(MyClass.class.getName())`)
+3. **Always set component and layer**: For EntrySpan and ExitSpan, always call `setComponent()` and `setLayer()`
+4. **Prefer `byName` for class matching**: Avoid `byHierarchyMatch` unless necessary (causes performance issues)
+5. **Use witness classes for version-specific plugins**: Implement `witnessClasses()` or `witnessMethods()` to activate plugins only for specific library versions
+6. **Always check submodules**: Protocol changes may require submodule updates
+7. **Generate sources first**: Run `mvnw compile` before analyzing generated code
+8. **Respect checkstyle**: No System.out, no @author, no Chinese characters
+9. **Follow plugin patterns**: Use existing V2 plugins as templates
+10. **Use Lombok**: Prefer annotations over boilerplate code
+11. **Test both unit and E2E**: Different test patterns for different scopes
+12. **Plugin naming**: Follow `{framework}-{version}-plugin` convention
+13. **Shaded dependencies**: Core dependencies are shaded to avoid classpath conflicts
+14. **Java version compatibility**: Agent core must maintain Java 8 compatibility, but individual plugins may target higher JDK versions (e.g., jdk-httpclient-plugin for JDK 11+, virtual-thread plugins for JDK 21+)
+15. **Bootstrap instrumentation**: Only use for JDK core classes, and only when absolutely necessary
+16. **Register plugins**: Always add plugin definition to `skywalking-plugin.def` file