# Lsp Setup

> Install and configure Language Server Protocol (LSP) servers for GitHub Copilot CLI. Use this skill when asked to install, configure, or troubleshoot LSP servers, or when setting up code intelligence for Go, TypeScript/JavaScript, Python, C/C++, or Java.

- Skill: `mengiu64/lsp-setup` (Agent Skill)
- Install (CLI): `npx skillmds@latest add mengiu64/lsp-setup`
- Raw SKILL.md: https://api.skillmd.com/api/skills/mengiu64/lsp-setup/raw
- Safety review: pending (external: skill-scanner PASS, skillspector CAUTION)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: mengiu64 (https://skillmd.com/u/mengiu64)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/mengiu64/lsp-setup

---


# LSP Setup Skill

This skill guides you through installing and configuring LSP servers for GitHub Copilot CLI.
It supports **Linux** and **macOS** and covers 5 language servers.

## General Guidelines

### OS Detection

Always detect the operating system first:

```bash
OS="$(uname -s)"
```

- `Linux` → use `apt` (Debian/Ubuntu) or check for other package managers
- `Darwin` → use `brew`

### Path Conventions

- **Never** use hardcoded absolute paths like `/home/username/...`
- Always use `$HOME` for home directory references
- Resolve binary paths dynamically with `command -v <binary>` or `which <binary>`
- The LSP config file is located at `$HOME/.copilot/lsp-config.json`

### Workflow

For each LSP server:
1. Check if it's already installed (`command -v <binary>`)
2. Install it using the appropriate method for the detected OS
3. Resolve the absolute path of the installed binary
4. Add an entry to `$HOME/.copilot/lsp-config.json`
5. Verify with `/lsp show` and `/lsp test <name>`

---

## LSP Server: Go (gopls)

### Prerequisites
- Go must be installed (`go version`)

### Install

```bash
go install golang.org/x/tools/gopls@latest
```

Works identically on Linux and macOS. The binary is installed to `$HOME/go/bin/gopls` (or `$GOPATH/bin/gopls` if `GOPATH` is set).

### Verify

```bash
GOPLS_PATH="$(command -v gopls || echo "$HOME/go/bin/gopls")"
"$GOPLS_PATH" version
```

### lsp-config.json entry

```json
"go": {
  "command": "<resolved absolute path to gopls>",
  "args": ["serve"],
  "fileExtensions": {
    ".go": "go"
  }
}
```

---

## LSP Server: TypeScript/JavaScript (typescript-language-server)

### Prerequisites
- Node.js must be installed (`node --version`)

### Install

```bash
npm install -g typescript-language-server typescript
```

Works identically on Linux and macOS.

### Verify

```bash
TSL_PATH="$(command -v typescript-language-server)"
"$TSL_PATH" --version
```

### lsp-config.json entry

```json
"typescript": {
  "command": "<resolved absolute path to typescript-language-server>",
  "args": ["--stdio"],
  "fileExtensions": {
    ".ts": "typescript",
    ".tsx": "typescriptreact",
    ".js": "javascript",
    ".jsx": "javascriptreact"
  }
}
```

---

## LSP Server: Python (pylsp)

### Prerequisites
- Python 3 must be installed (`python3 --version`)
- pip3 must be available (`pip3 --version`)

### Install

Detect if `--break-system-packages` is needed (required on Debian/Ubuntu with PEP 668 externally-managed Python):

```bash
OS="$(uname -s)"
if [ "$OS" = "Linux" ] && python3 -c "import sysconfig; print(sysconfig.get_path('stdlib'))" 2>/dev/null | grep -q "/usr/lib"; then
  pip3 install --user --break-system-packages python-lsp-server
else
  pip3 install --user python-lsp-server
fi
```

On macOS with Homebrew Python, `--user` install works without `--break-system-packages`.

### Verify

```bash
PYLSP_PATH="$(command -v pylsp || echo "$HOME/.local/bin/pylsp")"
"$PYLSP_PATH" --help
```

### lsp-config.json entry

```json
"python": {
  "command": "<resolved absolute path to pylsp>",
  "args": [],
  "fileExtensions": {
    ".py": "python"
  }
}
```

---

## LSP Server: C/C++ (clangd)

### Prerequisites
- None (installed via system package manager)

### Install

```bash
OS="$(uname -s)"
if [ "$OS" = "Darwin" ]; then
  # clangd is included with Xcode Command Line Tools or can be installed via brew
  if ! command -v clangd &>/dev/null; then
    brew install llvm
    # clangd will be at $(brew --prefix llvm)/bin/clangd
  fi
elif [ "$OS" = "Linux" ]; then
  sudo apt install -y clangd
fi
```

### Verify

```bash
CLANGD_PATH="$(command -v clangd)"
# On macOS with brew llvm, it may be at: $(brew --prefix llvm)/bin/clangd
if [ -z "$CLANGD_PATH" ] && [ "$(uname -s)" = "Darwin" ]; then
  CLANGD_PATH="$(brew --prefix llvm)/bin/clangd"
fi
"$CLANGD_PATH" --version
```

### lsp-config.json entry

```json
"cpp": {
  "command": "<resolved absolute path to clangd>",
  "args": [],
  "fileExtensions": {
    ".c": "c",
    ".h": "c",
    ".cpp": "cpp",
    ".hpp": "cpp",
    ".cc": "cpp",
    ".cxx": "cpp"
  }
}
```

---

## LSP Server: Java (jdtls)

### Prerequisites
- Java 21+ must be installed (`java -version`)

### Install

1. Download the latest jdtls release:

```bash
JDTLS_VERSION="1.56.0"
JDTLS_BUILD="202601291528"
JDTLS_DIR="$HOME/.local/share/jdtls"
mkdir -p "$JDTLS_DIR"
curl -sL "https://www.eclipse.org/downloads/download.php?file=/jdtls/milestones/${JDTLS_VERSION}/jdt-language-server-${JDTLS_VERSION}-${JDTLS_BUILD}.tar.gz&r=1" \
  -o /tmp/jdtls.tar.gz -L
tar -xzf /tmp/jdtls.tar.gz -C "$JDTLS_DIR"
rm -f /tmp/jdtls.tar.gz
```

2. Create a cross-platform wrapper script:

```bash
mkdir -p "$HOME/.local/bin"
cat > "$HOME/.local/bin/jdtls" << 'WRAPPER'
#!/bin/sh
# Cross-platform JAVA_HOME detection
if [ -z "$JAVA_HOME" ]; then
  OS="$(uname -s)"
  if [ "$OS" = "Darwin" ]; then
    JAVA_HOME="$(/usr/libexec/java_home 2>/dev/null || true)"
  elif [ "$OS" = "Linux" ]; then
    JAVA_BIN="$(readlink -f "$(command -v java)" 2>/dev/null)"
    if [ -n "$JAVA_BIN" ]; then
      JAVA_HOME="$(dirname "$(dirname "$JAVA_BIN")")"
    fi
  fi
  export JAVA_HOME
fi
exec "$HOME/.local/share/jdtls/bin/jdtls" "$@"
WRAPPER
chmod +x "$HOME/.local/bin/jdtls"
```

### Verify

```bash
"$HOME/.local/bin/jdtls" --help
```

### lsp-config.json entry

```json
"java": {
  "command": "<HOME>/.local/bin/jdtls",
  "args": [],
  "fileExtensions": {
    ".java": "java"
  }
}
```

Replace `<HOME>` with the resolved `$HOME` path.

---

## Generating the Full lsp-config.json

After installing the desired LSP servers, generate or update `$HOME/.copilot/lsp-config.json`.

The final file should look like this (include only the servers that were installed):

```json
{
  "lspServers": {
    "go": {
      "command": "<absolute path to gopls>",
      "args": ["serve"],
      "fileExtensions": { ".go": "go" }
    },
    "typescript": {
      "command": "<absolute path to typescript-language-server>",
      "args": ["--stdio"],
      "fileExtensions": {
        ".ts": "typescript",
        ".tsx": "typescriptreact",
        ".js": "javascript",
        ".jsx": "javascriptreact"
      }
    },
    "python": {
      "command": "<absolute path to pylsp>",
      "args": [],
      "fileExtensions": { ".py": "python" }
    },
    "cpp": {
      "command": "<absolute path to clangd>",
      "args": [],
      "fileExtensions": {
        ".c": "c", ".h": "c",
        ".cpp": "cpp", ".hpp": "cpp",
        ".cc": "cpp", ".cxx": "cpp"
      }
    },
    "java": {
      "command": "<absolute path to jdtls>",
      "args": [],
      "fileExtensions": { ".java": "java" }
    }
  }
}
```

**Important**: Always resolve paths dynamically using `command -v` or known install locations. Never hardcode user-specific paths.

---

## Verification

After updating the config, instruct the user to run in Copilot CLI:

```
/lsp reload
/lsp show
```

To test a specific server:

```
/lsp test go
/lsp test typescript
/lsp test python
/lsp test cpp
/lsp test java
```

## References

- [Copilot CLI LSP docs](https://docs.github.com/en/copilot/reference/cli-command-reference)
- [gopls](https://pkg.go.dev/golang.org/x/tools/gopls)
- [typescript-language-server](https://github.com/typescript-language-server/typescript-language-server)
- [python-lsp-server](https://github.com/python-lsp/python-lsp-server)
- [clangd](https://clangd.llvm.org)
- [Eclipse JDT.LS](https://github.com/eclipse-jdtls/eclipse.jdt.ls)

