lsp

How the atopile Language Server works (pygls), how it builds per-document graphs for completion/hover/defs, and the invariants for keeping it fast and crash-proof.

3,147 stars

Best use case

lsp is best used when you need a repeatable AI agent workflow instead of a one-off prompt. It is especially useful for teams working in multi. How the atopile Language Server works (pygls), how it builds per-document graphs for completion/hover/defs, and the invariants for keeping it fast and crash-proof.

How the atopile Language Server works (pygls), how it builds per-document graphs for completion/hover/defs, and the invariants for keeping it fast and crash-proof.

Users should expect a more consistent workflow output, faster repeated execution, and less time spent rewriting prompts from scratch.

Practical example

Example input

Use the "lsp" skill to help with this workflow task. Context: How the atopile Language Server works (pygls), how it builds per-document graphs for completion/hover/defs, and the invariants for keeping it fast and crash-proof.

Example output

A structured workflow result with clearer steps, more consistent formatting, and an output that is easier to reuse in the next run.

When to use this skill

  • Use this skill when you want a reusable workflow rather than writing the same prompt again and again.

When not to use this skill

  • Do not use this when you only need a one-off answer and do not need a reusable workflow.
  • Do not use it if you cannot install or maintain the related files, repository context, or supporting tools.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/lsp/SKILL.md --create-dirs "https://raw.githubusercontent.com/atopile/atopile/main/.claude/skills/lsp/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/lsp/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How lsp Compares

Feature / AgentlspStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

How the atopile Language Server works (pygls), how it builds per-document graphs for completion/hover/defs, and the invariants for keeping it fast and crash-proof.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

Related Guides

SKILL.md Source

# LSP Module

The `lsp` module (located in `src/atopile/lsp/`) implements the Language Server Protocol for atopile. It provides IDE features like autocomplete, go-to-definition, and diagnostics (error reporting) for `ato` files.

## Quick Start

Run the server on stdio (what editors expect):

```bash
python -m atopile.lsp.lsp_server
```

## Relevant Files

- Server implementation: `src/atopile/lsp/lsp_server.py`
  - owns global `LSP_SERVER` (pygls `LanguageServer`)
  - maintains per-document `DocumentState` (graph/typegraph/build_result)
  - implements completion/hover/definition/diagnostics handlers
- Utilities: `src/atopile/lsp/lsp_utils.py`
- Optional debugging helper: `src/atopile/lsp/_debug_server.py`

## Dependants (Call Sites)

- **VSCode Extension**: The designated client for this server.
- **Compiler**: The LSP invokes the compiler (often in a partial or fault-tolerant mode) to understand the code structure.

## How to Work With / Develop / Test

### Core Concepts
- **Partial Compilation**: Unlike the CLI build, the LSP must handle broken or incomplete code without crashing.
- **Latency**: Features must be fast (<50ms for typing, <200ms for completion).
- **Per-document graphs**: each open document has an isolated `GraphView` + `TypeGraph` stored in `DocumentState`.
- **Keep last good build**: the server keeps the last successful `BuildFileResult` to power completion/hover even when the current edit has errors.

### Development Workflow
1) Edit handlers/helpers in `src/atopile/lsp/lsp_server.py`.
2) Run completion tests (fast loop) and verify GraphView cleanup paths.

### Testing
- Integration-style tests: `ato dev test --llm test/test_lsp_completion.py -q`

## Best Practices
- **Robustness**: Never let the server crash. Catch all exceptions in handlers and log them.
- **Debouncing**: Don't trigger expensive operations on every keystroke.

## Core Invariants (easy to regress)
- Always destroy old graphs on rebuild/reset (`DocumentState.reset_graph` calls `GraphView.destroy()`).
- Do not assume builds succeed; most features must handle:
  - syntax errors (ANTLR)
  - partial typegraphs
  - exceptions from linking/deferred execution

Related Skills

solver

3147
from atopile/atopile

How the Faebryk parameter solver works (Sets/Literals, Parameters, Expressions), the core invariants enforced during mutation, and practical workflows for debugging and extending the solver. Use when implementing or modifying constraint solving, parameter bounds, or debugging expression simplification.

SEXP Benchmark Strategy

3147
from atopile/atopile

## Goal

sexp

3147
from atopile/atopile

How the Zig S-expression engine and typed KiCad models work, how they are exposed to Python (pyzig_sexp), and the invariants around parsing, formatting, and freeing. Use when working with KiCad file parsing, S-expression generation, or layout sync.

pyzig

3147
from atopile/atopile

How the Zig↔Python binding layer works (pyzig), including build-on-import, wrapper generation patterns, ownership rules, and where to add new exported APIs. Use when adding Zig-Python bindings, modifying native extensions, or debugging C-API interactions.

planning

3147
from atopile/atopile

Spec-driven planning for complex design tasks: when to plan, how to write specs as .ato files, and how to verify against requirements.

Package Agent

3147
from atopile/atopile

You are a package specialist.

library

3147
from atopile/atopile

How the Faebryk component library is structured, how `_F.py` is generated, and the conventions/invariants for adding new library modules. Use when adding or modifying library components, traits, or module definitions.

graph

3147
from atopile/atopile

How the Zig-backed instance graph works (GraphView/NodeReference/EdgeReference), the real Python API surface, and the invariants around allocation, attributes, and cleanup. Use when working with low-level graph APIs, memory management, or building systems that traverse the instance graph.

frontend

3147
from atopile/atopile

Frontend standards for atopile extension webviews: architecture, contracts, design system, and testing workflow.

faebryk

3147
from atopile/atopile

How Faebryk's TypeGraph works (GraphView + Zig edges), how to traverse/resolve references, and how FabLL types/traits map onto edge types. Use when working with TypeGraph traversal, edge types, or building type-aware queries.

fabll

3147
from atopile/atopile

How FabLL (faebryk.core.node) maps Python node/trait declarations into the TypeGraph + instance graph, including field/trait invariants and instantiation patterns. Use when defining new components or traits, working with the Node API, or understanding type registration.

domain-layer

3147
from atopile/atopile

Instructions for electronics-specific logic and build processes: netlists, PCBs, build steps, and exporters. Use when implementing or modifying build steps, exporters, PCB generation, or BOM/netlist output.