aws-samples / aws-samples/sample-autonomous-cloud-coding-agents

RFC: add typescript-lsp plugin alongside pyright-lsp in .claude/settings.json

Open
#214 2 comments 0 reactions 0 assignees View on GitHub
RFC-proposal tooling
Dominant language
TypeScript
Stars
143
Forks
46
Avg merge
3d 9h
Merged PRs (30d)
20

Description

## Context

`.claude/settings.json` currently enables `pyright-lsp` for real-time TypeScript diagnostics during Claude Code editing sessions. This RFC asks whether we should also enable `typescript-lsp` (which runs `tsserver` — the same engine behind `tsc`).

Both are type-checkers for TypeScript. They have different implementations, different trade-offs, and occasionally produce different diagnostics for the same code.

## Current setup

| Component | Role |
|-----------|------|
| `tsc` (build step) | Compiles `src/` → `lib/`, emits `.d.ts`, uses `.tsbuildinfo` for incremental builds |
| `pyright-lsp` (Claude Code plugin) | Real-time type diagnostics during editing |
| Pre-commit hooks | Run `tsc --noEmit` + ESLint before push |

## Arguments for adding typescript-lsp

1. **Module resolution fidelity** — `tsserver` uses the identical resolver as `tsc`. In a `"moduleResolution": "nodenext"` project with CDK alpha packages (`@aws-cdk/aws-bedrock-agentcore-alpha`), conditional exports, and `resolveJsonModule`, there are known divergences where Pyright and `tsc` disagree on import validity. `tsserver` catches what `tsc` would reject.

2. **jsii-generated types** — CDK constructs have `.jsii` assembly metadata. `tsc`/`tsserver` respects these for overload resolution and deprecation; Pyright doesn't read `.jsii` manifests.

3. **Incremental state parity** — `tsserver` shares the same `.tsbuildinfo` as the build, so its diagnostics reflect stale cross-file references after renames. Pyright re-analyzes from scratch and may not catch artifacts that cause real build failures.

4. **Two independent oracles** — When two type-checkers disagree, that often signals a subtle real issue (unsound assertion, conditional type edge case). Seeing both perspectives before committing reduces "passes locally, fails CI" roundtrips.

5. **Rename/refactor accuracy** — `tsserver` rename follows the compiler's semantic graph exactly, including re-exports and namespace-qualified references in CDK construct trees.

6. **Reduces need for local `tsc --noEmit`** — Pre-push hooks run `tsc` which triggers CDK synth artifacts that fill `/tmp` on this system. Incremental `tsserver` diagnostics during editing could catch the same errors without a full compile pass.

## Arguments against adding typescript-lsp

1. **Diagnostic noise from disagreements** — When Pyright says "clean" and `tsserver` flags something (or vice versa), Claude Code must decide which to trust. Divergent diagnostics may cause unnecessary edits or confusion.

2. **Resource cost** — Running two full TypeScript analysis engines concurrently doubles memory and CPU for type-checking. On resource-constrained dev instances this may degrade responsiveness.

3. **Pyright is already sufficient** — Pyright covers `strict: true`, `strictNullChecks`, `noImplicitAny`, and all the flags this project uses. The build step (`tsc`) catches anything Pyright misses before code reaches CI.

4. **Maintenance burden** — Two LSPs may surface conflicting quick-fixes or code actions, requiring contributors to learn which to follow.

5. **The actual divergences are rare** — In practice, Pyright and `tsc` agree on 99%+ of diagnostics for standard CDK code. The edge cases (alpha packages, `.jsii`, conditional exports) may not justify the overhead.

## Questions for the team

- Have we experienced CI failures that `tsserver` diagnostics would have caught but Pyright missed?
- Is the `/tmp` fill issue from pre-push hooks a strong enough motivator to shift type-checking entirely to LSP-time?
- Would we enable both LSPs or replace Pyright with typescript-lsp?
- Are there performance concerns on the dev instances we use?

## References

- Current config: `.claude/settings.json`
- TSConfig: `cdk/tsconfig.json` (`module: "NodeNext"`, `strict: true`, `incremental: true`)
- Related: `/tmp` fill issue from CDK synth during hooks

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.