ecapture Agent Skills & AI Rules

GitHub

Capture SSL/TLS plaintext with eBPFโ€”no MITM proxy or custom CA installation. Supports Linux and Android on x86_64 and arm64.

15,523 stars C C 32 files ยท ~56,911 tokens #android#boringssl#ebpf#gnutls#golang#linux#loong64#network-analysis
RAW Rules
1 Discovered Rules โ€ข ~3,525 Estimated Tokens
Quick:
Loading skill content...

AI Agent Protocol & Instructions

AGENTS.md root-instruction ~3,525 tokens
Raw
# AGENTS.md โ€” eCapture repository guide

This is the canonical repository guide for coding agents. Tool-specific files
such as `CLAUDE.md` and `.github/copilot-instructions.md` are compatibility
entry points, not separate sources of project truth.

## How to use this guide

- These instructions apply to the entire repository unless a deeper
  `AGENTS.md` narrows them.
- For runtime behavior, trust source code and tests. For build behavior, trust
  `go.mod`, `Makefile`, `variables.mk`, `functions.mk`, and current workflows.
  For maintained E2E behavior, trust `test/e2e/README.md` and its harness.
- For architecture/runtime/output work, read `docs/agent/architecture.md` and
  `docs/agent/output-pipeline.md`.
- For probes, ABI, CLI config, or generated protocols, read
  `docs/agent/probe-development.md`.
- For build, formatting, lint, tests, E2E, or CI, read
  `docs/agent/build-test.md`.
- Some older prose may lag the code or build files. This guide and current
  implementation win on factual conflicts.
- Keep this file and the relevant detailed guide synchronized when a change
  invalidates a command, path, invariant, or known limitation.

## Product priorities

- TLS capture is the project's core focus. Give the TLS, GoTLS, and GnuTLS
  modules high priority, including support for OpenSSL, BoringSSL, Go TLS, and
  GnuTLS. Protect their correctness, compatibility, and end-to-end behavior
  when planning changes, reviews, and verification.
- Bash, Zsh, MySQL, and other non-core modules have lower priority. Maintain
  them, but prioritize core TLS functionality when work or coverage must be
  allocated.
- In user-facing material such as a promotional article, devote roughly 80%
  of the attention to the core TLS modules and 20% to non-core modules. This
  is an emphasis guideline, not a fixed quota for code or tests.

### Optional machine-local context

If `AGENTS.local.md` exists at the repository root, read it before choosing an
execution environment or running build, test, cross-compilation, or remote-host
operations. It may refine *where* commands run, but it must not override this
repository's safety, supported-platform, or verification requirements.

- `AGENTS.local.md` is optional and must remain uncommitted.
- Never require another contributor or a cloud agent to have it.
- Never copy its machine details into commits, logs, issues, or pull requests.
- Start from `AGENTS.local.example.md`; do not store credentials in either
  file.

## Non-negotiable platform boundary

eCapture may be edited anywhere, but compilation, linking, linting, tests,
eBPF generation, and execution require Linux. Android artifacts are also
built on a Linux host.

- Runtime targets: Linux on `x86_64`, `aarch64`, or `loongarch64`; Android on
  `x86_64` or `aarch64`.
- Minimum kernels: x86_64 >= 4.18; aarch64 >= 5.5; Linux loongarch64 >= 6.6.
- Loading probes requires root or the capabilities documented in
  `docs/minimum-privileges.md`. Maintained E2E harnesses have stricter root
  requirements.
- macOS and Windows are editing, formatting, and read-only inspection
  environments. Do not run `make`, Go builds/tests, lint, eBPF generation, or
  E2E there.
- Before using a remote Linux builder, verify its OS, architecture, checkout
  path, branch, commit, worktree, submodules, and synchronization state. Never
  assume local edits are present remotely or overwrite remote work.
- New or changed build/test scripts must reject unsupported OS, architecture,
  and kernel combinations before doing eBPF work.
- If the required Linux/root environment is unavailable, report exactly what
  was not run; never claim an unexecuted build or runtime passed.

## Fast mental model

eCapture attaches uprobes, kprobes, and TC programs, reads perf/ring-buffer
events, decodes their binary ABI in Go, and routes validated events to output
handlers and writers.

```text
main.go -> cli.Start() -> Cobra RunE -> runProbe()
  -> config.Validate() -> factory.CreateProbe()
  -> Probe.Initialize() / Start()
  -> embedded eBPF asset + ebpfmanager
  -> perf/ringbuf sample -> EventDecoder.Decode()
  -> optional module-private EventPreprocessor
  -> events.Dispatcher -> text/keylog/pcapng handler -> ByteSink
                       -> low-latency pcapng -> decrypt SDK -> text ByteSink
                       -> typed eCaptureQ EVENT publisher
```

`runProbe` owns signal handling and runtime reload orchestration. A concrete
probe owns its eBPF manager, attachments, maps/decoders, and mode-specific
handlers. `base.BaseProbe` owns shared logging, the default text handler,
readers, dispatch, reorder support, and common shutdown behavior.

See `docs/agent/architecture.md` for the CLI/probe matrix, repository map, and
package ownership.

## Critical cross-file invariants

- CLI imports trigger each probe's `register.go` `init()`. A seemingly unused
  import may be required for factory registration.
- Treat attachment and event plumbing as one atomic change:

  ```text
  C SEC section          <-> manager.Probe.Section
  C BPF function         <-> EbpfFuncName
  target symbol/offset   <-> AttachToFuncName / UAddress
  C map identifier       <-> manager.Map.Name / decoder registration
  C global variable      <-> manager.ConstantEditor
  C event layout         <-> Go event struct / DecodeFromBytes
  ```

- Preserve C/Go event field order, signedness, widths, byte order, arrays, and
  padding. Validate lengths before slicing. Perf samples may contain trailing
  alignment padding, so do not identify variants by exact length alone.
- `Configuration.Validate()` may run more than once and must be idempotent.
- Concrete probes must follow BaseProbe lifecycle ordering. Track every reader;
  custom reader loops must use `TrackReader` and `GoReaderLoop` equivalents so
  shutdown can unblock and join them before closing handlers.
- Dispatcher fan-out is synchronous and unordered. Multiple readers may call
  one handler concurrently; handlers/writers must be concurrency-safe and
  tolerate idempotent close. Perf reorder is per map/reader, not global.
- Module-private records such as OpenSSL connection metadata are consumed
  before output dispatch; they enrich captured output events instead of
  becoming standalone text or typed events.
- `--logaddr` is operational logging only. For TLS, GoTLS, and GnuTLS,
  `--eventaddr` is the primary captured-event destination for text (hook or
  pcapng source), keylog, and pcapng. eCaptureQ is an additive typed publisher,
  not a ByteSink.
- Linux production tags are `linux,netgo,ebpfassets,dynamic`; Android uses
  `ecap_android,netgo,ebpfassets,dynamic`. Preserve CO-RE and non-CO-RE paths.
- Never hand-edit or commit generated `bytecode/*.o`, `bytecode/*.d`,
  `.build/`, `assets/ebpf_probe_<target>_<goarch>_bindata.go`, generated LoongArch
  `vmlinux.h`, `bin/ecapture`, or `coverage.out`. Regenerate Protobuf and
  stringer outputs from their sources.

## Task guides and verification

Before changing a probe, event ABI, build flow, or test harness, read the
corresponding detailed guide listed above. At minimum:

- Documentation-only changes: verify paths, commands, links, and source facts.
- Go logic: format touched files, run targeted tests, and complete full race
  plus production-tag lint gates when Linux is available.
- Event decoders/ABI: add byte-level malformed, short, and padded-sample tests.
- eBPF C or manager setup: clean-build both CO-RE and non-CO-RE variants for
  affected architectures.
- CLI/output/capture modes: run the relevant strict E2E case on a real
  Linux/Android kernel.
- OpenSSL/BoringSSL mappings: test mapping, both asset variants, and the real
  library version.
- CI changes: validate least privilege and trusted/untrusted workflow
  boundaries.

Canonical commands, prerequisites, build races, E2E semantics, and the full
verification matrix live in `docs/agent/build-test.md`.

## Code conventions

- Module/import path: `github.com/gojue/ecapture/v2`; preserve the `/v2`
  suffix in new imports.
- Keep changes focused and follow the nearest working implementation. Probe
  implementations are not perfectly uniform, so do not copy one blindly.
- Do not add files unless necessary for the requested change. Prefer reusing
  existing code, scripts, and tests, and keep changes as small as practical.
  Avoid unrelated refactors and unnecessary helper layers.
- In probe/domain lifecycle code, prefer structured constructors and codes in
  `internal/errors`, adding context where useful. Preserve normal `%w`
  wrapping at boundaries where that is the local pattern.
- Use `internal/logger` inside probes/runtime code and zerolog in the CLI
  layer. Do not add ad-hoc `fmt.Println` or standard `log` calls for runtime
  logging.
- Format only touched files: `gofmt`/`goimports` for Go and the repository's
  exact clang-format style for C. `make format` is a broad C-only target.
- Keep eBPF verifier limits, bounded loops, stack use, helper availability,
  and old-kernel compatibility in mind.
- Preserve the `github.com/google/gopacket` replacement in `go.mod` unless a
  maintainer explicitly directs otherwise.
- Root `LICENSE` is Apache-2.0. Preserve each file's existing SPDX header;
  some imported or kernel-facing headers use other compatible licenses. Do
  not propagate stale prose that says AGPL, and leave license changes to a
  maintainer-directed task.

## Safety, Git, and release boundaries

- Captured logs, commands, SQL, keylogs, pcap/pcapng files, and test artifacts
  may contain secrets. Never commit or paste them unredacted.
- Preserve unrelated worktree changes. Do not stage, commit, push, open a PR,
  publish, tag, or release unless the user explicitly requests it.
- Name new branches with a conventional purpose prefix such as `feat/`,
  `bugfix/`, `docs/`, `test/`, or `chore/`, followed by a concise kebab-case
  description.
- The default branch is `master`. If asked to commit, follow
  `<package>: <what changed>`, keep the subject <= 70 characters, and explain
  why in the body as documented in `CONTRIBUTING.md`. Write the entire commit
  message in English unless the user explicitly requests a specific other
  language.
- Write GitHub pull request titles and bodies in English unless the user
  explicitly requests a specific other language.
- Keep ordinary fork-PR build/test jobs read-only and secret-free. Keep
  scanner-specific write permissions narrowly scoped. Any trusted write-back
  workflow must not execute untrusted fork code or its artifacts.
- Do not weaken security checks, verifier failures, or E2E assertions merely
  to make CI green.

## Known state and traps

- GnuTLS uses versioned C assets selected from the detected library patch
  release; keep the supported version-to-asset table synchronized with
  `kern/gnutls_*_kern.c`.
- Runtime reload reattaches process-lifetime output dependencies and creates a
  fresh probe context, but retains the original factory probe type; it is not
  a cross-probe hot-swap facility.
- Shared serializable probe fields are applied through
  `internal/config.CommonConfig` for every Cobra command and HTTP config
  factory. Keep process-lifetime output dependencies out of that copy path.
- HTTP reload distinguishes omitted captured-event destination/rotation fields
  from explicit empty/zero values. Omitted fields inherit from the active
  generation, while runtime logger and typed eCaptureQ dependencies are
  reattached separately.
- Probe registration currently discards duplicate-registration errors.
- Every probe uses the shared bytecode selector. `--btf=0` resolves kernel BTF
  once per process, while explicit modes fail when the linked asset set cannot
  satisfy them. Generated non-CO-RE objects use `*_kern_noncore.o`.
- `pkg/event_processor` and `internal/output/encoders` are not in the current
  production CLI event path.
- `TARGET_ARCH` selects the build artifact architecture (`amd64`, `arm64`,
  or `loong64`). `CROSS_ARCH` is a compatible alias used only when
  `TARGET_ARCH` is unset.
- Non-CO-RE compilation must retain Kbuild's `-fms-extensions` support for
  tagged anonymous fields in Linux 6.19+ headers; dropping it breaks field
  access and structure layout on Linux 7.x.
  LoongArch CO-RE needs the same support for generated runtime BTF headers.
  x86 non-CO-RE headers also require `CC_USING_FENTRY` when function tracing
  is configured; do not enable native `-pg`/`-mfentry` instrumentation for BPF.
- `make build` is not Go-only. Switching architecture, Android, or asset modes
  still requires a clean serial validation even though libpcap, bytecode, Go
  intermediates, and generated asset names are architecture-isolated. The
  `assets`, `assets_core`, and `assets_noncore` targets for one architecture
  write the same generated asset; do not request them together in one parallel
  make invocation.
- Linux release builds share an Ubuntu 24.04 x86_64 job. Loong64 joins the
  same release entry point and PR architecture matrix; only amd64/arm64
  produce Android artifacts. Loong64 is cross-built with `TARGET_ARCH=loong64`
  and the repository's LLVM 22.1.8 wrappers. Do not substitute `loong64` for the
  `loongarch64-linux-gnu` C target or `loongarch` Kbuild architecture.
- Native Linux/loong64 production builds also support Debian 13+ with Clang/
  LLVM 22.1.8, versioned LLD 22 linking and native multiarch libraries.
  The Clang driver remains Go's external linker entry point.
  `builder/init_env.sh` prepares dependencies and kernel inputs. Native CO-RE may use the running kernel's
  BTF; non-CO-RE still requires prepared LoongArch kernel headers. Building
  against packaged headers does not establish non-CO-RE compatibility with a
  different running kernel. See `docs/loong64-support.md`.
- The dedicated LoongArch E2E job shares `e2e.yml` push/PR/manual triggers,
  but only trusted repository refs enter the host. It builds CO-RE at the event
  SHA with LLVM 22.1.8 and runs OpenSSL/GoTLS directly from that checkout through
  a fixed sudo Shell entry point. Harness output streams live to Actions.
  Fork PRs retain hosted checks. Root-owned hooks enforce trusted refs and
  clean job processes, caches and owned TC state; there is no separate E2E unit.

## Focused references

- Architecture and runtime: `docs/agent/architecture.md`
- Probe and ABI development: `docs/agent/probe-development.md`
- Build and verification: `docs/agent/build-test.md`
- User-facing behavior: `README.md`, `README-zh_Hans.md`
- Build sources: `Makefile`, `variables.mk`, `functions.mk`, `builder/init_env.sh`
- E2E: `test/e2e/README.md`, `test/e2e/QUICK_REFERENCE.md`
- Privileges/security: `docs/minimum-privileges.md`, `SECURITY.md`
- Event forwarding: `docs/event-forward-api.md`, `pkg/ecaptureq/README.md`
- Generated/config docs: `protobuf/README.md`, `protobuf/PROTOCOLS.md`, `docs/remote-config-update-api.md`
- GitHub Copilot PR agent: `.github/agents/pr-agent.agent.md`