Skip to content

Commit 3d2e852

Browse files
GordonBeemingclaudegitbutler-client
authored
feat: Automatic LSP configuration for Copilot CLI (#74) (#84)
* feat: Automatic LSP configuration for Copilot CLI (#74) Automatically configure Language Server Protocol (LSP) servers in container images so Copilot CLI gets code intelligence out of the box. - Add lsp-typescript snippet: installs typescript-language-server for all images - Add lsp-csharp snippet: installs csharp-ls for dotnet images with .NET 10 SDK (csharp-ls v0.22.0 only ships net10.0 TFM, so dotnet-8/9 excluded) - Add lsp-rust snippet: adds rust-analyzer via rustup for rust images - Add lsp-golang snippet: installs gopls for golang images - Each snippet writes a config fragment to /etc/copilot/lsp-config.d/ - Entrypoint merges fragments into ~/.copilot/lsp-config.json at startup (skipped if user provides their own) - Update images.json and regenerate all Dockerfiles Closes #74 Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: GitButler <gitbutler@gitbutler.com> * fix: Pin LSP server versions and add error handling Address PR review feedback: - Add ARG for typescript, typescript-language-server versions (default: latest) - Add ARG for csharp-ls version (default: latest) - Add ARG for gopls version (default: latest) - Use --tool-path for csharp-ls instead of -g + symlink - Add try/catch per LSP config fragment in entrypoint to prevent malformed JSON from bricking container startup - Regenerate all Dockerfiles Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: GitButler <gitbutler@gitbutler.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: GitButler <gitbutler@gitbutler.com>
1 parent 4a7957a commit 3d2e852

17 files changed

Lines changed: 250 additions & 15 deletions

.github/copilot-instructions.md

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,29 +39,28 @@ You can also use the command `session-info` for more info on mounts for this pro
3939

4040
3. **Build properties**: `Directory.Build.props`
4141

42-
- Line 4: `<CopilotHereVersion>YYYY.MM.DD</CopilotHereVersion>`
42+
- Reads `CopilotHereVersion` from the `VERSION` file automatically (no manual edit needed)
4343

4444
4. **Build info**: `app/Infrastructure/BuildInfo.cs`
4545

4646
- Line 13: `public const string BuildDate = "YYYY.MM.DD";`
4747

48-
5. **This file**: `.github/copilot-instructions.md`
49-
- Update "Current version" below
50-
5148
### Verification Checklist
5249

5350
Before committing, verify all 5 locations have the EXACT SAME version:
5451

5552
```bash
5653
# Quick check - all should show the same version
54+
cat VERSION
5755
grep "Version: " copilot_here.sh
5856
grep "Version: " copilot_here.ps1
5957
grep "COPILOT_HERE_VERSION=" copilot_here.sh
6058
grep "CopilotHereVersion =" copilot_here.ps1
61-
grep "CopilotHereVersion>" Directory.Build.props
6259
grep "BuildDate = " app/Infrastructure/BuildInfo.cs
6360
```
6461

62+
Use `scripts/bump-version.sh YYYY.MM.DD` to update all locations at once.
63+
6564
### When to Update Version
6665

6766
- Any modification to shell function code

docker/generated/Dockerfile.default

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,17 @@ RUN ARCH=$(dpkg --print-architecture) \
4444
&& rm /tmp/powershell.tar.gz; \
4545
fi
4646

47+
# --- snippet: lsp-typescript ---
48+
# Install TypeScript Language Server for code intelligence
49+
ARG TYPESCRIPT_VERSION=latest
50+
ARG TYPESCRIPT_LANGUAGE_SERVER_VERSION=latest
51+
RUN npm install -g typescript@${TYPESCRIPT_VERSION} typescript-language-server@${TYPESCRIPT_LANGUAGE_SERVER_VERSION}
52+
53+
# Write LSP config fragment for TypeScript
54+
RUN mkdir -p /etc/copilot/lsp-config.d && \
55+
echo '{ "lspServers": { "typescript": { "command": "typescript-language-server", "args": ["--stdio"], "fileExtensions": { ".ts": "typescript", ".tsx": "typescriptreact", ".js": "javascript", ".jsx": "javascriptreact" } } } }' \
56+
> /etc/copilot/lsp-config.d/typescript.json
57+
4758
# --- snippet: copilot-cli ---
4859
# ARG for the Copilot CLI version - passed from build process
4960
# This ensures cache invalidation when a new version is available

docker/generated/Dockerfile.dotnet

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,28 @@ RUN wget https://dot.net/v1/dotnet-install.sh -O dotnet-install.sh \
9595
fi \
9696
&& rm dotnet-install.sh
9797

98+
# --- snippet: lsp-typescript ---
99+
# Install TypeScript Language Server for code intelligence
100+
ARG TYPESCRIPT_VERSION=latest
101+
ARG TYPESCRIPT_LANGUAGE_SERVER_VERSION=latest
102+
RUN npm install -g typescript@${TYPESCRIPT_VERSION} typescript-language-server@${TYPESCRIPT_LANGUAGE_SERVER_VERSION}
103+
104+
# Write LSP config fragment for TypeScript
105+
RUN mkdir -p /etc/copilot/lsp-config.d && \
106+
echo '{ "lspServers": { "typescript": { "command": "typescript-language-server", "args": ["--stdio"], "fileExtensions": { ".ts": "typescript", ".tsx": "typescriptreact", ".js": "javascript", ".jsx": "javascriptreact" } } } }' \
107+
> /etc/copilot/lsp-config.d/typescript.json
108+
109+
# --- snippet: lsp-csharp ---
110+
# Install C# Language Server for code intelligence
111+
# Install directly to a shared location so appuser can access it
112+
ARG CSHARP_LS_VERSION=latest
113+
RUN dotnet tool install csharp-ls --tool-path /usr/local/bin --version ${CSHARP_LS_VERSION}
114+
115+
# Write LSP config fragment for C#
116+
RUN mkdir -p /etc/copilot/lsp-config.d && \
117+
echo '{ "lspServers": { "csharp": { "command": "csharp-ls", "args": [], "fileExtensions": { ".cs": "csharp", ".csx": "csharp" } } } }' \
118+
> /etc/copilot/lsp-config.d/csharp.json
119+
98120
# --- snippet: copilot-cli ---
99121
# ARG for the Copilot CLI version - passed from build process
100122
# This ensures cache invalidation when a new version is available

docker/generated/Dockerfile.dotnet-10

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,28 @@ RUN wget https://dot.net/v1/dotnet-install.sh -O dotnet-install.sh \
6969
fi \
7070
&& rm dotnet-install.sh
7171

72+
# --- snippet: lsp-typescript ---
73+
# Install TypeScript Language Server for code intelligence
74+
ARG TYPESCRIPT_VERSION=latest
75+
ARG TYPESCRIPT_LANGUAGE_SERVER_VERSION=latest
76+
RUN npm install -g typescript@${TYPESCRIPT_VERSION} typescript-language-server@${TYPESCRIPT_LANGUAGE_SERVER_VERSION}
77+
78+
# Write LSP config fragment for TypeScript
79+
RUN mkdir -p /etc/copilot/lsp-config.d && \
80+
echo '{ "lspServers": { "typescript": { "command": "typescript-language-server", "args": ["--stdio"], "fileExtensions": { ".ts": "typescript", ".tsx": "typescriptreact", ".js": "javascript", ".jsx": "javascriptreact" } } } }' \
81+
> /etc/copilot/lsp-config.d/typescript.json
82+
83+
# --- snippet: lsp-csharp ---
84+
# Install C# Language Server for code intelligence
85+
# Install directly to a shared location so appuser can access it
86+
ARG CSHARP_LS_VERSION=latest
87+
RUN dotnet tool install csharp-ls --tool-path /usr/local/bin --version ${CSHARP_LS_VERSION}
88+
89+
# Write LSP config fragment for C#
90+
RUN mkdir -p /etc/copilot/lsp-config.d && \
91+
echo '{ "lspServers": { "csharp": { "command": "csharp-ls", "args": [], "fileExtensions": { ".cs": "csharp", ".csx": "csharp" } } } }' \
92+
> /etc/copilot/lsp-config.d/csharp.json
93+
7294
# --- snippet: copilot-cli ---
7395
# ARG for the Copilot CLI version - passed from build process
7496
# This ensures cache invalidation when a new version is available

docker/generated/Dockerfile.dotnet-8

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,17 @@ RUN wget https://dot.net/v1/dotnet-install.sh -O dotnet-install.sh \
6969
fi \
7070
&& rm dotnet-install.sh
7171

72+
# --- snippet: lsp-typescript ---
73+
# Install TypeScript Language Server for code intelligence
74+
ARG TYPESCRIPT_VERSION=latest
75+
ARG TYPESCRIPT_LANGUAGE_SERVER_VERSION=latest
76+
RUN npm install -g typescript@${TYPESCRIPT_VERSION} typescript-language-server@${TYPESCRIPT_LANGUAGE_SERVER_VERSION}
77+
78+
# Write LSP config fragment for TypeScript
79+
RUN mkdir -p /etc/copilot/lsp-config.d && \
80+
echo '{ "lspServers": { "typescript": { "command": "typescript-language-server", "args": ["--stdio"], "fileExtensions": { ".ts": "typescript", ".tsx": "typescriptreact", ".js": "javascript", ".jsx": "javascriptreact" } } } }' \
81+
> /etc/copilot/lsp-config.d/typescript.json
82+
7283
# --- snippet: copilot-cli ---
7384
# ARG for the Copilot CLI version - passed from build process
7485
# This ensures cache invalidation when a new version is available

docker/generated/Dockerfile.dotnet-9

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,17 @@ RUN wget https://dot.net/v1/dotnet-install.sh -O dotnet-install.sh \
6969
fi \
7070
&& rm dotnet-install.sh
7171

72+
# --- snippet: lsp-typescript ---
73+
# Install TypeScript Language Server for code intelligence
74+
ARG TYPESCRIPT_VERSION=latest
75+
ARG TYPESCRIPT_LANGUAGE_SERVER_VERSION=latest
76+
RUN npm install -g typescript@${TYPESCRIPT_VERSION} typescript-language-server@${TYPESCRIPT_LANGUAGE_SERVER_VERSION}
77+
78+
# Write LSP config fragment for TypeScript
79+
RUN mkdir -p /etc/copilot/lsp-config.d && \
80+
echo '{ "lspServers": { "typescript": { "command": "typescript-language-server", "args": ["--stdio"], "fileExtensions": { ".ts": "typescript", ".tsx": "typescriptreact", ".js": "javascript", ".jsx": "javascriptreact" } } } }' \
81+
> /etc/copilot/lsp-config.d/typescript.json
82+
7283
# --- snippet: copilot-cli ---
7384
# ARG for the Copilot CLI version - passed from build process
7485
# This ensures cache invalidation when a new version is available

docker/generated/Dockerfile.dotnet-playwright

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,28 @@ RUN npx playwright install --with-deps
136136
# Make playwright browsers directory world-writable so any UID can access/update them
137137
RUN chmod -R 777 /ms-playwright
138138

139+
# --- snippet: lsp-typescript ---
140+
# Install TypeScript Language Server for code intelligence
141+
ARG TYPESCRIPT_VERSION=latest
142+
ARG TYPESCRIPT_LANGUAGE_SERVER_VERSION=latest
143+
RUN npm install -g typescript@${TYPESCRIPT_VERSION} typescript-language-server@${TYPESCRIPT_LANGUAGE_SERVER_VERSION}
144+
145+
# Write LSP config fragment for TypeScript
146+
RUN mkdir -p /etc/copilot/lsp-config.d && \
147+
echo '{ "lspServers": { "typescript": { "command": "typescript-language-server", "args": ["--stdio"], "fileExtensions": { ".ts": "typescript", ".tsx": "typescriptreact", ".js": "javascript", ".jsx": "javascriptreact" } } } }' \
148+
> /etc/copilot/lsp-config.d/typescript.json
149+
150+
# --- snippet: lsp-csharp ---
151+
# Install C# Language Server for code intelligence
152+
# Install directly to a shared location so appuser can access it
153+
ARG CSHARP_LS_VERSION=latest
154+
RUN dotnet tool install csharp-ls --tool-path /usr/local/bin --version ${CSHARP_LS_VERSION}
155+
156+
# Write LSP config fragment for C#
157+
RUN mkdir -p /etc/copilot/lsp-config.d && \
158+
echo '{ "lspServers": { "csharp": { "command": "csharp-ls", "args": [], "fileExtensions": { ".cs": "csharp", ".csx": "csharp" } } } }' \
159+
> /etc/copilot/lsp-config.d/csharp.json
160+
139161
# --- snippet: copilot-cli ---
140162
# ARG for the Copilot CLI version - passed from build process
141163
# This ensures cache invalidation when a new version is available

docker/generated/Dockerfile.dotnet-rust

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,37 @@ RUN chmod -R a+rwX /usr/local/cargo
116116
# Verify installation
117117
RUN rustc --version && cargo --version
118118

119+
# --- snippet: lsp-typescript ---
120+
# Install TypeScript Language Server for code intelligence
121+
ARG TYPESCRIPT_VERSION=latest
122+
ARG TYPESCRIPT_LANGUAGE_SERVER_VERSION=latest
123+
RUN npm install -g typescript@${TYPESCRIPT_VERSION} typescript-language-server@${TYPESCRIPT_LANGUAGE_SERVER_VERSION}
124+
125+
# Write LSP config fragment for TypeScript
126+
RUN mkdir -p /etc/copilot/lsp-config.d && \
127+
echo '{ "lspServers": { "typescript": { "command": "typescript-language-server", "args": ["--stdio"], "fileExtensions": { ".ts": "typescript", ".tsx": "typescriptreact", ".js": "javascript", ".jsx": "javascriptreact" } } } }' \
128+
> /etc/copilot/lsp-config.d/typescript.json
129+
130+
# --- snippet: lsp-csharp ---
131+
# Install C# Language Server for code intelligence
132+
# Install directly to a shared location so appuser can access it
133+
ARG CSHARP_LS_VERSION=latest
134+
RUN dotnet tool install csharp-ls --tool-path /usr/local/bin --version ${CSHARP_LS_VERSION}
135+
136+
# Write LSP config fragment for C#
137+
RUN mkdir -p /etc/copilot/lsp-config.d && \
138+
echo '{ "lspServers": { "csharp": { "command": "csharp-ls", "args": [], "fileExtensions": { ".cs": "csharp", ".csx": "csharp" } } } }' \
139+
> /etc/copilot/lsp-config.d/csharp.json
140+
141+
# --- snippet: lsp-rust ---
142+
# Install Rust Analyzer for code intelligence
143+
RUN rustup component add rust-analyzer
144+
145+
# Write LSP config fragment for Rust
146+
RUN mkdir -p /etc/copilot/lsp-config.d && \
147+
echo '{ "lspServers": { "rust": { "command": "rust-analyzer", "args": [], "fileExtensions": { ".rs": "rust" } } } }' \
148+
> /etc/copilot/lsp-config.d/rust.json
149+
119150
# --- snippet: copilot-cli ---
120151
# ARG for the Copilot CLI version - passed from build process
121152
# This ensures cache invalidation when a new version is available

docker/generated/Dockerfile.golang

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,27 @@ RUN mkdir -p ${GOPATH} \
6363
# Verify installation
6464
RUN go version
6565

66+
# --- snippet: lsp-typescript ---
67+
# Install TypeScript Language Server for code intelligence
68+
ARG TYPESCRIPT_VERSION=latest
69+
ARG TYPESCRIPT_LANGUAGE_SERVER_VERSION=latest
70+
RUN npm install -g typescript@${TYPESCRIPT_VERSION} typescript-language-server@${TYPESCRIPT_LANGUAGE_SERVER_VERSION}
71+
72+
# Write LSP config fragment for TypeScript
73+
RUN mkdir -p /etc/copilot/lsp-config.d && \
74+
echo '{ "lspServers": { "typescript": { "command": "typescript-language-server", "args": ["--stdio"], "fileExtensions": { ".ts": "typescript", ".tsx": "typescriptreact", ".js": "javascript", ".jsx": "javascriptreact" } } } }' \
75+
> /etc/copilot/lsp-config.d/typescript.json
76+
77+
# --- snippet: lsp-golang ---
78+
# Install gopls (Go Language Server) for code intelligence
79+
ARG GOPLS_VERSION=latest
80+
RUN go install golang.org/x/tools/gopls@${GOPLS_VERSION}
81+
82+
# Write LSP config fragment for Go
83+
RUN mkdir -p /etc/copilot/lsp-config.d && \
84+
echo '{ "lspServers": { "go": { "command": "gopls", "args": ["serve"], "fileExtensions": { ".go": "go" } } } }' \
85+
> /etc/copilot/lsp-config.d/golang.json
86+
6687
# --- snippet: copilot-cli ---
6788
# ARG for the Copilot CLI version - passed from build process
6889
# This ensures cache invalidation when a new version is available

docker/generated/Dockerfile.playwright

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,17 @@ RUN npx playwright install --with-deps
8585
# Make playwright browsers directory world-writable so any UID can access/update them
8686
RUN chmod -R 777 /ms-playwright
8787

88+
# --- snippet: lsp-typescript ---
89+
# Install TypeScript Language Server for code intelligence
90+
ARG TYPESCRIPT_VERSION=latest
91+
ARG TYPESCRIPT_LANGUAGE_SERVER_VERSION=latest
92+
RUN npm install -g typescript@${TYPESCRIPT_VERSION} typescript-language-server@${TYPESCRIPT_LANGUAGE_SERVER_VERSION}
93+
94+
# Write LSP config fragment for TypeScript
95+
RUN mkdir -p /etc/copilot/lsp-config.d && \
96+
echo '{ "lspServers": { "typescript": { "command": "typescript-language-server", "args": ["--stdio"], "fileExtensions": { ".ts": "typescript", ".tsx": "typescriptreact", ".js": "javascript", ".jsx": "javascriptreact" } } } }' \
97+
> /etc/copilot/lsp-config.d/typescript.json
98+
8899
# --- snippet: copilot-cli ---
89100
# ARG for the Copilot CLI version - passed from build process
90101
# This ensures cache invalidation when a new version is available

0 commit comments

Comments
 (0)