Metadata-Version: 2.4
Name: kcapture
Version: 0.0.1
Summary: Host-agnostic knowledge-capture transport — one MCP + CLI that forwards a capture manifest to the kmint ingestion engine (the sole writer).
Author: yremy
License: Proprietary
Requires-Python: >=3.11
Description-Content-Type: text/markdown
Requires-Dist: mcp>=1.2
Requires-Dist: jsonschema>=4.21
Requires-Dist: kmint==0.1.0
Provides-Extra: dev
Requires-Dist: pytest>=7; extra == "dev"
Requires-Dist: build>=1.0; extra == "dev"

# kcapture

**One knowledge-capture MCP + CLI, host-agnostic.** When you reach a decision while reading
code with an LLM, `kcapture` records it — by validating a *capture manifest* and forwarding it
to **`kmint`**, the single deterministic writer. `kcapture` writes nothing itself; units are
born `SubmittedForRefinement` and **never auto-published** (the host's tool-approval prompt is
the human gate). `kledger` stays read-only.

This is the transport for the `reverse-engineering.code` source-type binding
(**ADR-KCM-FUNC-0003**). The contract — the capture manifest — is owned by `kmint`
(`kmint/schemas/capture-manifest.v1.json`); the vocabulary by the ADR catalogue
(`kmint source-types --json`). kcapture keeps no copy of either.

## Two faces, one core

- **CLI** — `kcapture validate|record|list-source-types`
- **MCP (stdio)** — `kcapture serve-mcp` exposes three tools: `list_source_types`,
  `validate_manifest`, `record_capture`.

Both are thin adapters over the same manifest validation + `kmint` shell-out.

## Install into your AI host — one command

`kcapture install --host <vendor>` writes/updates that host's MCP config **idempotently**,
launching the server via `uvx --from <pin> kcapture serve-mcp` (**zero pre-install** — the pin
hides the proprietary index):

| Host | Command | Config written | Sibling doc |
|---|---|---|---|
| Claude Code | `kcapture install --host claude` | `./.mcp.json` (`mcpServers`) | [install/claude.md](install/claude.md) |
| GitHub Copilot | `kcapture install --host copilot` | `./.vscode/mcp.json` (`servers`, `type: stdio`) | [install/copilot.md](install/copilot.md) |
| Gemini CLI | `kcapture install --host gemini` | `./.gemini/settings.json` (`mcpServers`) | [install/gemini.md](install/gemini.md) |
| Cursor | `kcapture install --host cursor` | `./.cursor/mcp.json` (`mcpServers`) | [install/cursor.md](install/cursor.md) |

Add `--dry-run` to preview, `--config-path P` to target a specific file, `--pin S` to override
the source uvx resolves. Adding a vendor = one row in `kcapture/hosts.py` + one sibling doc.

## The single MCP, many vendors as siblings

There is exactly one host-agnostic capture MCP (`kcapture/mcp_server.py`). The per-vendor
difference is small and parallel — config location, the `mcpServers` vs `servers` key, and the
optional `type: stdio`. That difference is a table (`kcapture/hosts.py`), not a fork. A vendor
graduates to its own repo only if its packaging becomes a genuinely separate published artefact
(a VS Code Marketplace extension, a Gemini extension); then only that vendor's packaging splits,
the core stays shared here.

## Manifest, in one glance

```json
{
  "sourceType": "reverse-engineering.code",
  "domain": "PAYMENTS",
  "source": { "kind": "code", "repoUrl": "…", "commit": "<full-sha>", "path": "src/pay.py" },
  "derivedFrom": [ { "kind": "llm-output", "text": "what the model said about the code" } ],
  "units": [ { "text": "the recovered decision, in one sentence" } ],
  "trigger": { "mode": "model-proposed", "by": "copilot:knowledge-capture@<model>", "at": "<ISO-8601>" }
}
```

- `domain` → the minted handle `BNK.KNOW.MD.<DOMAIN>.<NNN>`.
- `derivedFrom` is the **two-capture case**: the raw LLM output is captured as its own artefact
  `DERIVED_FROM` the code capture (FUNC-0003 R3) — provenance the human gate reviews.
- `kmint` derives provider + confidence and mints the handles; the manifest does not assign them.
- `trigger.mode` is mandatory and honest (URBA-0003 P5).

## Dev

```bash
pip install -e ".[dev]"     # needs the pinned kmint installed too
pytest -q                   # unit + drift guard; the contract test skips unless KCAPTURE_CONTRACT=1
```

Run primarily as a local wheel + console script; the GHCR image exists for k-family parity only.
