# Reported issues for Longhand

Pod holds 11 of 11 GitHub reports that passed its relevance review. This can include external user reports, maintainer-confirmed bugs, and concrete feature gaps. Treat them as evidence to inspect, not a count of distinct defects.

Back to [Longhand](/mcp/longhand).

## Most discussed

### MCP tool loading fails in Claude Code: outputSchema incompatibility

## Problem

When longhand's MCP server is registered with Claude Code (CLI), the server connects successfully but tool loading fails with the following validation error:

```
Reconnected to longhand, but fetching tools failed: [
  {
    "code": "invalid_value",
    "values": ["object"],
    "path": ["tools", 0, "outputSchema", "type"],
    "message": "Invalid input: expected \"object\""
  },
  ... (same error for tools 1, 2, 4, 6, 11, 12, 14, 15, 16, 17, 18)
]
```

## Root cause

Longhand uses…

[Read the thread](https://github.com/Wynelson94/longhand/issues/9) · 2026-05-22 · closed · external user · 2 comments

### outputSchema with non-object top-level type breaks tool loading in Claude Code

## Problem

12 of 19 MCP tools fail to load in Claude Code because their `outputSchema` declares a top-level `"type": "array"` or uses `"oneOf"` without a top-level `"type"`. Claude Code's MCP client validator requires `outputSchema.type` to be `"object"`.

This is the root cause of #9.

## Analysis

I mapped every tool definition in `mcp_server.py` against the error output from #9:

| Index | Tool | `outputSchema.type` | Loads? |
|-------|------|---------------------|--------|
| 0 | `search` |…

[Read the thread](https://github.com/Wynelson94/longhand/issues/10) · 2026-05-22 · closed · external user · 1 comment

### Redaction misses git commit messages

With `redact.enabled`, secrets are masked at parse time across an event's `content`, `tool_output`, `error_snippet`, `old_content`, `new_content`, and its raw JSON (`_EVENT_TEXT_FIELDS` in `longhand/redaction.py`). But `git_commit_message` is not in that list.

The parser extracts it from git output (`parser.py`, and `codex.py` for Codex `exec` commands), and `store.py` persists it as `git_operations.commit_message`. So a secret that appears in a commit message is stored unmasked at ingest,…

[Read the thread](https://github.com/Wynelson94/longhand/issues/110) · 2026-09-28 · open · 0 comments

### `mcp install` writes the macOS Claude Desktop path on every OS

`CLAUDE_DESKTOP_CONFIG_PATH` is hardcoded to `~/Library/Application Support/Claude/claude_desktop_config.json` (`longhand/setup_commands.py`). On Windows (the best-effort CI tier), Claude Desktop reads `%APPDATA%\Claude\claude_desktop_config.json`, so `mcp install` writes a file nothing reads and still reports success. On Linux there is no Claude Desktop.

**Expected:** a platform-specific path, or skip with a message where Desktop doesn't exist.

_Found and verified against the code during the…

[Read the thread](https://github.com/Wynelson94/longhand/issues/105) · 2026-09-28 · open · 0 comments

### CLI session-prefix resolution only scans the 1,000 most recent sessions

`timeline`, `replay`, `export`, `status --session`, and `search --session` resolve a session-ID prefix by filtering `store.sqlite.list_sessions(limit=1000)` in Python (5 call sites in `longhand/cli/_commands.py`). `cli/helpers._resolve_prefix` already does this correctly with SQL `LIKE` over the whole table; its docstring records the same bug being fixed for the MCP path.

The maintainer's archive is at 792 sessions, so this will start failing silently at 1,001.

**Expected:** all five call…

[Read the thread](https://github.com/Wynelson94/longhand/issues/104) · 2026-09-28 · open · 0 comments

### MCP output caps: six tools are uncapped, and `max_chars <= 0` disables truncation

The README promised every tool is capped. In fact:

- `max_chars` is accepted by 5 of 13 tools: `search`, `get_session_timeline`, `recall`, `recall_project_status`, `find_commits`.
- `list_sessions` and `list_projects` have a fixed 16,000 cap, which doesn't apply in their `project_id` / `match` modes.
- Uncapped: `get_file_history` (every edit, no LIMIT), `replay_file` (the whole file), `find_episodes` (including the detail mode's `file_state_after`), `list_plans`, `get_stats`, `reconcile`.
-…

[Read the thread](https://github.com/Wynelson94/longhand/issues/103) · 2026-09-28 · open · 0 comments

### `search` auto-scope can't be overridden; its hint is a no-op

When a query names a project (score ≥ 0.8), `search` scopes to it and returns `auto_scope_hint: "… Pass project_name=None to override."` (`longhand/mcp_server.py`). JSON `null` can't be told apart from omitting the key, so that call auto-scopes again. There is no way to run an unscoped search whose text names a project.

That is the "remedy that cannot work" COMPATIBILITY.md Promise 5 rules out. Since 1.2.1, an explicit `session_id` turns auto-scope off, but that is not a general opt-out.…

[Read the thread](https://github.com/Wynelson94/longhand/issues/102) · 2026-09-28 · open · 0 comments

### The update check runs on exit of `shared-mcp`, `mcp serve`, and `demo`

`_UPDATE_CHECK_EXCLUDED` (`longhand/cli/_commands.py`) lists only the hidden entry points: `mcp-server`, the hook commands, `context`, and `backfill-episodes`. The comment above it says an MCP server "may not gain network calls", but:

- `shared-mcp` and `mcp serve` are MCP servers too, and they refresh the PyPI cache when they exit.
- `demo` is documented as not touching `~/.longhand`, but its exit-time refresh writes `~/.longhand/update-check.json`, creating the directory (see the 0700…

[Read the thread](https://github.com/Wynelson94/longhand/issues/101) · 2026-09-28 · open · 0 comments

## Most recent

### doctor's "Claude Code MCP" row misses plugin-provided servers

`doctor` checks only the top-level `mcpServers` key of `~/.claude.json` (`longhand/setup_commands.py`, "Claude Code MCP installed?"). A server provided by the Longhand plugin (`.mcp.json`) or registered at project scope shows as "not installed". Doctor then tells the user to run `claude mcp add` for a server they already have.

**Expected:** recognize plugin-provided and project-scoped registrations, or reword the row to "not found in ~/.claude.json".

_Found and verified against the code…

[Read the thread](https://github.com/Wynelson94/longhand/issues/100) · 2026-09-28 · open · 0 comments

### `~/.longhand` can be created without 0700

`LonghandStore` creates the data dir with `mode=0o700` (`longhand/storage/store.py`), but only if it gets there first. Two other paths create it with the default umask, typically 0755:

- the update-check cache: `target.parent.mkdir(parents=True, exist_ok=True)` (`longhand/update_check.py`)
- `config --set`: `config_path.parent.mkdir(parents=True, exist_ok=True)` (`longhand/cli/_commands.py`)

`longhand demo` writes the update-check cache on exit. So the README's recommended first command can…

[Read the thread](https://github.com/Wynelson94/longhand/issues/99) · 2026-09-28 · open · 0 comments

### `config --set` ignores a relocated store, and `--edit` does nothing

`longhand config --set k=v` always writes `~/.longhand/config.json`: `config()` in `longhand/cli/_commands.py` builds `config_path = Path.home() / ".longhand" / "config.json"`. It ignores both its own `--data-dir` option and `LONGHAND_DATA_DIR`.

The readers use the **resolved** data dir. Redaction reads `resolve_data_dir() / "config.json"` (`longhand/redaction.py`), and so does the prompt-hook config loader. With a relocated store, `config --set` writes a file nothing reads, and prints that…

[Read the thread](https://github.com/Wynelson94/longhand/issues/96) · 2026-09-28 · open · 0 comments

The remaining reports are on [the project's issue tracker](https://github.com/Wynelson94/longhand/issues).
