diff --git a/claude-code/.devcontainer/init-plugins.sh b/claude-code/.devcontainer/init-plugins.sh index ebcf56c..2bea2d7 100755 --- a/claude-code/.devcontainer/init-plugins.sh +++ b/claude-code/.devcontainer/init-plugins.sh @@ -26,6 +26,7 @@ MARKETPLACES=( "GoogleChrome/modern-web-guidance" "AgriciDaniel/claude-seo" "cloudflare/skills" + "rubberduck-studio/typescript-native-lsp" ) for marketplace in "${MARKETPLACES[@]}"; do @@ -41,7 +42,6 @@ done PLUGINS=( "frontend-design@claude-plugins-official" "code-review@claude-plugins-official" - "typescript-lsp@claude-plugins-official" "code-simplifier@claude-plugins-official" "playwright@claude-plugins-official" "superpowers@claude-plugins-official" @@ -57,6 +57,10 @@ PLUGINS=( "ralphex@ralphex" "modern-web-guidance@googlechrome" "claude-seo@agricidaniel-claude-seo" + # Replaces typescript-lsp@claude-plugins-official, which wraps tsserver and fails + # every request on TypeScript 7 (no tsserver.js). Runs `tsc --lsp` on TS 7+ and + # falls back to typescript-language-server on TS 6 and older (#194). + "typescript-native-lsp@typescript-native-lsp" ) for plugin in "${PLUGINS[@]}"; do @@ -67,6 +71,25 @@ for plugin in "${PLUGINS[@]}"; do fi done +# ── Conflicting plugins ───────────────────────────────────────────────────── +# Plugins that claim the same file extensions as one in PLUGINS: Claude Code +# starts only whichever registers first. Not installed above, but a persistent +# ~/.claude volume may still hold them from an older run — disable if enabled. +DISABLED_PLUGINS=( + "typescript-lsp@claude-plugins-official" # superseded by typescript-native-lsp +) + +for plugin in "${DISABLED_PLUGINS[@]}"; do + if claude plugin list --json 2>/dev/null \ + | jq -e --arg id "$plugin" 'any(.[]; .id == $id and .enabled)' >/dev/null; then + if claude plugin disable "$plugin" 2>&1; then + echo "✔ Disabled: $plugin" + else + echo "⚠ Failed to disable: $plugin" >&2 + fi + fi +done + # ~/.claude is a persistent volume, so `install` no-ops after the first run. # Refresh marketplace indexes first — `plugin update` resolves against the cache. if claude plugin marketplace update 2>&1; then diff --git a/claude-code/README.md b/claude-code/README.md index 693ecdf..3cfd482 100644 --- a/claude-code/README.md +++ b/claude-code/README.md @@ -104,13 +104,12 @@ Mark as executable: `chmod +x init-plugins.sh` #### Bundled plugins -`init-plugins.sh` registers five marketplaces and installs the following plugins: +`init-plugins.sh` registers six marketplaces and installs the following plugins: | Marketplace | Plugin | Purpose | |---|---|---| | `anthropics/claude-plugins-official` | `frontend-design` | Production-grade UI/UX scaffolding | | `anthropics/claude-plugins-official` | `code-review` | Multi-agent PR review | -| `anthropics/claude-plugins-official` | `typescript-lsp` | TypeScript language-server tooling | | `anthropics/claude-plugins-official` | `code-simplifier` | Refactors for clarity and consistency | | `anthropics/claude-plugins-official` | `playwright` | Browser MCP (system chromium via `patch-playwright-mcp`) | | `anthropics/claude-plugins-official` | `superpowers` | Workflow skills (TDD, debugging, planning) | @@ -122,6 +121,9 @@ Mark as executable: `chmod +x init-plugins.sh` | `umputun/ralphex` | `ralphex` | Autonomous plan execution | | `GoogleChrome/modern-web-guidance` | `modern-web-guidance` | Accessible, performant, secure modern web patterns ([docs](https://developer.chrome.com/docs/modern-web-guidance)) | | `AgriciDaniel/claude-seo` | `claude-seo` | SEO analysis toolkit — technical SEO, schema, E-E-A-T, GEO/AEO, Google APIs ([repo](https://github.com/AgriciDaniel/claude-seo)) | +| `rubberduck-studio/typescript-native-lsp` | `typescript-native-lsp` | TypeScript/JavaScript LSP: TS 7's native server (`tsc --lsp`), falls back to `typescript-language-server` on TS 6 and older ([repo](https://github.com/rubberduck-studio/typescript-native-lsp)) | + +> **Why not the official `typescript-lsp`:** it runs `typescript-language-server`, which wraps `tsserver`. TypeScript 7 (the native Go port) ships no `tsserver.js`, so on a TS 7 project the official plugin fails every request. `typescript-native-lsp` covers TS 7 and older versions in one plugin. The two must not be enabled together: when two plugins claim `.ts`, Claude Code starts only the first one it registers. That's why `init-plugins.sh` also disables `typescript-lsp` when a persisted `~/.claude` volume still has it (`DISABLED_PLUGINS`). TS 6 and older projects need `typescript-language-server` in the project (`bun add -d typescript-language-server`) or installed globally. The official plugin needed that too. Switch back once [anthropics/claude-plugins-official#4492](https://github.com/anthropics/claude-plugins-official/issues/4492) ships native TS 7 support (#194). To remove a plugin in your project, delete its entry from the local `init-plugins.sh` — the script is a template, not image-baked, so each consumer controls its own list.