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
2 changes: 1 addition & 1 deletion codex-plugin/.codex-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "tracedecay",
"version": "0.0.0",
"description": "Codex integration for the TraceDecay semantic code intelligence MCP server.",
"description": "Codex integration for TraceDecay semantic code intelligence: MCP server plus a `tracedecay tool` CLI fallback exposing the same tools when MCP is unavailable.",
"author": {
"name": "ScriptedAlchemy",
"url": "https://github.com/ScriptedAlchemy"
Expand Down
7 changes: 7 additions & 0 deletions codex-plugin/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ Codex has no always-applied rule surface (unlike Cursor's `rules/`), so the
tool-routing steering Cursor places in a rule is injected through the
`SessionStart`/`UserPromptSubmit` hooks instead.

Every MCP tool is also available from the shell as `tracedecay tool <name>`
(`tracedecay tool` lists all tools; `tracedecay tool <name> --help` shows a
tool's parameters). The bundled `using-the-cli` skill and the injected steering
point agents at that CLI fallback when the MCP transport errors or times out,
instead of querying `.tracedecay` databases directly or giving up on
tracedecay.

The `PostCompact` hook starts `codex app-server` as a short-lived child process
and sets `TRACEDECAY_CODEX_SUMMARY_CHILD=1` to prevent recursive summary hooks.
Set `TRACEDECAY_CODEX_BIN` to use a different Codex binary,
Expand Down
42 changes: 42 additions & 0 deletions codex-plugin/skills/using-the-cli/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
---
name: using-the-cli
description: 'Use when a tracedecay MCP call fails, times out, or the server is disconnected or unconfigured — every MCP tool is also a shell command, `tracedecay tool` plus the tool name. Switch to the CLI instead of querying .tracedecay databases directly or abandoning tracedecay.'
---

# Using the tracedecay CLI

The `tracedecay` binary exposes every MCP tool as a shell command. MCP and CLI hit the same project store and return the same payloads, so an MCP transport failure (timeout, disconnect, missing server config) loses nothing: run the same tool with the same arguments via `tracedecay tool <name>` and keep following whatever `tracedecay:*` skill you were in.

## Discovery

1. **List every tool → `tracedecay tool`** (no name): all tools grouped by category with one-line summaries.
2. **One tool's parameters → `tracedecay tool <name> --help`**: the tool's full description plus each parameter with its type and required/optional flag.
3. **Everything else → `tracedecay --help`**: the non-tool subcommands (`init`, `sync`, `status`, `doctor`, `daemon`, `sessions`, `dashboard`, …).

## Invocation

- Arguments are alternating `--key value` flags: `tracedecay tool search --query "parse config" --limit 10`.
- Tool names work with or without the `tracedecay_` prefix (`tool search` ≡ `tool tracedecay_search`).
- `--json` prints raw JSON; `--args '{"key":"value"}'` passes a whole JSON argument object; any value starting with `@` is read from that file (handy for multi-line replacement bodies, e.g. `--new-body @/tmp/body.txt`).
- `--project <path>` picks the project root explicitly; otherwise the nearest initialised project walking up from cwd is used.
- Truncated responses emit the same `handle` envelope as MCP — dereference with `tracedecay tool retrieve --handle rh_…`.

## When to switch

- An MCP call returns a client or transport error, times out, or the server drops mid-session.
- The tracedecay MCP server is not configured in this host but `tracedecay` is on `PATH`.
- A subagent or hook context has shell access but no MCP access.

After falling back, diagnose the MCP side with `tracedecay doctor` and `tracedecay tool runtime`, and tell the user the session is running on the CLI fallback (and why) instead of silently downgrading.

## Guardrails

- Never query `.tracedecay/*.db` with sqlite3 or scripts — schemas are internal and change without notice. The CLI is the supported fallback, not raw DB access.
- Do not abandon tracedecay for broad Grep/file reads just because MCP transport failed; the CLI answers the same graph, memory, and session questions.
- CLI editing tools (`str_replace`, `replace_symbol`, …) mutate the working tree exactly like their MCP twins — apply the same care as `tracedecay:atomic-code-edits`.
- If the CLI also fails (binary missing or project not initialised), fall back to plain tools and suggest `tracedecay init` / `tracedecay doctor` to the user.

## Output

- The same result the MCP tool would have returned, plus a note that the CLI fallback was used and why.
- If any result includes a `tracedecay_metrics:` line, report the savings to the user.
2 changes: 1 addition & 1 deletion cursor-plugin/.cursor-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "tracedecay",
"version": "0.0.0",
"description": "Cursor integration for the TraceDecay semantic code intelligence MCP server.",
"description": "Cursor integration for TraceDecay semantic code intelligence: MCP server plus a `tracedecay tool` CLI fallback exposing the same tools when MCP is unavailable.",
"author": {
"name": "ScriptedAlchemy",
"url": "https://github.com/ScriptedAlchemy"
Expand Down
7 changes: 7 additions & 0 deletions cursor-plugin/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@ build does not expand it, reinstall with the latest Cursor and run
Hook commands derive the active project from Cursor's event payload /
`CURSOR_PROJECT_DIR`, not from the plugin directory.

Every MCP tool is also available from the shell as `tracedecay tool <name>`
(`tracedecay tool` lists all tools; `tracedecay tool <name> --help` shows a
tool's parameters). The bundled `using-the-cli` skill and the always-applied
rule steer agents to that CLI fallback when the MCP transport errors or times
out, instead of querying `.tracedecay` databases directly or giving up on
tracedecay.

For sessions resumed from compacted context, the `sessionStart` hook adds a
short recovery hint through Cursor's `additional_context` channel so the agent
knows to query TraceDecay LCM/session recall before assuming the compacted
Expand Down
1 change: 1 addition & 0 deletions cursor-plugin/rules/tracedecay.mdc
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ alwaysApply: true
- **Edit:** for anchored or structural source edits, follow the `tracedecay:atomic-code-edits` skill (`tracedecay_str_replace`, `tracedecay_replace_symbol`, `tracedecay_ast_grep_rewrite`, …) — the graph re-indexes itself after each write.
- **Recall:** for prior decisions or past conversations, use `tracedecay_message_search` / `tracedecay_fact_store` search (skills: `tracedecay:recalling-project-memory`, `tracedecay:recalling-session-context`); for updating, deleting, or curating stored facts, use `tracedecay:curating-project-memory`.
- **Truncated MCP responses:** if a tracedecay response has `truncated: true` plus `handle`, narrow the query first when that answers the task; if the omitted details are needed, call `tracedecay_retrieve` with the `handle` instead of guessing or re-running a broad query.
- **MCP errors/timeouts:** if a tracedecay MCP call errors, times out, or the server is disconnected, every tool is also available as a shell command — `tracedecay tool <name> --key value` (`tracedecay tool` lists all tools, `tracedecay tool <name> --help` shows parameters; see `tracedecay:using-the-cli`). Do not query `.tracedecay` databases directly and do not abandon tracedecay because the MCP transport failed.
- Every common workflow has a `tracedecay:*` skill (searching-for-code, tracing-functions, finding-impacted-areas, running-impacted-tests, reviewing-a-diff, code-health-report, …) — reach for the matching skill before improvising.
- Fall back to plain file reads, search, or shell only when tracedecay cannot answer or has already pinpointed the exact files.
42 changes: 42 additions & 0 deletions cursor-plugin/skills/using-the-cli/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
---
name: using-the-cli
description: 'Use when a tracedecay MCP call fails, times out, or the server is disconnected or unconfigured — every MCP tool is also a shell command, `tracedecay tool` plus the tool name. Switch to the CLI instead of querying .tracedecay databases directly or abandoning tracedecay.'
---

# Using the tracedecay CLI

The `tracedecay` binary exposes every MCP tool as a shell command. MCP and CLI hit the same project store and return the same payloads, so an MCP transport failure (timeout, disconnect, missing server config) loses nothing: run the same tool with the same arguments via `tracedecay tool <name>` and keep following whatever `tracedecay:*` skill you were in.

## Discovery

1. **List every tool → `tracedecay tool`** (no name): all tools grouped by category with one-line summaries.
2. **One tool's parameters → `tracedecay tool <name> --help`**: the tool's full description plus each parameter with its type and required/optional flag.
3. **Everything else → `tracedecay --help`**: the non-tool subcommands (`init`, `sync`, `status`, `doctor`, `daemon`, `sessions`, `dashboard`, …).

## Invocation

- Arguments are alternating `--key value` flags: `tracedecay tool search --query "parse config" --limit 10`.
- Tool names work with or without the `tracedecay_` prefix (`tool search` ≡ `tool tracedecay_search`).
- `--json` prints raw JSON; `--args '{"key":"value"}'` passes a whole JSON argument object; any value starting with `@` is read from that file (handy for multi-line replacement bodies, e.g. `--new-body @/tmp/body.txt`).
- `--project <path>` picks the project root explicitly; otherwise the nearest initialised project walking up from cwd is used.
- Truncated responses emit the same `handle` envelope as MCP — dereference with `tracedecay tool retrieve --handle rh_…`.

## When to switch

- An MCP call returns a client or transport error, times out, or the server drops mid-session.
- The tracedecay MCP server is not configured in this host but `tracedecay` is on `PATH`.
- A subagent or hook context has shell access but no MCP access.

After falling back, diagnose the MCP side with `tracedecay doctor` and `tracedecay tool runtime`, and tell the user the session is running on the CLI fallback (and why) instead of silently downgrading.

## Guardrails

- Never query `.tracedecay/*.db` with sqlite3 or scripts — schemas are internal and change without notice. The CLI is the supported fallback, not raw DB access.
- Do not abandon tracedecay for broad Grep/file reads just because MCP transport failed; the CLI answers the same graph, memory, and session questions.
- CLI editing tools (`str_replace`, `replace_symbol`, …) mutate the working tree exactly like their MCP twins — apply the same care as `tracedecay:atomic-code-edits`.
- If the CLI also fails (binary missing or project not initialised), fall back to plain tools and suggest `tracedecay init` / `tracedecay doctor` to the user.

## Output

- The same result the MCP tool would have returned, plus a note that the CLI fallback was used and why.
- If any result includes a `tracedecay_metrics:` line, report the savings to the user.
4 changes: 4 additions & 0 deletions src/agents/codex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,10 @@ const CODEX_EMBEDDED_PLUGIN_FILES: &[(&str, &str)] = &[
"skills/tracking-session-health/SKILL.md",
include_str!("../../codex-plugin/skills/tracking-session-health/SKILL.md"),
),
(
"skills/using-the-cli/SKILL.md",
include_str!("../../codex-plugin/skills/using-the-cli/SKILL.md"),
),
];

fn codex_plugin_install_dir(home: &Path) -> PathBuf {
Expand Down
4 changes: 4 additions & 0 deletions src/agents/cursor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,10 @@ const EMBEDDED_PLUGIN_FILES: &[(&str, &str)] = &[
"skills/tracking-session-health/SKILL.md",
include_str!("../../cursor-plugin/skills/tracking-session-health/SKILL.md"),
),
(
"skills/using-the-cli/SKILL.md",
include_str!("../../cursor-plugin/skills/using-the-cli/SKILL.md"),
),
(
"agents/code-explorer.md",
include_str!("../../cursor-plugin/agents/code-explorer.md"),
Expand Down
8 changes: 7 additions & 1 deletion src/hooks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1408,6 +1408,7 @@ pub const CURSOR_PLUGIN_SKILLS: &[&str] = &[
"searching-for-code",
"tracing-functions",
"tracking-session-health",
"using-the-cli",
];

/// Builds the Cursor `sessionStart` `additional_context` text.
Expand Down Expand Up @@ -1490,7 +1491,12 @@ pub fn build_codex_session_context_for_workspace(
(tracedecay_context, tracedecay_search, tracedecay_callers, tracedecay_callees, \
tracedecay_impact, tracedecay_files, tracedecay_affected) over broad file reads \
or shell search for codebase exploration, symbol lookup, call graphs, and \
impact analysis. Fall back to file reads only when tracedecay cannot answer.\n",
impact analysis. Fall back to file reads only when tracedecay cannot answer.\n\
If an MCP call errors, times out, or the server is disconnected, every tool \
is also a shell command: `tracedecay tool <name> --key value` (`tracedecay \
tool` lists tools, `tracedecay tool <name> --help` shows parameters). Use \
that CLI instead of querying .tracedecay databases directly or abandoning \
tracedecay.\n",
);
append_codex_recall_and_registry_guidance(&mut s);
match status {
Expand Down
19 changes: 18 additions & 1 deletion src/mcp/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -376,10 +376,20 @@ fn tool_error_response(id: Value, tool_name: &str, error: &TraceDecayError) -> J
}
}

JsonRpcResponse::error(
let cli_name = tool_name.strip_prefix("tracedecay_").unwrap_or(tool_name);
JsonRpcResponse::error_with_data(
id,
ErrorCode::InternalError,
format!("tool execution failed: {error}"),
Some(json!({
"tool": tool_name,
"cli_fallback": format!(
"This tool is also available from the shell: `tracedecay tool {cli_name} ...` \
(`tracedecay tool {cli_name} --help` for parameters). If MCP calls keep \
failing or timing out, fall back to that CLI instead of querying \
.tracedecay databases directly."
),
})),
)
}

Expand Down Expand Up @@ -1494,6 +1504,13 @@ impl McpServer {
tools are read-only and safe to call in parallel. Edit \
and session-memory tools can mutate local project state \
and declare readOnlyHint=false. \
Every tool is also available from the shell: \
`tracedecay tool <name> --key value` (run `tracedecay tool` \
to list tools, `tracedecay tool <name> --help` for \
parameters). If an MCP call errors, times out, or this \
server disconnects, fall back to that CLI instead of \
querying .tracedecay databases directly or abandoning \
tracedecay. \
When a tool result contains a `tracedecay_metrics:` line, \
report the savings to the user (e.g. 'TraceDecay\\'d ~N tokens')."
}),
Expand Down
4 changes: 3 additions & 1 deletion tests/lsp_code_diagnostics_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,9 @@ async fn stdio_client_keeps_listening_after_initial_empty_publish() {
&[script_path.display().to_string()],
temp.path(),
vec![fake_document(FAKE_LANGUAGE, FAKE_PATH, "let nope")],
std::time::Duration::from_millis(250),
// 250ms (from the Windows wall-time trim) misses the fake server's
// late publish on contended macOS runners; 500ms was stable before.
std::time::Duration::from_millis(500),
)
.await
.unwrap();
Expand Down
Loading