Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .agents/skills/ccg/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
name: ccg
description: "Build, update, inspect, and search code-context-graph graphs and route to specialized CCG workflows. Use when a task needs CCG setup, graph freshness, algorithm or feature-pipeline understanding, exact symbol or relationship lookup, annotation-aware full-text search, safe full or scoped synchronization, MCP graph queries, combining direct source lookup with CCG before an absence or completeness claim, or selection among CCG analysis, docs, annotation, and namespace skills. Do not use for a simple file or string lookup when grep/read is sufficient."
---

# CCG Runtime Adapter

Read the [canonical CCG skill](../../../skills/ccg/SKILL.md) completely before
acting. Resolve its linked resources relative to the canonical skill directory
and follow its routing, safety, search, and completion instructions for the
current task.
112 changes: 6 additions & 106 deletions .claude/skills/ccg/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,111 +1,11 @@
---
name: ccg
description: code-context-graph — build code knowledge graphs and search. Core entry point for parsing, building, and querying code graphs.
description: "Build, update, inspect, and search code-context-graph graphs and route to specialized CCG workflows. Use when a task needs CCG setup, graph freshness, algorithm or feature-pipeline understanding, exact symbol or relationship lookup, annotation-aware full-text search, safe full or scoped synchronization, MCP graph queries, combining direct source lookup with CCG before an absence or completeness claim, or selection among CCG analysis, docs, annotation, and namespace skills. Do not use for a simple file or string lookup when grep/read is sufficient."
---

# code-context-graph — Core Build & Search
# CCG Runtime Adapter

Local code analysis tool that parses codebases via Tree-sitter into a knowledge graph with 12 language support and annotation-powered search.

## Subcommands

| Command | Description | Example |
| ----------------------------------- | ------------------------------------------- | ----------------------------------------- |
| `build [dir]` | Parse directory, build graph + search index | `ccg build .` |
| `build --exclude <pat>` | Exclude files/paths (repeatable) | `ccg build --exclude vendor` |
| `build --no-recursive [dir]` | Only parse top-level directory | `ccg build --no-recursive .` |
| `update [dir]` | Incremental sync (changed files only) | `ccg update .` |
| `status` | Show graph statistics (nodes/edges/files) | `ccg status` |
| `search <query>` | FTS keyword search (includes @annotations) | `ccg search "authentication"` |
| `search --path <prefix> <query>` | Scoped search by path prefix | `ccg search --path internal/auth "login"` |
| `languages` | List supported languages and extensions | `ccg languages` |
| `example [language]` | Show annotation writing example | `ccg example go` |
| `tags` | Show all annotation tag reference | `ccg tags` |
| `serve` | Start MCP server (stdio by default) | `ccg serve` |
| `serve --transport streamable-http` | Start MCP server over HTTP | `ccg serve --transport streamable-http` |
| `serve --http-addr :9090` | Custom HTTP listen address | `ccg serve --http-addr :9090` |
| `serve --stateless` | Stateless session mode | `ccg serve --stateless` |
| `serve --allow-repo <pat>` | Allowed repos for webhook sync (repeatable) | `ccg serve --allow-repo "org/*"` |
| `serve --webhook-secret <s>` | HMAC secret for webhook verification | `ccg serve --webhook-secret mysecret` |
| `serve --repo-root <dir>` | Root dir for cloned repos | `ccg serve --repo-root /data/repos` |

## Execution

Parse the user's input after `ccg` and run via Bash:

```bash
ccg {subcommand} {args}
```

If the binary doesn't exist, build it first:

```bash
CGO_ENABLED=1 go build -tags "fts5" -o ccg ./cmd/ccg/
```

## When no arguments provided

Show available commands:

```
Available ccg commands:
ccg build [dir] — Build code knowledge graph
ccg update [dir] — Incremental update
ccg status — Graph statistics
ccg search <query> — Full-text search (annotations included)
ccg languages — List supported languages
ccg serve — Start MCP server

Related skills:
/ccg-analyze — Code analysis & architecture
/ccg-annotate — Annotation system & AI workflow
/ccg-docs — Documentation & RAG indexing
```

## MCP Tools (7)

| Tool | Description |
| ----------------------- | ---------------------------------------------------------- |
| `parse_project` | Parse source files |
| `build_or_update_graph` | Full/incremental build with postprocessing |
| `run_postprocess` | Run flows/communities/search rebuild |
| `get_node` | Get node by qualified name |
| `search` | Full-text search |
| `query_graph` | Predefined graph queries (callers, callees, imports, etc.) |
| `list_graph_stats` | Node/edge/file counts |

## Smart Behaviors

### Auto-rebuild when stale

If `ccg.db` doesn't exist or the user asks to analyze the project, run `ccg build .` first.

### Annotation-aware search

When the user asks about business concepts, use FTS search which includes annotation content:

- `@intent` — function purpose/goal
- `@domainRule` — business rules
- `@sideEffect` — side effects
- `@mutates` — state changes
- `@index` — file/package level description

Example: user asks "결제 관련 코드" → `ccg search "결제"` finds functions annotated with payment-related @intent/@domainRule.

## Graph Schema

Node kinds: `function`, `class`, `type`, `test`, `file`

Edge kinds: `calls`, `imports_from`, `inherits`, `implements`, `contains`, `tested_by`, `depends_on`, `references`

## Supported Languages (12)

Go, Python, TypeScript, Java, Ruby, JavaScript, C, C++, Rust, Kotlin, PHP, Lua

## HTTP Endpoints (Streamable HTTP mode)

| Endpoint | Method | Description |
| ---------- | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| `/mcp` | POST/GET/DELETE | MCP protocol endpoint (session-based) |
| `/health` | GET | Health check — returns `{"status":"ok"}` |
| `/webhook` | POST | GitHub / Gitea webhook receiver (when `--allow-repo` configured). Supports `X-Hub-Signature-256` and `X-Gitea-Signature` HMAC verification. |
Read the [canonical CCG skill](../../../skills/ccg/SKILL.md) completely before
acting. Resolve its linked resources relative to the canonical skill directory
and follow its routing, safety, search, and completion instructions for the
current task.
37 changes: 37 additions & 0 deletions internal/adapters/inbound/cli/skills_contract_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,43 @@ func TestProjectSkillsDeclareRuntimeContract(t *testing.T) {
}
}

func TestCoreSkillHasClaudeAndAntigravityProjectAdapters(t *testing.T) {
repoRoot := filepath.Join("..", "..", "..", "..")
canonicalPath := filepath.Join(repoRoot, "skills", "ccg", "SKILL.md")
canonicalRaw, err := os.ReadFile(canonicalPath)
if err != nil {
t.Fatalf("read canonical skill: %v", err)
}
canonical := parseSkillContract(t, canonicalRaw)

adapters := map[string]string{
"claude": filepath.Join(repoRoot, ".claude", "skills", "ccg", "SKILL.md"),
"antigravity": filepath.Join(repoRoot, ".agents", "skills", "ccg", "SKILL.md"),
}
for runtime, path := range adapters {
t.Run(runtime, func(t *testing.T) {
raw, err := os.ReadFile(path)
if err != nil {
t.Fatalf("read runtime adapter: %v", err)
}
adapter := parseSkillContract(t, raw)
if adapter.Name != canonical.Name {
t.Errorf("name = %q, want canonical name %q", adapter.Name, canonical.Name)
}
if adapter.Description != canonical.Description {
t.Errorf("description differs from canonical discovery contract")
}
if !strings.Contains(string(raw), "[canonical CCG skill](../../../skills/ccg/SKILL.md)") {
t.Error("adapter does not route to the canonical CCG skill")
}
linkedPath := filepath.Clean(filepath.Join(filepath.Dir(path), "..", "..", "..", "skills", "ccg", "SKILL.md"))
if linkedPath != filepath.Clean(canonicalPath) {
t.Errorf("canonical link resolves to %q, want %q", linkedPath, canonicalPath)
}
})
}
}

func TestProjectSkillsDoNotAdvertiseRemovedCommands(t *testing.T) {
for _, command := range []string{"ccg index", "ccg languages", "ccg example", "ccg tags"} {
matches, err := filepath.Glob(filepath.Join("..", "..", "..", "..", "skills", "*", "SKILL.md"))
Expand Down
52 changes: 42 additions & 10 deletions skills/ccg/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
---
name: ccg
description: "Build, update, inspect, and search code-context-graph graphs and route to specialized CCG workflows. Use when a task needs CCG setup, graph freshness, algorithm or feature-pipeline understanding, exact symbol or relationship lookup, annotation-aware full-text search, safe full or scoped synchronization, MCP graph queries, or selection among CCG analysis, docs, annotation, and namespace skills. Do not use for a simple file or string lookup when grep/read is sufficient."
description: "Build, update, inspect, and search code-context-graph graphs and route to specialized CCG workflows. Use when a task needs CCG setup, graph freshness, algorithm or feature-pipeline understanding, exact symbol or relationship lookup, annotation-aware full-text search, safe full or scoped synchronization, MCP graph queries, combining direct source lookup with CCG before an absence or completeness claim, or selection among CCG analysis, docs, annotation, and namespace skills. Do not use for a simple file or string lookup when grep/read is sufficient."
metadata:
version: 1.4.0
version: 1.4.1
openclaw:
category: "code-intelligence"
domain: "core"
Expand Down Expand Up @@ -166,17 +166,45 @@ Every hit carries a `node_id`. Hand that ID straight to `get_node`,
`query_graph`, `get_impact_radius`, or `trace_flow` — the answer exists to
start a graph walk, not to finish the investigation.

**When a question comes back empty or weak, the search is not broken — the
reasons were never written down.** A question mostly made of words nobody
recorded gets no intent hits by design. Hand off to the `ccg-annotate` skill:
annotate the area under investigation, rebuild the graph, then re-ask the same
question. That loop, not query rephrasing, is what makes questions answerable.
**When coverage says the reasons were never written, fix the evidence rather
than rephrasing the query.** If `annotation_coverage.with_reason` is zero or
`next` names `ccg-annotate`, hand off to the `ccg-annotate` skill: annotate the
area under investigation, rebuild the graph, then re-ask the same question. An
empty or weak answer without that evidence is not enough to blame annotations;
follow the hybrid workflow below and inspect freshness and truncation first.

**Difference from Grep**: Grep scans source text directly. CCG full-text search
queries indexed symbol fields and annotations together. Searching "결제" can find
a `payment` function when its annotation contains "결제 처리"; search does not
infer translations or arbitrary synonyms that are absent from the index.

## Hybrid Search Workflow

Do not treat grep/read and CCG search as mutually exclusive. Prefer `rg` when
it is available for repository text searches. The two approaches answer
different parts of the same investigation:

1. When the question names an exact identifier, path, literal, or error text,
use grep/read for the current source. Also use CCG when the task asks why the
code exists, how it relates to other code, or what a change affects.
2. When the question cannot name a symbol yet, start with `ccg search`. Feed the
returned qualified names, paths, and distinctive reason terms into grep/read
to verify the candidate against source.
3. Before concluding that code or behavior does not exist, verify graph
freshness and check both CCG and grep/read. A miss in either one alone is not
proof of absence: CCG can be stale or rank a candidate off the first page,
while grep cannot find intent or relationships that are not written as the
query's exact text.
4. Merge corroborating results by file path and symbol instead of presenting
duplicate lists. Preserve why each result was found (`exact text`,
`identifier`, `recorded reason`, or `graph relationship`). Treat source as
authority for current text and location; treat CCG as candidate evidence for
intent and relationships, then verify those claims with the relevant graph
query or source read.

Run the two searches in parallel when the request contains both an exact clue
and an intent/relationship question, or when a completeness claim matters.

## Reading a Path You Already Have

`search` ranks; it can be wrong about what matters.
Expand Down Expand Up @@ -243,7 +271,10 @@ a narrow question before expanding through graph queries.

## Boundary

- Use grep/read for a known filename, exact string, or one obvious location.
- Follow the hybrid workflow when both direct source evidence and indexed
intent or relationship evidence can materially change the answer.
- Use grep/read alone only for a known filename, exact string, or one obvious
location with no intent, relationship, or completeness claim.
- Treat algorithm, feature-flow, and pipeline questions as relationship analysis rather than simple location lookup.
- Use `ccg search` for intent and annotation candidates, not exact graph proof.
- Use specialized CCG skills for analysis, docs, annotations, or namespaces.
Expand All @@ -255,5 +286,6 @@ a narrow question before expanding through graph queries.
Before finishing, state the namespace and freshness evidence used (or say it
was not verified), name the evidence-producing tools or commands, report result
limits and truncation, record the chosen `replace` behavior for scoped updates,
and list any failed/skipped postprocess step, source fallback, or verification
that was not run.
say whether grep/read corroborated CCG whenever absence or completeness was
claimed, and list any failed/skipped postprocess step, source fallback, or
verification that was not run.
Loading