Skip to content
This repository was archived by the owner on Jan 13, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: ["3.12"]
python-version: ["3.13"]
os: [ubuntu-latest]

steps:
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/release-beta.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ jobs:
- name: Install uv
uses: astral-sh/setup-uv@v7
with:
python-version: "3.12"
python-version: "3.13"
enable-cache: true

- name: Check version
Expand Down Expand Up @@ -69,7 +69,7 @@ jobs:
- name: Install uv and set Python version
uses: astral-sh/setup-uv@v7
with:
python-version: "3.12"
python-version: "3.13"
enable-cache: true

- name: Build sdist and wheel
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
- name: Install uv
uses: astral-sh/setup-uv@v7
with:
python-version: "3.12"
python-version: "3.13"
enable-cache: true

- name: Check version
Expand Down Expand Up @@ -69,7 +69,7 @@ jobs:
- name: Install uv and set Python version
uses: astral-sh/setup-uv@v7
with:
python-version: "3.12"
python-version: "3.13"
enable-cache: true

- name: Build sdist and wheel
Expand Down
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
[![Python](https://img.shields.io/badge/Python-3.13+-blue.svg)](https://python.org)
[![License](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)

> **⚠️ Windows Temporary Not Supported**
> Due to implementation details, `lsp-cli` does not currently support Windows. Support for Windows will be added in the next version.

A powerful command-line interface for the [**Language Server Agent Protocol (LSAP)**](https://github.com/lsp-client/LSAP). `lsp-cli` provides a bridge between traditional [Language Server Protocol (LSP)](https://microsoft.github.io/language-server-protocol/) servers and high-level agentic workflows, offering structured data access and a robust background server management system.

Built on top of [lsp-client](https://github.com/lsp-client/lsp-client) and [LSAP](https://github.com/lsp-client/LSAP), this tool is designed for developers and AI agents who need reliable, fast, and structured access to language intelligence.
Expand Down Expand Up @@ -31,7 +34,7 @@ Built on top of [lsp-client](https://github.com/lsp-client/lsp-client) and [LSAP
More supported languages coming very soon!

```bash
uv tool install lsp-cli
uv tool install --python 3.13 lsp-cli
```

## Quick Start
Expand Down
2 changes: 2 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ classifiers = [
"Programming Language :: Python",
"Programming Language :: Python :: 3.13",
"License :: OSI Approved :: MIT License",
"Operating System :: POSIX :: Linux",
"Operating System :: MacOS",
]
dependencies = [
"anyio>=4.12.0",
Expand Down
19 changes: 19 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
"""Shared test fixtures and utilities for LSP CLI tests."""

import subprocess
from pathlib import Path


class BaseLSPTest:
"""Base class for LSP CLI tests with common helper methods."""

def run_lsp_command(self, *args, timeout=30):
"""Run an lsp command and return the result."""
result = subprocess.run(
["uv", "run", "lsp"] + list(args),
capture_output=True,
text=True,
timeout=timeout,
cwd=Path(__file__).parent.parent,
)
return result
10 changes: 10 additions & 0 deletions tests/fixtures/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Build artifacts
node_modules/
target/
*.pyc
__pycache__/

# Lock files that might be generated
package-lock.json
yarn.lock
Cargo.lock
35 changes: 35 additions & 0 deletions tests/fixtures/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Test Fixtures

This directory contains minimal test projects for each supported language in LSP CLI.

## Purpose

These fixtures are used by the language support tests (`test_language_support.py`) to verify that LSP CLI can correctly:
- Detect and start language servers for each supported language
- Manage server lifecycle (start, list, stop)
- Handle multiple language servers simultaneously

## Structure

Each subdirectory contains a minimal but valid project for its respective language:

- **go_project/**: Go project with `go.mod` and simple main package
- **rust_project/**: Rust project with `Cargo.toml` and src directory
- **typescript_project/**: TypeScript project with `package.json`, `tsconfig.json`, and TypeScript file
- **javascript_project/**: JavaScript project with `package.json` and ES module
- **deno_project/**: Deno project with `deno.json` configuration

## Requirements

For the tests to work, the following language servers must be installed:
- `basedpyright` (Python)
- `gopls` (Go)
- `rust-analyzer` (Rust)
- `typescript-language-server` (TypeScript/JavaScript)
- `deno` (Deno)

However, the tests will skip or fail gracefully if the required language server is not installed or cannot be started for a project.

## Maintenance

These fixtures should remain minimal and focused. They exist only to verify basic LSP server integration, not to test language-specific features.
5 changes: 5 additions & 0 deletions tests/fixtures/deno_project/deno.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"tasks": {
"run": "deno run main.ts"
}
}
25 changes: 25 additions & 0 deletions tests/fixtures/deno_project/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/**
* A simple greeter class
*/
export class Greeter {
private name: string;

/**
* Creates a new Greeter instance
* @param name The name to greet
*/
constructor(name: string) {
this.name = name;
}

/**
* Returns a greeting message
* @returns The greeting message
*/
greet(): string {
return `Hello, ${this.name}!`;
}
}

const greeter = new Greeter("World");
console.log(greeter.greet());
3 changes: 3 additions & 0 deletions tests/fixtures/go_project/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module example.com/hello

go 1.21
23 changes: 23 additions & 0 deletions tests/fixtures/go_project/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package main

import "fmt"

// Greeter provides greeting functionality
type Greeter struct {
name string
}

// NewGreeter creates a new Greeter instance
func NewGreeter(name string) *Greeter {
return &Greeter{name: name}
}

// Greet returns a greeting message
func (g *Greeter) Greet() string {
return fmt.Sprintf("Hello, %s!", g.name)
}

func main() {
greeter := NewGreeter("World")
fmt.Println(greeter.Greet())
}
23 changes: 23 additions & 0 deletions tests/fixtures/javascript_project/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/**
* A simple greeter class
*/
export class Greeter {
/**
* Creates a new Greeter instance
* @param {string} name - The name to greet
*/
constructor(name) {
this.name = name;
}

/**
* Returns a greeting message
* @returns {string} The greeting message
*/
greet() {
return `Hello, ${this.name}!`;
}
}

const greeter = new Greeter("World");
console.log(greeter.greet());
7 changes: 7 additions & 0 deletions tests/fixtures/javascript_project/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"name": "hello-javascript",
"version": "1.0.0",
"description": "Test JavaScript project",
"main": "index.js",
"type": "module"
}
6 changes: 6 additions & 0 deletions tests/fixtures/rust_project/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[package]
name = "hello"
version = "0.1.0"
edition = "2021"

[dependencies]
21 changes: 21 additions & 0 deletions tests/fixtures/rust_project/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/// A simple greeter struct
pub struct Greeter {
name: String,
}

impl Greeter {
/// Creates a new Greeter instance
pub fn new(name: String) -> Self {
Greeter { name }
}

/// Returns a greeting message
pub fn greet(&self) -> String {
format!("Hello, {}!", self.name)
}
}

fn main() {
let greeter = Greeter::new(String::from("World"));
println!("{}", greeter.greet());
}
25 changes: 25 additions & 0 deletions tests/fixtures/typescript_project/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/**
* A simple greeter class
*/
export class Greeter {
private name: string;

/**
* Creates a new Greeter instance
* @param name The name to greet
*/
constructor(name: string) {
this.name = name;
}

/**
* Returns a greeting message
* @returns The greeting message
*/
greet(): string {
return `Hello, ${this.name}!`;
}
}

const greeter = new Greeter("World");
console.log(greeter.greet());
12 changes: 12 additions & 0 deletions tests/fixtures/typescript_project/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"name": "hello-typescript",
"version": "1.0.0",
"description": "Test TypeScript project",
"main": "index.ts",
"scripts": {
"build": "tsc"
},
"devDependencies": {
"typescript": "5.7.2"
}
}
10 changes: 10 additions & 0 deletions tests/fixtures/typescript_project/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
}
}
Loading