Skip to main content
The Language Server Protocol (LSP) integration provides powerful code intelligence features including completions, symbol search, and code navigation within sandbox environments.

Overview

Daytona’s LSP support enables:
  • Code completions - Intelligent autocomplete suggestions
  • Symbol search - Find functions, classes, and variables across projects
  • Document symbols - Extract structure from source files
  • Multi-language support - TypeScript, JavaScript, and Python

Supported Languages

Daytona supports LSP for the following languages:
enum LspLanguageId {
  PYTHON = 'python',
  TYPESCRIPT = 'typescript',
  JAVASCRIPT = 'javascript'
}

Creating an LSP Server

Initialize Language Server

Create and start an LSP server for your project:
const lsp = await sandbox.createLspServer(
  'typescript',          // language
  'workspace/project'    // project root path
);

// Start the language server
await lsp.start();
languageId
LspLanguageId
required
Language server type: ‘typescript’, ‘javascript’, or ‘python’
pathToProject
string
required
Path to project root directory. Relative paths resolved from sandbox working directory.

Document Lifecycle

Open a Document

Notify the LSP server when opening a file:
await lsp.didOpen('workspace/project/src/index.ts');
Opening a document enables language features like diagnostics and completions for that file.

Close a Document

Notify the LSP server when closing a file:
await lsp.didClose('workspace/project/src/index.ts');
Closing documents helps the LSP server manage resources efficiently.
path
string
required
Path to the file. Relative paths resolved from project path set in LSP server constructor.

Code Completions

Get Completion Suggestions

Retrieve intelligent completion suggestions at a cursor position:
const completions = await lsp.completions(
  'workspace/project/src/index.ts',
  {
    line: 10,        // zero-based line number
    character: 15    // zero-based character offset
  }
);

console.log('Incomplete:', completions.isIncomplete);

completions.items.forEach(item => {
  console.log(`${item.label} (${item.kind})`);
  console.log(`  Detail: ${item.detail}`);
  console.log(`  Docs: ${item.documentation}`);
  console.log(`  Insert: ${item.insertText || item.label}`);
});
Position Format:
interface Position {
  line: number;      // Zero-based line number
  character: number; // Zero-based character offset
}
Completion Response:
interface CompletionList {
  isIncomplete: boolean;      // More items available
  items: CompletionItem[];    // Completion suggestions
}

interface CompletionItem {
  label: string;              // Text to display
  kind: number;               // Completion type
  detail?: string;            // Additional info
  documentation?: string;     // Documentation
  sortText?: string;          // Sort order
  filterText?: string;        // Filter text
  insertText?: string;        // Text to insert
}
path
string
required
Path to the file
position
Position
required
Cursor position for completions

Document Symbols

Get all symbols (functions, classes, variables) from a document:
const symbols = await lsp.documentSymbols(
  'workspace/project/src/index.ts'
);

symbols.forEach(symbol => {
  console.log(`${symbol.kind} ${symbol.name}`);
  console.log(`  Location: ${symbol.location}`);
});

Workspace Symbols

Search for symbols across the entire sandbox:
// Search for all symbols containing "User"
const symbols = await lsp.sandboxSymbols('User');

symbols.forEach(symbol => {
  console.log(`${symbol.name} (${symbol.kind})`);
  console.log(`  in ${symbol.location}`);
});
workspaceSymbols() is deprecated. Use sandboxSymbols() instead.
Symbol Response:
interface LspSymbol {
  name: string;        // Symbol name
  kind: string;        // Symbol type (function, class, etc.)
  location: string;    // File location
}
query
string
required
Search query to match against symbol names

Complete Example

import { Daytona, Image } from '@daytonaio/sdk';

const daytona = new Daytona();

const sandbox = await daytona.create({
  image: Image.base('ubuntu:25.10').runCommands(
    'apt-get update && apt-get install -y nodejs npm',
    'npm install -g typescript typescript-language-server'
  ),
  language: 'typescript'
});

try {
  const projectPath = 'workspace/myproject';
  
  // Clone a TypeScript project
  await sandbox.git.clone(
    'https://github.com/user/typescript-project.git',
    projectPath
  );
  
  // Create and start LSP server
  const lsp = await sandbox.createLspServer('typescript', projectPath);
  await lsp.start();
  
  // Find files to analyze
  const matches = await sandbox.fs.searchFiles(
    projectPath,
    '*.ts'
  );
  
  const mainFile = matches.files[0];
  
  // Open document for analysis
  await lsp.didOpen(mainFile);
  
  // Get document symbols
  const symbols = await lsp.documentSymbols(mainFile);
  console.log('Document contains', symbols.length, 'symbols');
  
  symbols.forEach(symbol => {
    console.log(`- ${symbol.kind}: ${symbol.name}`);
  });
  
  // Get completions at a specific position
  const completions = await lsp.completions(mainFile, {
    line: 5,
    character: 10
  });
  
  console.log('\nAvailable completions:');
  completions.items.slice(0, 10).forEach(item => {
    console.log(`- ${item.label}: ${item.detail}`);
  });
  
  // Search for specific symbols across project
  const userSymbols = await lsp.sandboxSymbols('handleRequest');
  console.log('\nFound symbols matching "handleRequest":');
  userSymbols.forEach(symbol => {
    console.log(`- ${symbol.name} in ${symbol.location}`);
  });
  
  // Clean up when done
  await lsp.didClose(mainFile);
  await lsp.stop();
  
} finally {
  await daytona.delete(sandbox);
}

Language-Specific Setup

TypeScript / JavaScript

Ensure TypeScript LSP is installed:
const sandbox = await daytona.create({
  image: Image.base('ubuntu:25.10').runCommands(
    'apt-get update && apt-get install -y nodejs npm',
    'npm install -g typescript typescript-language-server'
  ),
  language: 'typescript'
});

Python

Ensure Python LSP is installed:
const sandbox = await daytona.create({
  image: Image.base('ubuntu:22.04').runCommands(
    'apt-get update',
    'apt-get install -y python3 python3-pip',
    'pip3 install python-lsp-server'
  ),
  language: 'python'
});

Best Practices

Always call didOpen() before getting completions or symbols for a file:
await lsp.didOpen(filePath);
const completions = await lsp.completions(filePath, position);
Release resources by closing documents you’re no longer working with:
await lsp.didClose(filePath);
Always stop the LSP server to free resources:
try {
  await lsp.start();
  // ... use LSP
} finally {
  await lsp.stop();
}
Remember that line and character positions are zero-based:
// Line 1, Column 1 in editor = { line: 0, character: 0 }
const completions = await lsp.completions(file, {
  line: 0,      // First line
  character: 0  // First character
});

Use Cases

Extract structure and symbols from codebases:
const symbols = await lsp.documentSymbols(file);
const functions = symbols.filter(s => s.kind === 'Function');
Use completions to assist with code generation:
const completions = await lsp.completions(file, position);
const suggestions = completions.items.map(i => i.label);
Identify symbols before performing refactoring:
const symbols = await lsp.workspaceSymbols('OldClassName');
// Find all occurrences before renaming

Troubleshooting

If you get “Invalid languageId” error, ensure you’re using one of the supported language IDs: 'python', 'typescript', or 'javascript'.
Make sure the LSP server for your language is installed in the sandbox image before calling start().

Git Operations

Clone repositories for LSP analysis

File System

Search and manage source files

Build docs developers (and LLMs) love