AhuAIComplete
Inline AI code completion (ghost text) for Sublime Text, with Ollama / OpenAI / OpenAI FIM backends.
Details
Installs
- Total 5
- Win 3
- Mac 2
- Linux 0
| Sep 19 | Sep 18 | Sep 17 | Sep 16 | Sep 15 | Sep 14 | Sep 13 | Sep 12 | Sep 11 | Sep 10 | Sep 9 | Sep 8 | Sep 7 | Sep 6 | Sep 5 | Sep 4 | Sep 3 | Sep 2 | Sep 1 | Aug 31 | Aug 30 | Aug 29 | Aug 28 | Aug 27 | Aug 26 | Aug 25 | Aug 24 | Aug 23 | Aug 22 | Aug 21 | Aug 20 | Aug 19 | Aug 18 | Aug 17 | Aug 16 | Aug 15 | Aug 14 | Aug 13 | Aug 12 | Aug 11 | Aug 10 | Aug 9 | Aug 8 | Aug 7 | Aug 6 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Windows | 0 | 2 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| Mac | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 |
| Linux | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
Readme
- Source
- raw.githubusercontent.com
AhuAIComplete
Inline AI code completion for Sublime Text 4, with the interaction model of
Codeium / Copilot: grey ghost text appears at the cursor as you type, Tab
accepts it, Esc dismisses it.
No vendor lock-in — a local Ollama instance, DeepSeek, OpenAI, or an internal vLLM / one-api deployment all work as long as the API is compatible. Zero third-party dependencies: Sublime's bundled Python is enough.
You type up to the opening bracket and pause:
typed: return fib(n-1) + fib(
shown: n-2)
The n-2) part appears at the cursor as grey ghost text; Tab inserts it.
Installation
Package Control — run Package Control: Install Package and pick AhuAIComplete.
From source, for hacking on the code. Clone the repository straight into the Packages directory; Sublime loads a package in place, so there is nothing to build and no installer to run:
cd ~/Library/Application\ Support/Sublime\ Text/Packages # macOS
git clone https://github.com/ahu/AIComplete AhuAIComplete
Sublime reloads the package's top-level module when it is saved, but not the
submodules under lib/, so a reloader is worth having while working on those —
AutomaticPackageReloader
does exactly that.
Once installed, run AhuAIComplete: Test Connection from the command palette. It sends one real request and prints the result in the output panel, so a misconfiguration is obvious at a glance.
Configuration
Preferences -> Package Settings -> AhuAIComplete -> Settings.
The default is a local Ollama:
ollama pull qwen2.5-coder:1.5b # lightweight, fine for everyday use
ollama pull qwen2.5-coder:7b # noticeably better, if your machine allows
To use a hosted service, change provider and fill in the matching block:
| provider | API | Best for |
|---|---|---|
ollama |
/api/generate + suffix |
Local models: private and free |
openai_fim |
/completions + suffix |
Best for completion: real fill-in-the-middle |
openai |
/chat/completions |
General fallback: works with any chat model |
For example, the DeepSeek fill-in-the-middle endpoint:
{
"provider": "openai_fim",
"providers": {
"openai_fim": {
"base_url": "https://api.deepseek.com/beta",
"api_key": "sk-...",
"model": "deepseek-chat"
}
}
}
To keep the key out of the settings file, set the AICOMPLETE_API_KEY or
OPENAI_API_KEY environment variable. Note that it must be exported in the
shell that launches Sublime; starting the editor from the Dock will not pick
it up.
Key bindings
| Action | macOS | Windows / Linux |
|---|---|---|
| Accept the whole suggestion | Tab |
Tab |
| Accept only the next word | Ctrl+Option+-> |
Ctrl+Alt+-> |
| Accept only the next line | Ctrl+Option+Down |
Ctrl+Alt+Down |
| Dismiss | Esc |
Esc |
| Request a completion manually | Cmd+Shift+Enter |
Alt+\ |
| Cycle candidates | Cmd+Shift+[ / ] |
Alt+[ / ] |
Each platform's bindings live in a single file, so
Preferences -> Package Settings -> AhuAIComplete -> Key Bindings shows every
shortcut at once.
macOS note:
Optionplus a key produces a composed character (Option+\types«), so every shortcut that originally usedOptionbecameCmd+Shift+...on macOS, which always matches. When a key does not work,AhuAIComplete: Request Completionin the command palette does the same thing independently of any key binding.
Tab is only taken over while a suggestion is visible and the autocomplete
popup is not showing, so ordinary indentation and snippet navigation are
unaffected.
For several candidates, set num_suggestions to 2 or 3 (the default is 3).
openai and openai_fim use the API's n parameter to get them in one
request; ollama does not support n, so it fires several parallel
requests with different seeds instead. Running 3 with a local 1.5b model is
cheap. When candidates are available, press Cmd+Shift+[ / ]
(Windows / Linux: Alt+[ / ]) to cycle; a badge shows the current index.
How this differs from other completion packages
There is only one goal here — fast inline ghost text — so there is no chat panel, no “edit selection” command, and no setup wizard. Specifics:
- Real fill-in-the-middle instead of a chat prompt. The
openai_fimandollamaproviders send the code after the cursor as asuffix, so the model fills the gap rather than continuing a conversation. This is the single biggest factor in completion quality. - Multiple candidates with cycling. Other packages return one suggestion. Here you can request several and step through them, which matters with small local models that are otherwise deterministic.
- Standard library only, no installer and no build step. There is no companion CLI, no GUI installer, and no third-party dependency to vendor; it runs on the Python that ships with Sublime Text 4.
- Per-view control. Completion can be toggled globally, for one file, or via the status bar indicator.
A few design notes
Network requests stay off Sublime's async thread. Sublime's async worker
is a single-threaded queue; putting HTTP on it would block every plugin's
asynchronous events. Requests run on a separate daemon thread and only hop
back to the main thread via set_timeout.
Suggestions are reused while you type. If the characters you keep typing match the beginning of the suggestion, it is trimmed in place and displayed again instead of triggering a new request — fewer tokens, no flicker. The 64 characters before the cursor are checksummed first, so edits elsewhere cannot shift the position unnoticed.
Stale responses are always discarded. Every view carries an incrementing
token; a response is dropped when the token does not match, when
change_count has moved on, or when the cursor is no longer in place.
Model output is cleaned before display. Models ramble, so
lib/postprocess.py strips markdown fences, removes a repeated copy of the
prefix, drops closing brackets that duplicate the suffix, truncates overly long
output, and removes special tokens. This is the key step for completion
quality and the focus of the test suite.
Triggering only happens at the end of a line. By default a request is only
sent when nothing substantial follows the cursor (trailing whitespace, or
closing characters such as ) ] } ; ,). Turn off trigger_only_at_line_end
to trigger everywhere.
Tests
python3 tests/test_logic.py # 41 pure logic tests, no Sublime needed
python3 tests/test_live.py # hits a real backend, three completion cases
python3 tests/test_live.py ollama qwen2.5-coder:7b # pick provider / model
Code layout
ai_complete.py commands and event listeners (Sublime loads only the
.py files at the package root)
lib/settings.py settings access, with environment-variable fallback
lib/context.py prefix/suffix extraction, language detection,
cross-file context, trigger conditions
lib/client.py HTTP for the three providers, standard library only
lib/postprocess.py model-output cleaning pipeline
lib/ghost.py phantom rendering of the grey suggestion
lib/engine.py debounce, concurrency, stale-response dropping,
LRU cache, candidate management
examples/demo.py scratch file for trying completions by hand
tests/ pure-logic tests (no Sublime needed) and live tests
Troubleshooting
Enable "debug": true first; the log goes to the Sublime console
(Ctrl+`).
- Nothing happens at all — run the connection test; make sure the cursor
is at the end of a line; look for
AI ...in the status bar. - The status bar stays on
AI err— the console holds the full error. Usuallybase_url, the model name, or the key is wrong. - Suggestions contain duplicated brackets — a backend quality issue; try a
coder-series model, or add a targeted trimming rule to
postprocess.py. - SSL errors with a self-signed certificate — set
verify_ssltofalsetemporarily. - Too noisy or too expensive — raise
debounce_ms, or request completions manually only (Cmd+Shift+Enteron macOS,Alt+\on Windows / Linux; withenabledset tofalse, manual requests still work).