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
4 changes: 3 additions & 1 deletion .claude/skills/famstack-lsp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

A skills-directory plugin: Claude Code discovers it in place as `famstack-lsp@skills-dir` on the next session, with no marketplace and no install step. It only starts once you have accepted the workspace trust dialog for this repo.

It wires one thing: `basedpyright-langserver` over stdio for `.py` and `.pyi`. That gives an agent working in this repo live diagnostics after each edit, plus go-to-definition and find-references, instead of grepping for a symbol and hoping.
It wires `basedpyright-langserver` over stdio for `.py` and `.pyi`. That gives an agent working in this repo live diagnostics after each edit, plus go-to-definition and find-references, instead of grepping for a symbol and hoping.

It also carries a SessionStart hook (`hooks/`). A hook cannot reach the server Claude Code spawned, so it does not warm the index itself: it tells the agent to load the deferred `LSP` tool and run one throwaway query, or reports that the binary is missing. Changes to the hook take effect after `/reload-plugins`.

## Requirement

Expand Down
14 changes: 14 additions & 0 deletions .claude/skills/famstack-lsp/hooks/hooks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"hooks": {
"SessionStart": [
{
"hooks": [
{
"type": "command",
"command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/session-start.sh\""
}
]
}
]
}
}
14 changes: 14 additions & 0 deletions .claude/skills/famstack-lsp/hooks/session-start.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/bin/sh
# SessionStart: stdout becomes context for the agent.
#
# A hook cannot reach the language server Claude Code spawned, so it cannot
# warm the index itself. It tells the agent to, because the LSP tool is
# deferred (listed by name only, easy to read as unavailable) and a cold
# server answers from a partial index instead of waiting.

if ! command -v basedpyright-langserver >/dev/null 2>&1; then
echo "famstack-lsp: basedpyright-langserver is not on PATH, so there is no language server this session. Install it with 'uv tool install basedpyright' (or run tools/init-repo), then /reload-plugins. Until then, use 'uvx basedpyright <paths>' for diagnostics and grep for navigation."
exit 0
fi

echo "famstack-lsp: a Python language server is available through the deferred LSP tool. Load it with ToolSearch 'select:LSP' before the first question about a symbol, then warm it with one throwaway workspaceSymbol query for 'HookResolver' on lib/stack/hooks.py and ignore the result: a cold server answers from a partial index. See CLAUDE.md."
2 changes: 2 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ If you might do both, load both. They are short on purpose.

The type checker is worth one look before you start, whatever your harness: the tree carries a standing error count, so a bare run tells you nothing about your own change. The "Static checks" section of the engineer file has the two commands that separate the two, and works from any agent that can run a shell.

If your harness gives you a language server, questions about a symbol (where it is defined, who calls it, what type it is) go to it rather than to grep. Warm it with one throwaway query first: a cold server answers from a partial index instead of waiting, and a first find-references on `compose_up` returned only its definition where the warm answer was five. Before a rename, grep for the name as well. String references such as `monkeypatch.setattr("stack.docker.compose_up", ...)` are text, and the server does not count them. The engineer file covers reading its answers.

## Approach (universal)

Six principles. The first four are distilled from [Andrej Karpathy's observations on LLM coding pitfalls](https://github.com/multica-ai/andrej-karpathy-skills); the fifth is classic separation of concerns; the sixth is what we test and why. Apply to every change, every role. **Tradeoff:** these bias toward caution over speed. For trivial tasks (typos, obvious one-liners), use judgment.
Expand Down
11 changes: 11 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
@AGENTS.md
@docs/agent/ops.md
@docs/agent/dev.md

## Claude Code: the language server

The `famstack-lsp` plugin (`.claude/skills/famstack-lsp/`) runs basedpyright for this repo. Two things about it are specific to this harness:

- **The `LSP` tool is deferred.** It is listed by name only, not with the other tools, so it reads as unavailable. Load it with ToolSearch `select:LSP` before the first question about a symbol.
- **Warm it before trusting it.** Run one `workspaceSymbol` query for `HookResolver` on `lib/stack/hooks.py` and ignore the result. It returns a single line, and it makes the server index the workspace.

The plugin's SessionStart hook says both at the start of every session, and says when `basedpyright-langserver` is missing instead. If neither message appears, the plugin is not loaded: run `claude plugin list` (see CONTRIBUTING.md § Language server).

Use it for definitions, references, callers (`incomingCalls`) and types (`hover`). Use grep for text. How to read its answers is in the engineer file, § Static checks.
Loading