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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]

### Added
- `ctx similar <description>`: find existing functions/methods similar to a natural-language description before writing a new one; reports similarity score, fan-in, and a one-line doc per hit, supports `--keyword` (FTS5 fallback that needs no embeddings), `--openai`, and `--json`, and exits with code 2 when embeddings are missing
- `ctx hotspots`: rank files (or symbols with `--by symbol`) by combined git churn and code complexity (`score = normalized_churn * normalized_complexity`), with `--since`, `--limit`, `--min-churn`, and `--against REF` filters and `--json` output including each file's top 3 most complex symbols; see `docs/json-output.md`
- `ctx check`: architecture rules engine driven by `.ctx/rules.toml` -- declare layers as glob patterns over indexed files, then enforce `forbidden` layer dependencies, `allowed_dependents` whitelists, `limit` metric thresholds (fan-in / fan-out / complexity / file symbols), and `no_new_dependents` frozen paths; supports `--against REF` to scope violations to changed files, `--list` to inspect parsed rules, and `--json`; exits 1 when violations are found (see `ctx check --help` for a full example)
- Global `--json` flag: `search`, `semantic`, `query find/callers/deps/graph/impact/stats/files`, and `explain` emit a single machine-readable JSON document wrapped in a stable envelope (`ctx_version`, `command`, `generated_at`, `data`); see `docs/json-output.md`
Expand Down
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,17 @@ ctx semantic "error handling" --openai # OpenAI embeddings
ctx semantic "database queries" --limit 20
```

### `ctx similar <description>`
Find existing functions similar to a description — reuse before you write. Before writing a new function, run `ctx similar` with its intended purpose; if a strong match exists (high similarity and fan-in), extend or reuse it instead.

```bash
ctx similar "parse a config file into a struct" # Embedding search (functions/methods only)
ctx similar "retry with backoff" --keyword # FTS5 fallback, no embeddings needed
ctx similar "count tokens" --limit 5 --json # Machine-readable output
```

Each hit shows the symbol, similarity score, fan-in (how many callers it already has), and a one-line doc. Requires `ctx embed` first (exits with code 2 otherwise); `--keyword` works without embeddings.

### `ctx embed`
Generate embeddings for semantic search.

Expand Down
29 changes: 29 additions & 0 deletions docs/json-output.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,35 @@ Note: `query.graph` and `query.impact` nodes come from graph traversal, which do

If no embeddings have been generated yet, `results` is empty and a hint is printed to stderr.

### `similar`

`ctx similar <QUERY> [--limit N] [--keyword] [--openai] --json`

Finds function/method symbols similar to a natural-language (or signature-like) description, so you can reuse an existing utility instead of writing a new one.

```json
{
"query": "count tokens in a string",
"mode": "semantic",
"results": [
{
"symbol": { "name": "count_tokens", "qualified_name": null, "kind": "function", "file": "src/tokens.rs", "line_start": 41, "line_end": 60 },
"score": 0.83,
"fan_in": 12,
"brief": "Count tokens using the configured encoding."
}
]
}
```

- `mode` is `"semantic"` (embedding search, the default) or `"keyword"` (`--keyword`, FTS5-based, needs no embeddings or API key).
- `score` depends on the mode. In `semantic` mode it is the embedding similarity in `0.0..=1.0` (cosine similarity, or `1/(1+d)` for L2 distance when sqlite-vec is used). In `keyword` mode it is the hybrid-search relevance score: `1.0` for an exact name match, `0.9` for a prefix match, `0.7` for a contains match, or a normalized FTS5 bm25 relevance (`|rank| / (1 + |rank|)`) in `0.0..=1.0`.
- `fan_in` is the number of resolved incoming `calls` edges — a high value signals an established utility worth reusing.
- `brief` is the symbol's one-line doc: the brief doc comment, falling back to the first sentence of the docstring, else `""`.
- Only `function` and `method` symbols are returned.

Exit codes: running without `--keyword` when no embeddings have been generated is an operational error (exit code 2, with a hint to run `ctx embed` or use `--keyword`). Zero matches is still a success (exit 0) with an empty `results` array.

### `query.find`

`ctx query find <PATTERN> [--kind K] [--file F] --json`
Expand Down
27 changes: 27 additions & 0 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,33 @@ pub enum Command {
openai: bool,
},

/// Find existing functions similar to a description (reuse before you write)
///
/// Searches function and method symbols by embedding similarity and
/// reports a one-line doc, similarity score, and fan-in for each hit so
/// you can judge whether an established utility already covers the need.
///
/// Exit codes: 0 = success (even with no matches); 2 = no embeddings
/// generated yet (run `ctx embed`, or use --keyword for FTS-based search
/// that needs no embeddings) or any other operational error.
Similar {
/// Natural language or signature-like description of the intended function
query: String,

/// Maximum number of results
#[arg(long, short, default_value = "10")]
limit: usize,

/// Use FTS5 keyword search instead of embeddings (works with zero
/// embeddings and no API key)
#[arg(long)]
keyword: bool,

/// Use OpenAI API instead of local model (requires OPENAI_API_KEY)
#[arg(long)]
openai: bool,
},

/// Analyze code complexity and flag high fan-out functions
Complexity {
/// Fan-out threshold (default: 10, flag > 50 as critical)
Expand Down
2 changes: 2 additions & 0 deletions src/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ pub mod index;
pub mod interactive;
pub mod query;
pub mod search;
pub mod similar;
pub mod smart_cmd;
pub mod symbol;

Expand All @@ -32,6 +33,7 @@ pub use interactive::run_serve;
pub use interactive::run_shell;
pub use query::run_query;
pub use search::run_search;
pub use similar::run_similar;
pub use smart_cmd::run_smart;
pub use symbol::{run_explain, run_source};

Expand Down
Loading
Loading