Skip to content
NLEN
Illustration: Installing Tabby as a local code assistant with Docker

Installing Tabby as a local code assistant with Docker

By Ivo Donker — compiled with AI assistance (Claude & Gemini)

System requirements (indicative): At least 16 GB of system RAM, an NVIDIA GPU with at least 8 GB of VRAM (such as an RTX 3060, 4060, or higher), and a Linux distribution with Docker and the NVIDIA Container Toolkit. Common model choices as a guideline: StarCoder2-3B for infilling and Qwen2.5-Coder-7B for instruct/chat.

Within the route of self-hosting language models, this guide sits in the phase apply and integrate. Once the underlying server and runtime are set up, we now focus specifically on automating software development. Anyone already familiar with the basics of containerization can first consult the guide on running a local language model in Docker for general background on how container isolation is fundamentally built up.

Tabby is an open-source, self-hostable AI coding assistant that acts as a direct alternative to proprietary cloud services such as GitHub Copilot. Unlike generic chat interfaces, Tabby revolves around two specific tasks: real-time inline code completion (Fill-in-the-Middle) and context-aware interaction through a chat panel in your editor. By deploying Tabby you retain full control over your intellectual property and codebase, without compromising on latency while typing.

Hardware requirements and VRAM calculation for code generation

Code generation places fundamentally different demands on hardware than an average chat LLM. For inline autocomplete, latency is the single most important factor: a suggestion has to appear within 100 to 250 milliseconds so as not to interrupt a developer's typing flow. Anyone who wants to understand which graphics card or memory configuration fits can review the system requirements in the guide on hardware for local LLM setups to make a well-founded choice between dedicated VRAM and system bandwidth.

With Tabby we ideally split the workload across two separate models: a compact FIM model (Fill-in-the-Middle) such as StarCoder2-3B or DeepSeek-Coder-1.3B for real-time completions, and a larger chat model such as Qwen2.5-Coder-7B for complex refactoring or explanation. To determine whether both models fit in video memory simultaneously, the table below offers an indicative overview of the estimated VRAM footprint at various precision levels.

Model Task Format / Precision Estimated VRAM footprint (indicative) GPU guideline
StarCoder2-3B Autocomplete (FIM) FP16 / BF16 ~6.2 GB RTX 3060 (12 GB)
DeepSeek-Coder-1.3B Autocomplete (FIM) FP16 ~3.1 GB GTX 1660 Ti / RTX 3050 (6-8 GB)
Qwen2.5-Coder-7B Chat / Instruct Q4_K_M (GGUF/AWQ) ~5.8 GB RTX 4060 Ti (16 GB)
Qwen2.5-Coder-1.5B Autocomplete & Chat FP16 ~3.8 GB RTX 3060 / 4060 (8 GB)

For a detailed explanation of how compression techniques affect the balance between precision and model size, the documentation points to the article in which quantization and bit reduction are set out clearly. In practice the guideline is that a dedicated graphics card with at least 8 GB to 12 GB of VRAM is advisable to serve inline autocomplete smoothly.

Tabby architecture: FIM versus Chat

Tabby's architecture rests on a modular design optimized specifically for programming languages. Where regular language models predict only what follows after a given prompt, software development requires context on both sides of the cursor. This mechanism is known as Fill-in-the-Middle (FIM).

The FIM mechanism splits the open source file into a prefix (everything before the cursor) and a suffix (everything after the cursor). The model learns to fill in the missing code in between. Tabby manages these context windows itself and combines this with Git repository indexing. That lets the system pass relevant definitions and functions from other files in your project to the prompt as extra context, which raises the accuracy of the proposed code considerably.

Alongside the generation engine, Tabby contains a built-in search index based on Tree-sitter. This parser converts source files directly into an abstract syntax tree (AST). When the developer calls a function defined elsewhere in the project, the indexer recognizes the relation and automatically injects the function signature into the context window of the FIM model. As a result, generated parameters line up seamlessly with existing interfaces within the repository.

Docker Compose configuration with GPU passthrough

To roll out Tabby reproducibly and in isolation, we use Docker Compose in combination with the NVIDIA Container Toolkit. Make sure the official NVIDIA drivers and the container toolkit are installed and configured on the host system beforehand.

Below is a complete docker-compose.yml in which Tabby is configured with CUDA acceleration and persistent storage for downloaded models and repository indices:

services:
  tabby:
    image: registry.tabbyml.com/tabbyml/tabby:0.26.0
    container_name: tabby-server
    restart: unless-stopped
    ports:
      - "8080:8080"
    volumes:
      - ./data:/data
    environment:
      - TABBY_LOG_LEVEL=info
    command:
      - serve
      - --model
      - StarCoder2-3B
      - --chat-model
      - Qwen2.5-Coder-7B
      - --device
      - cuda
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: all
              capabilities: [gpu]

Then bring the stack up from the terminal:

docker compose up -d
docker compose logs -f tabby

During the first start the container automatically downloads the requested weights from the model registry to the mounted volume ./data. Once initialization is complete, the web interface listens on port 8080 of the host system.

Initialization and setting up the administrator account

After starting the container, navigate in your browser to http://localhost:8080 (or the IP address of your local server). The first step is creating the primary administrator account.

In the admin panel you configure the following essential parameters:

Connecting development environments: VS Code and JetBrains

Once the server is running and you have a token, you can set up the client extensions. For Microsoft Visual Studio Code this goes through the official Tabby extension from the marketplace. Anyone who would rather explore alternative extensions can also work through the guide on connecting a local LLM to VS Code for broader integration options.

In VS Code, open the settings (settings.json) and add the server configuration:

{
  "tabby.server.endpoint": "http://127.0.0.1:8080",
  "tabby.server.token": "jouw_gegenereerde_auth_token_hier",
  "tabby.inlineCompletion.triggerMode": "automatic",
  "tabby.inlineCompletion.anonymousUsageTracking": false
}

Within JetBrains IDEs (such as IntelliJ IDEA, PyCharm, or WebStorm) you install the plugin Tabby through the Plugins menu. Then go to Settings > Tools > Tabby, enter the server endpoint, and paste the authentication token. After saving, the status bar in the bottom right immediately shows a status icon once the connection is active.

Comparison: Tabby versus Continue.dev

Developers who want to enrich their workflow with local AI regularly hesitate between Tabby and Continue.dev. Although both solutions run locally, they follow fundamentally different design choices. Anyone who wants to study how that other popular tool works will find all the details in the step-by-step guide on setting up Continue.dev with local models in VS Code.

Property Tabby Continue.dev
Architecture Client-server with a central backend Client-side orchestrator (extension-driven)
Inference engine Integrated (C++ / Rust / llama.cpp) External (connects to Ollama, LM Studio, vLLM)
Focus area Fast FIM autocomplete & indexing Advanced chat, prompt engineering & diff editing
Team functionality Central server management and shared API keys Individual configuration per developer
Client resource footprint Very low (thin client extension) Moderate (manages context and extension runtime)

Measurement method: validating latency and generation speed

The effectiveness of an inline code assistant depends almost entirely on response time. To determine whether your setup meets the practical norms, we measure three crucial parameters: Time To First Token (TTFT), tokens per second during generation, and the acceptance ratio of suggestions.

A reliable measurement method is run directly against Tabby's HTTP endpoints using curl and a timing measurement. This eliminates any network overhead from the IDE extension:

curl -w "\nTijd tot reactie: %{time_starttransfer}s\nTotale tijd: %{time_total}s\n" \
  -X POST http://localhost:8080/v1/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer jouw_gegenereerde_auth_token_hier" \
  -d '{
    "language": "python",
    "segments": {
      "prefix": "def bereken_gemiddelde(waarden: list[float]) -> float:\n    \"\"\"Bereken het gemiddelde van een lijst getallen.\"\"\"\n    ",
      "suffix": "\n    return resultaat"
    }
  }'

Interpreting the measured values follows strict guideline figures:

Security, isolation, and GDPR aspects

The main argument for a local code assistant is data sovereignty. With cloud-based alternatives, program code, internal function names, API structures, and sometimes even hardcoded configurations are sent to external processors. By running Tabby inside a local network, all source code stays within your own infrastructure.

In the context of data minimization and compliance, this approach aligns neatly with the guidelines for privacy-friendly AI use in the workplace. To strengthen the application sandbox further, applying network isolation is advisable. The article on sandboxing LLM tools through Docker isolation explains how containers can be functionally shielded from the public internet by means of strict Docker network rules.

To prevent the Docker container from initiating outbound traffic after the models have been downloaded, you can attach the container to an internal bridge network without a default gateway. That makes it technically impossible for source code fragments to leak outward over a network connection.

Measuring performance and power consumption

A continuously running model server consumes power permanently, even when idle. A modern mid-range graphics card draws an estimated 10 to 20 watts at idle. As soon as a developer is actively typing code and Tabby handles dozens of FIM requests per minute, power briefly peaks at 150 to 250 watts.

To gain insight into the operational costs of such a machine, you can work through the calculation using the guide on power consumption of local AI systems, in which the difference between peak load and continuous consumption is quantified. The quality of the syntax produced also calls for systematic checking; consult the reference framework for evaluating generated code to spot regressions in model quality in good time.

Practical examples and language-specific scenarios

To clarify how the FIM model behaves in practice, we look at how Tabby handles context-sensitive completions in different programming languages.

TypeScript: interface matching and object completion

Suppose that in a file types.ts the following data structure is defined:

export interface GebruikerProfiel {
  id: string;
  volledigeNaam: string;
  email: string;
  actief: boolean;
  rollen: string[];
}

When the developer, in another file mapper.ts begins writing a transformation function, the editor places the cursor directly after the assignment:

export function formatteerGebruiker(data: GebruikerProfiel) {
  return {
    label: /* CURSOR HIER */
  };
}

Thanks to the repository index, Tabby reads in the definition of GebruikerProfiel . The FIM model completes the missing expression straight away to:

    label: `${data.volledigeNaam} (${data.email})`,
    isAdmin: data.rollen.includes("admin")

Python: error handling and type hints

When writing asynchronous API calls in Python, Tabby completes missing exceptions based on common library conventions:

async def fetch_json(url: str) -> dict:
    async with httpx.AsyncClient() as client:
        try:
            response = await client.get(url, timeout=5.0)
            response.raise_for_status()
            return response.json()
        except httpx.HTTPStatusError as exc:
            # Tabby FIM vult aan:
            logger.error(f"Fout bij ophalen {url}: {exc.response.status_code}")
            raise

Limitations and practical pitfalls

Although Tabby offers an effective solution for local autonomy, the platform has a few clear limitations:

Maintenance, updates, and backup of repository indices

Because Tabby functions as a permanent background service, the database of repository indices needs periodic maintenance. All configurations, tokens, and generated syntax trees are stored in the directory mounted to the container (in the Compose example ./data).

When updating the model or the container image, the following standard procedure suffices:

# 1. Stop de actieve server
docker compose down

# 2. Haal de nieuwste image op
docker compose pull

# 3. Start de container opnieuw
docker compose up -d

When large changes are made to the source files on the host, the Tree-sitter index can become outdated. Through the web interface at http://localhost:8080/settings/repositories a manual re-indexing can be started at any moment to restore consistency between project files and FIM suggestions.

Conclusion

By installing Tabby through Docker you create a self-contained, privacy-friendly, and fast coding assistant on your own hardware. By tuning FIM models specifically for low latency and deploying chat models for extensive tasks, you get a robust development environment without sensitive code ever leaving your network.