Build GitHub Copilot
KINDAreplaces $10/mosaves $120/yrback to the verdict
A Tabby server on your own machine or a GPU box, serving fill-in-the-middle completions to VS Code and JetBrains through official plugins, indexing your repositories for context, with latency measured rather than assumed and an acceptance rate you can compare against the subscription you left.
Before step 1
Everything below is assumed from the first step. Tick each one when you actually have it, not when you plan to.
- have readyfree if you already have suitable hardware; a suitable GPU otherwise starts in the high hundreds of USD, which is the figure the comparison in Phase 5 has to justify
Why This is the prerequisite that decides whether the project is viable. Below it, Tabby falls back to CPU and completions arrive too late to be useful.
Get it Check an existing machine first with nvidia-smi. An RTX 20-series or newer qualifies. Apple silicon uses the Metal path instead and works well for smaller models.
Verify
nvidia-smi reports compute capability 7.0 or higher, or you are on Apple silicon - installfree
Why The container image is the fastest route to a running server, but it needs the GPU visible inside the container.
Get it Install Docker, then the NVIDIA container toolkit on Linux. On Apple silicon, use the native build rather than a container. open ↗
Verify
docker run --gpus all reports the GPU, or the native binary starts and reports the Metal device - installfree
Why The plugin is what turns a completion endpoint into ghost text. Writing your own is a project of its own.
Get it Install from your editor's plugin marketplace and point it at your server address.
Verify
The plugin's status indicator shows connected - have readyfree, but it must be done first
Why Phase 5 compares against them, and once you have cancelled the subscription you cannot go back and measure.
Get it Spend a morning with the paid tool, logging how often you accept a completion and roughly how fast they arrive. Record it before you start.
Verify
A written baseline exists with an acceptance rate and a latency impression - have readyfree
Why Models and indexes are large, and a model download that fails halfway through a full disk wastes an evening.
Get it Check free space before pulling a model. Larger models need considerably more.
Verify
df reports at least twenty gigabytes free
Data model
Create these before the first phase that stores anything. Changing a table later is the expensive kind of change.
- This is a deployment, so the model that matters is your operational state, not a schema. - server · the Tabby instance, its bound address, its model and its device - index · which repositories are indexed, when, and how large the index is - completions(t, latency_ms, accepted, model, language, prefix_len) · your own log, because acceptance rate is the only honest quality measure - baseline · the latency and acceptance figures from the subscription you are replacing, recorded before you cancel it
Environment variables
These go in a .env file the app reads at startup. The pack's .env.example is this table as a file · copy it, never commit the filled-in version.
| Variable | Needed | Example | Where the value comes from |
|---|---|---|---|
TABBY_HOST | required | 127.0.0.1 | Bind address. Keep it on loopback unless you have deliberately added authentication. |
TABBY_PORT | required | 8080 | The port the completion server listens on. |
TABBY_MODEL | required | StarCoder2-3B | The completion model. Chosen by the measurement in Phase 2, not by parameter count. |
TABBY_DEVICE | required | cuda | cuda, metal or cpu. The cpu value is a diagnostic, not a working configuration. |
TABBY_TOKENsecret | optional | replace-with-a-random-token | Product phase only. Required the moment the server listens on anything but loopback. |
COMPLETION_LOG_PATH | required | ~/.local/share/tabby/completions.sqlite | Your own latency and acceptance log. This is what makes Phase 5 possible. |
The build, in order
Hardware truth and a first completion
A completion appears in your editor, and you know whether your hardware can serve them fast enough to be useful.
Check the GPU model and its compute capability, or confirm Apple silicon. Write the answer down before installing anything, because it constrains every later choice.
terminalnvidia-smi --query-gpu=name,compute_cap --format=csv
Start with the smallest completion model that fits comfortably. A model that barely fits will swap and be slower than a smaller one that does not.
terminaldocker run -it --gpus all -p 8080:8080 -v $HOME/.tabby:/data tabbyml/tabby serve --model StarCoder2-3B --device cuda
Install the Tabby VS Code plugin, point it at your server, and record the time from keystroke to ghost text over twenty completions.
Files
notes/latency.md
done when · tick each as it passeswatch out- Tabby's CUDA path defaults to int8 and requires compute capability 7.0 or higher, meaning an RTX 20-series card or newer. On anything older it falls back to CPU, where completions arrive after you have already typed the line, which is the same as having none. Establish this before you spend a weekend on it.
Choosing a model by measurement
You picked the model on evidence rather than on parameter count.
Record latency, language and whether you accepted it. The plugin can be configured to log, or you can wrap the server endpoint.
Files
scripts/log_completions.pyA morning each, on code you were writing anyway. Synthetic prompts will mislead you because they lack the surrounding file.
Model, latency, acceptance and the reason. In three months you will not remember why, and you will be tempted to re-test.
Files
docs/model-choice.md
done when · tick each as it passeswatch out- A larger model produces better completions and worse latency, and past roughly half a second the completion arrives after you have typed the line yourself, so its quality stops mattering. Acceptance rate captures this trade-off and a benchmark score does not.
Repository context
Completions know about the rest of your codebase, not just the open file.
Add each repository to the server configuration with an exclusion list. Start from .gitignore and add credential paths.
Files
~/.tabby/config.tomlA periodic job. An index that reflects last month's code is worse than useless because it confidently suggests names you have since renamed.
Define a distinctively named function in one file and start calling it in another. If the completion knows the signature, indexing is doing something.
done when · tick each as it passeswatch out- Indexing node_modules or a build directory buries genuine context under generated code and makes both indexing and retrieval slower. Exclude aggressively; the index should cover code you wrote.
Availability and the offline case
The server is there when you start work, and the editor is usable when it is not.
A systemd unit, a launchd agent or a restart policy on the container. Confirm by rebooting rather than by reading the configuration.
terminalsystemctl --user enable --now tabby
Stop the server and work for ten minutes. Anything worse than a missing suggestion is a bug worth fixing before you rely on this.
Inspect the bound address. If it is not loopback, add a token and verify an unauthenticated request is refused.
terminalss -tlnp | grep 8080
done when · tick each as it passeswatch out- A completion server bound to all interfaces with no authentication is a free GPU for anyone on the network. Bind to localhost unless you have deliberately added a token, and check what it is actually listening on rather than what you intended.
Was it worth it
You can answer the question with numbers instead of a feeling.
Accepted completions over offered completions, by language. Aggregate hides that it may be excellent for one language and useless for another.
Files
scripts/report.pyHardware amortised, electricity, and your setup time at whatever you value it. Compare with the annual subscription.
Files
docs/comparison.mdIncluding the case where you go back. A documented negative result is worth more than a quiet retreat.
Files
docs/comparison.md
done when · tick each as it passeswatch out- Sunk cost makes this comparison hard to do honestly after a weekend of setup. Record the baseline numbers from the paid tool before you cancel it, because afterwards you will only have a memory of how good it felt.
Serving a teamproduct builder
Colleagues can use it without you handing out a bare port.
A reverse proxy for certificates and the server's own token support for identity. Test revocation, not just issuance.
Files
CaddyfileSimulate concurrent completion requests and find where latency crosses the half second threshold. That number is your user limit.
Files
scripts/loadtest.pyWhat request content is stored, for how long, and who can read it. One paragraph, agreed before rollout.
Files
docs/retention.md
done when · tick each as it passeswatch out- Completion requests contain the code around the cursor, which means the server sees your colleagues' work in progress. Decide and publish the retention policy before anyone connects, not after someone asks.
That is the whole plan for GitHub Copilot. What it deliberately does not cover is below · check the gaps before you call it a replacement.
- Copilot's latency at scale, which is a fleet of accelerators.
- Native GitHub integration across pull requests and code review.
- Model routing by task, done invisibly by the subscription.
- Fine-tuning on your own codebase.
- native GitHub/IDE integration
- fast completions
- model routing
- code review/security features
- managed billing
- team controls
- A separate chat and agent setup, which wants a different model entirely
- Per-language acceptance tracking to find where it genuinely helps
- Sharing one server across a small team, once the saturation point is known
Need the files? The project pack on the verdict page hands your agent the whole brief · more dev tools.