feat(integrations): ship Claude Code skill for kebab
Add `integrations/claude-code/kebab/` — a Claude Code skill that calls `kebab search --json` / `kebab ask --json` automatically when the user asks an internal-context / runbook / wiki-lookup question. Install via `cp -r integrations/claude-code/kebab ~/.claude/skills/` (or symlink for in-place updates). The shipped SKILL.md keeps its frontmatter `description` generic so the trigger fires on any "internal / org-specific" cue — per-user keywords (team / system / acronym) belong in a local override, not in the repo-shipped frontmatter. CLAUDE.md §Wire schema v1: add a paragraph documenting the `integrations/<host>/` layout and the rule that a wire schema major bump (v1→v2) updates each shipped integration in the same PR — same shape as the version-cascade rule. README.md §외부 AI 통합: replace the "~50줄 wrapper" prose with a direct link to `integrations/claude-code/`, since the wrapper is now in-tree.
This commit is contained in:
@@ -62,6 +62,8 @@ Read the relevant task spec's deps section before adding an import. New crates i
|
||||
|
||||
All `--json` output carries a `schema_version` field (`ingest_report.v1`, `search_hit.v1`, `answer.v1`, `doctor.v1`, …). Schemas live in `docs/wire-schema/v1/`. The wire shape is the contract for external integrations (Claude Code skills, MCP, etc.); breaking it requires a `*.v2` major bump and parallel-running both for one phase.
|
||||
|
||||
In-tree integration packages live under `integrations/<host>/` — currently `integrations/claude-code/kebab/` (a Claude Code skill that calls `kebab search --json` / `kebab ask --json`). Any wire schema major bump (v1→v2) MUST update each shipped integration in the same PR, same as the version-cascade rule below. Per-user trigger keywords (team / system / acronym) belong in the user's local copy of the skill, not in the repo-shipped frontmatter — keep `integrations/claude-code/kebab/SKILL.md`'s `description` generic.
|
||||
|
||||
## Versioning cascade
|
||||
|
||||
`parser_version` / `chunker_version` / `embedding_version` / `prompt_template_version` / `index_version` follow the cascade rule in design §9. Changing any of these invalidates downstream records (chunks, embeddings, eval runs, …). When changing a version: either ship a re-process job or treat it as a breaking schema bump. The eval runner snapshots all five into `eval_runs.config_snapshot_json`.
|
||||
|
||||
@@ -157,7 +157,8 @@ config 예시는 [docs/SMOKE.md](docs/SMOKE.md) 의 `/tmp/kebab-smoke/config.tom
|
||||
|
||||
`--json` 출력 + frozen wire schema v1 가 stable contract. 통합 옵션:
|
||||
|
||||
- **Claude Code / Codex skill** — `kebab search --json` / `kebab ask --json` 호출하는 ~50줄 wrapper. multi-turn 은 `kebab ask --session <id> --json` 으로 영속 — wrapper 가 conversation id 관리하면 외부 agent 도 `--repl` 없이 stateful 대화 가능 (p9-fb-18).
|
||||
- **Claude Code skill** — repo 의 [`integrations/claude-code/`](integrations/claude-code/) 가 ship-ready skill. `cp -r integrations/claude-code/kebab ~/.claude/skills/` 한 번이면 새 Claude Code 세션부터 자동 trigger (내부 시스템 / 위키 lookup / 사내 runbook 질문). multi-turn 은 `kebab ask --session <id> --json` 으로 영속 — skill 이 conversation id 관리하면 외부 agent 도 `--repl` 없이 stateful 대화 가능 (p9-fb-18).
|
||||
- **Codex / 기타 agent host** — `--json` + frozen wire schema v1 가 stable contract. 동일 패턴으로 ~50줄 wrapper 작성 가능. `integrations/<host>/` 에 추가 PR 환영.
|
||||
- **MCP server** — stdio JSON-RPC 로 `kebab-app` facade 1:1 노출.
|
||||
- **HTTP wrapper** — `kebab serve --bind 127.0.0.1:7711` (P+, local-only 가치 신중).
|
||||
|
||||
|
||||
57
integrations/claude-code/README.md
Normal file
57
integrations/claude-code/README.md
Normal file
@@ -0,0 +1,57 @@
|
||||
# Claude Code integration
|
||||
|
||||
Skill packages that let [Claude Code](https://claude.ai/claude-code) call `kebab` automatically when a question would benefit from the user's local KB.
|
||||
|
||||
## Available skills
|
||||
|
||||
| Skill | Trigger | What it does |
|
||||
|-------|---------|--------------|
|
||||
| [`kebab`](kebab/SKILL.md) | Internal / org-specific questions, runbooks, indexed-doc lookups | Calls `kebab search --json` / `kebab ask --json` and folds the results into the answer with citations |
|
||||
|
||||
## Install
|
||||
|
||||
User-level (every Claude Code session on this machine):
|
||||
|
||||
```bash
|
||||
# from a kebab repo checkout
|
||||
cp -r integrations/claude-code/kebab ~/.claude/skills/
|
||||
|
||||
# verify
|
||||
ls ~/.claude/skills/kebab/SKILL.md
|
||||
```
|
||||
|
||||
Or symlink so `git pull` in the repo updates the skill in place:
|
||||
|
||||
```bash
|
||||
mkdir -p ~/.claude/skills
|
||||
ln -s "$(pwd)/integrations/claude-code/kebab" ~/.claude/skills/kebab
|
||||
```
|
||||
|
||||
Project-level (only loads when Claude Code runs in a specific project):
|
||||
|
||||
```bash
|
||||
mkdir -p <project>/.claude/skills
|
||||
cp -r integrations/claude-code/kebab <project>/.claude/skills/
|
||||
```
|
||||
|
||||
After install, start a fresh Claude Code session — the skill self-registers from its frontmatter `description` and is invoked automatically when a matching question shows up. No config edit needed.
|
||||
|
||||
## Customization
|
||||
|
||||
The shipped `SKILL.md` is generic on purpose — it triggers on any "internal / org-specific" cue. To make Claude Code more eager (or less) for **your** corpus, edit the frontmatter `description` of your local copy and add the team / system / acronym keywords that should trigger the skill (e.g. `MLOps`, `DMQ`, `AiSuite`). Don't PR those keywords back into this repo — they're per-user.
|
||||
|
||||
A symlink install + a `~/.claude/skills/kebab/SKILL.md.local` patch script is one pattern; another is to keep a fork branch with personalized frontmatter and rebase on `main`.
|
||||
|
||||
## Update policy
|
||||
|
||||
The skill consumes `kebab`'s wire schema v1 (`schema_version` fields like `search_hit.v1`, `answer.v1`). When the wire schema major-bumps to v2, this skill is updated in the same PR — see the project root [`CLAUDE.md`](../../CLAUDE.md#wire-schema-v1) §Wire schema v1.
|
||||
|
||||
## Other hosts
|
||||
|
||||
`kebab` exposes the same `--json` contract to any agent host. To add a new integration:
|
||||
|
||||
1. Drop a directory under `integrations/<host>/` mirroring the structure here.
|
||||
2. Reference `docs/wire-schema/v1/` for the JSON shapes.
|
||||
3. Link from this `README.md` table.
|
||||
|
||||
A native MCP server (`kebab serve --mcp`) and an HTTP wrapper are listed in the root [README §외부 AI 통합](../../README.md#외부-ai-통합) as future options.
|
||||
88
integrations/claude-code/kebab/SKILL.md
Normal file
88
integrations/claude-code/kebab/SKILL.md
Normal file
@@ -0,0 +1,88 @@
|
||||
---
|
||||
name: kebab
|
||||
description: Local knowledge base + RAG over the user's pre-indexed documents (wiki crawls, Markdown notes, PDFs, images). Use when answering questions that need internal context the user has indexed locally — e.g. team-specific procedures, internal runbooks, infrastructure docs, credentials registries, project-specific conventions. Also use when a domain question (Kubernetes, MLOps, internal tooling, etc.) needs additional grounding from indexed docs before answering. Do NOT use for general public questions, code in the working directory, or anything obviously outside the indexed corpus.
|
||||
---
|
||||
|
||||
# kebab — local KB / RAG access
|
||||
|
||||
`kebab` is a CLI installed at `~/.cargo/bin/kebab` (binary name: `kebab`). It indexes the user's personal documents and exposes them via lexical / vector / hybrid search and a local-LLM RAG answer. All output speaks frozen wire schema v1 — every JSON record carries a `schema_version` field.
|
||||
|
||||
## When to invoke
|
||||
|
||||
Trigger when the user's question matches **any** of:
|
||||
|
||||
- Refers to internal/organization-specific systems, procedures, or jargon that a generic public answer would miss.
|
||||
- Names a runbook or procedure the user is likely to have indexed ("how do I X", "what's our policy on Y", "where's the doc for Z").
|
||||
- Domain-technical question where additional internal context (custom CRDs, internal naming, team conventions) would change the answer vs. a generic public answer.
|
||||
- User explicitly references "the wiki", "내부 문서", "kb", or asks "do we have docs on X".
|
||||
|
||||
**Skip** when:
|
||||
|
||||
- The question is about public OSS, language semantics, or anything in the current working directory.
|
||||
- The user is editing kebab's own source — that's a code task, not a KB query.
|
||||
- A previous `kebab` call in this session already returned `grounded: false` on a near-identical query (don't loop).
|
||||
|
||||
User-specific trigger keywords (team names, system names, internal acronyms) belong in a per-user override of this SKILL.md, not in this repo-shipped version.
|
||||
|
||||
## Two surfaces, pick the right one
|
||||
|
||||
### `kebab search` — when you need the source
|
||||
|
||||
Use when the user wants to **find** a doc, or when you (the model) need raw chunks to reason from before answering.
|
||||
|
||||
```bash
|
||||
kebab search "<query>" --mode hybrid --json
|
||||
```
|
||||
|
||||
- `--mode hybrid` is the default-correct choice. Use `vector` for semantic-only ("docs about X concept"), `lexical` for exact strings ("the literal flag `--foo-bar`").
|
||||
- Output is a JSON array of `search_hit.v1` objects. Key fields: `rank`, `score`, `doc_path`, `heading_path[]`, `section_label`, `snippet`, `citation` (has line range / page), `chunk_id`.
|
||||
- Cite back to the user as `doc_path § heading_path[-1]` so they can open the source.
|
||||
|
||||
### `kebab ask` — when you need the answer
|
||||
|
||||
Use when the user wants a synthesized answer, not a list of links.
|
||||
|
||||
```bash
|
||||
kebab ask "<question>" --json
|
||||
```
|
||||
|
||||
- Returns one `answer.v1` object: `answer` (markdown), `citations[]`, `grounded` (bool), `refusal_reason`, `model`.
|
||||
- **If `grounded == false`** → the KB doesn't have enough context. Don't paraphrase the refusal as if it were an answer. Tell the user the KB came up dry and fall back to your own knowledge or ask for the source.
|
||||
- For follow-up turns on the same topic, pass `--session <stable-id>` so kebab gets prior history. Pick a slug (`team-onboarding-2026-05`) and reuse it across the conversation. Sessions persist across Claude sessions until `kebab reset --data-only`.
|
||||
|
||||
## Parsing tips
|
||||
|
||||
- Both commands print **one JSON value to stdout**, progress / warnings to stderr. Capture stdout only: `kebab search ... --json 2>/dev/null`.
|
||||
- `search --json` output can be large for broad queries. Pipe through `jq` to project: `jq '.[] | {rank, doc_path, heading: .heading_path[-1], snippet}'`.
|
||||
- `ask --json`'s `citations[]` mirrors `search_hit.v1` minus retrieval internals — same `doc_path` / `citation` shape.
|
||||
- Schema reference lives in the kebab repo at `docs/wire-schema/v1/*.schema.json` if a field is unclear.
|
||||
|
||||
## Quick health check
|
||||
|
||||
If a call fails or returns suspicious output, run `kebab doctor` first — it surfaces config-load / data-dir / Ollama-reachability problems in one line each. Don't silently retry on errors; report the doctor output.
|
||||
|
||||
## Workflow recipes
|
||||
|
||||
**Recipe A — user asks an internal-context question, you want grounded answer:**
|
||||
|
||||
1. `kebab ask "<question>" --json`
|
||||
2. If `grounded`, cite `citations[].doc_path` in your reply and quote the user's `answer` (translate / condense as needed).
|
||||
3. If `!grounded`, switch to `kebab search "<question>" --mode hybrid --json` and look at top 3 hits — sometimes content exists but RAG threshold rejected it. If hits look relevant, summarize from snippets and cite. If still nothing, tell the user.
|
||||
|
||||
**Recipe B — domain question where internal context might exist:**
|
||||
|
||||
1. Run `kebab search "<key terms>" --mode hybrid --json` quickly (cheap, no LLM).
|
||||
2. If top hit's `score` is low (< ~0.3) or no hits, answer from general knowledge without mentioning the KB.
|
||||
3. If top hit is relevant, fold its content into your answer and cite `doc_path`.
|
||||
|
||||
**Recipe C — user wants to know "what's in the KB about X":**
|
||||
|
||||
1. `kebab search "X" --mode hybrid --json | jq '.[] | {doc_path, heading: .heading_path[-1]}'`
|
||||
2. List unique `doc_path`s back to the user as a discovery surface.
|
||||
|
||||
## Don't
|
||||
|
||||
- Don't run `kebab ingest` / `kebab reset` / `kebab init` automatically. Those mutate state — the user runs them.
|
||||
- Don't pass user-supplied raw text into the query without trimming — long queries (> a few hundred chars) waste embedding budget. Extract the question.
|
||||
- Don't fabricate `doc_path`s. If you didn't see a doc in `search` / `ask` output, it's not in the KB.
|
||||
- Don't use `kebab tui` from a skill — it's interactive only.
|
||||
Reference in New Issue
Block a user