diff --git a/README.md b/README.md index 9063c68cb..869acfadb 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,8 @@ One command. Walk away. Come back to a built project with clean git history.
npm install -g gsd-pi
+> **📋 NOTICE: New to Node on Mac?** If you installed Node.js via Homebrew, you may be running a development release instead of LTS. **[Read this guide](./docs/node-lts-macos.md)** to pin Node 24 LTS and avoid compatibility issues.
+
---
diff --git a/docs/node-lts-macos.md b/docs/node-lts-macos.md
new file mode 100644
index 000000000..67582aec1
--- /dev/null
+++ b/docs/node-lts-macos.md
@@ -0,0 +1,75 @@
+# Pinning Node.js LTS on macOS with Homebrew
+
+If you installed Node.js via Homebrew (`brew install node`), you're tracking the **latest current release** — which can include odd-numbered development versions (e.g. 23.x, 25.x). These aren't LTS and may have breaking changes or instability.
+
+GSD requires Node.js **v22 or later** and works best on an **LTS (even-numbered) release**. This guide shows how to pin Node 24 LTS using Homebrew.
+
+## Check your current version
+
+```bash
+node --version
+```
+
+If this shows an odd number (e.g. `v23.x`, `v25.x`), you're on a development release.
+
+## Install Node 24 LTS
+
+Homebrew provides versioned formulas for LTS releases:
+
+```bash
+# Unlink the current (possibly non-LTS) version
+brew unlink node
+
+# Install Node 24 LTS
+brew install node@24
+
+# Link it as the default
+brew link --overwrite node@24
+```
+
+Verify:
+
+```bash
+node --version
+# Should show v24.x.x
+```
+
+## Why pin to LTS?
+
+- **Stability** — LTS releases receive bug fixes and security patches for 30 months
+- **Compatibility** — npm packages (including GSD) test against LTS versions
+- **No surprises** — `brew upgrade` won't jump you to an unstable development release
+
+## Prevent accidental upgrades
+
+By default, `brew upgrade` will upgrade all packages, which could move you off the pinned version. Pin the formula:
+
+```bash
+brew pin node@24
+```
+
+To unpin later:
+
+```bash
+brew unpin node@24
+```
+
+## Switching between versions
+
+If you need multiple Node versions (e.g. 22 and 24), consider using a version manager instead:
+
+- **[nvm](https://github.com/nvm-sh/nvm)** — `nvm install 24 && nvm use 24`
+- **[fnm](https://github.com/Schniz/fnm)** — `fnm install 24 && fnm use 24` (faster, Rust-based)
+- **[mise](https://mise.jdx.dev/)** — `mise use node@24` (polyglot version manager)
+
+These let you set per-project Node versions via `.node-version` or `.nvmrc` files.
+
+## Verify GSD works
+
+After pinning:
+
+```bash
+node --version # v24.x.x
+npm install -g gsd-pi
+gsd --version
+```
diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md
index 022688338..452ca8ccb 100644
--- a/docs/troubleshooting.md
+++ b/docs/troubleshooting.md
@@ -123,3 +123,27 @@ Doctor rebuilds `STATE.md` from plan and roadmap files on disk and fixes detecte
- **Dashboard:** `Ctrl+Alt+G` or `/gsd status` for real-time diagnostics
- **Forensics:** `/gsd forensics` for structured post-mortem analysis of auto-mode failures
- **Session logs:** `.gsd/activity/` contains JSONL session dumps for crash forensics
+
+## LSP (Language Server Protocol)
+
+### "LSP isn't available in this workspace"
+
+GSD auto-detects language servers based on project files (e.g. `package.json` → TypeScript, `Cargo.toml` → Rust, `go.mod` → Go). If no servers are detected, the agent skips LSP features.
+
+**Check status:**
+```
+lsp status
+```
+
+This shows which servers are active and, if none are found, diagnoses why — including which project markers were detected but which server commands are missing.
+
+**Common fixes:**
+
+| Project type | Install command |
+|-------------|-----------------|
+| TypeScript/JavaScript | `npm install -g typescript-language-server typescript` |
+| Python | `pip install pyright` or `pip install python-lsp-server` |
+| Rust | `rustup component add rust-analyzer` |
+| Go | `go install golang.org/x/tools/gopls@latest` |
+
+After installing, run `lsp reload` to restart detection without restarting GSD.
diff --git a/packages/pi-coding-agent/src/core/lsp/index.ts b/packages/pi-coding-agent/src/core/lsp/index.ts
index b2dbf2c6d..9bcfa66f7 100644
--- a/packages/pi-coding-agent/src/core/lsp/index.ts
+++ b/packages/pi-coding-agent/src/core/lsp/index.ts
@@ -14,7 +14,7 @@ import {
setIdleTimeout,
WARMUP_TIMEOUT_MS,
} from "./client.js";
-import { getServersForFile, type LspConfig, loadConfig } from "./config.js";
+import { getServersForFile, type LspConfig, loadConfig, hasRootMarkers, resolveCommand } from "./config.js";
import { applyTextEdits, applyWorkspaceEdit } from "./edits.js";
import { ToolAbortError, clampTimeout, throwIfAborted } from "./helpers.js";
import { detectLspmux } from "./lspmux.js";
@@ -370,10 +370,36 @@ export function createLspTool(cwd: string): AgentTool