Kilo Code with an uncensored model

Kilo Code takes a custom OpenAI-compatible provider in its Providers settings and in kilo.jsonc: the base URL, the key, uncensored model ids with their costs. Both the extension and the CLI, the cost per agent turn and the errors.

Steps checked November 2, 2026 · prices as of November 9, 2026

Kilo Code takes a custom OpenAI-compatible provider two ways: a dialog in the extension’s Providers settings, and a provider block in kilo.jsonc that the extension and the Kilo CLI both read. Either one, and an uncensored build answers in the chat panel and in the terminal, with tool calls for edits and commands. The same ids work in Cursor, OpenCode and, through a router, Claude Code.

Where the settings are

In the editor extension: Settings (the gear icon) → Providers tab → Custom provider, at the bottom of the list. The dialog takes the provider, its base URL, the key and the models. The same screen is where Kilo Code lists the providers it ships with.

In the Kilo CLI, and for anything the dialog does not expose: kilo.jsonc (or kilo.json). The global file is ~/.config/kilo/kilo.jsonc; a project file is ./kilo.jsonc or a file inside ./.kilo/. Both load, the project file wins on the same key, and the CLI needs a restart after an edit. Per the Custom Models docs, token limits, tool calling and variants for a custom model are set in this file, whichever client you use.

Picking a model is the same in both: the model selector in the chat prompt area or /models in the extension, /models in the CLI.

Steps

Create a key in the console first. Then take either path; they end in the same place.

In the extension

  1. Settings → Providers → Custom provider.
  2. Provider ID: uncensoredllm. Display name: UncensoredLLM.
  3. Provider API: OpenAI Compatible. This API serves /v1/chat/completions, which is the format that option speaks; the other two options are for Responses and Messages endpoints.
  4. Base URL: https://api.uncensoredllm.ai/v1. API key: the whole sk-ullm- key.
  5. Models: with a valid base URL and key, Kilo Code fetches the list from /v1/models and shows it as a searchable picker. Tick the ids you want, or add them by id and display name. Start with these three:
model ids
1glm-5.3-uncensored
2glm-5.3-flash-uncensored
3deepseek-v4.1-flash-abliterated
  1. Leave Headers empty and click Submit. The ids appear in the model selector in the chat prompt area; pick one and send a message.

In kilo.jsonc

  1. Put the key in the environment of the shell that starts Kilo:
shell
1export UNCENSOREDLLM_API_KEY="sk-ullm-live-…"
  1. Add the provider block to the global ~/.config/kilo/kilo.jsonc. The key under provider follows the Kilo docs’ own OpenAI-compatible example; the names and prices under models are from the catalog, and any id on the models page goes in the same way:
~/.config/kilo/kilo.jsonc
1{
2 "$schema": "https://app.kilo.ai/config.json",
3 "model": "openai-compatible/glm-5.3-uncensored",
4 "provider": {
5 "openai-compatible": {
6 "options": {
7 "apiKey": "{env:UNCENSOREDLLM_API_KEY}",
8 "baseURL": "https://api.uncensoredllm.ai/v1"
9 },
10 "models": {
11 "glm-5.3-uncensored": {
12 // "tool_call": true, once the model page lists tool calls
13 "name": "GLM-5.3 Uncensored",
14 "cost": { "input": 0.282, "output": 0.846, "cache_read": 0.0799 }
15 },
16 "glm-5.3-flash-uncensored": {
17 // "tool_call": true, once the model page lists tool calls
18 "name": "GLM-5.3 Flash Uncensored",
19 "cost": { "input": 0.10528, "output": 0.36848, "cache_read": 0.010528 }
20 },
21 "deepseek-v4.1-flash-abliterated": {
22 // "tool_call": true, once the model page lists tool calls
23 "name": "DeepSeek V4.1 Flash Abliterated",
24 "cost": { "input": 0.84875, "output": 1.6975, "cache_read": 0.1455 }
25 }
26 }
27 }
28 }
29}
  1. Start kilo in the project. The model line selects glm-5.3-uncensored; /models switches to another id under openai-compatible for the session, and kilo -m openai-compatible/glm-5.3-uncensored picks one for a single run.

The {env:UNCENSOREDLLM_API_KEY} reference resolves only in trusted config: the global file, a file passed through KILO_CONFIG, or an organization-managed one. In a project kilo.jsonc it is ignored with a warning, so the block belongs in the global file, or the project file carries the block without apiKey and the global file carries only the key.

What each setting does

Provider API
OpenAI Compatible
the request format the dialog uses: Chat Completions, which is what this API serves
Base URL / options.baseURL
https://api.uncensoredllm.ai/v1
where the requests go; the /v1 at the end matters. The dialog also takes a full /chat/completions URL
API key / options.apiKey
{env:UNCENSOREDLLM_API_KEY}
the whole sk-ullm- key, typed in the dialog or read from the variable in the global file
Models / models
id → { name, … }
the ids the picker offers, each exactly as the models page shows it; the config key is the id sent to the API unless an `id` field overrides it
tool_call
true
tells Kilo the model takes tool calls, which the agent needs for file edits and terminal commands; set it where the model page lists tool calls
limit
{ context, output }
the context window and the longest answer, in tokens; the model page states them. With context unset, Kilo never compacts the conversation
cost
{ input, output, cache_read }
USD per million tokens, from the catalog above, so kilo stats and the session cost line match the bill
model
openai-compatible/glm-5.3-uncensored
the default, as provider key / model id; small_model and agent.<name>.model take the same form

Picking a model

Kilo Code sends OpenAI-format requests through the OpenAI Compatible adapter, and every build on the models page answers in that format. An agent turn carries the conversation, the files Kilo read and every tool result so far, so input tokens are most of the bill and a build with a low input price costs the least per turn. The last column says whether the build takes tool calls; that is the tool_call flag above, and the agent loop needs it for edits and shell commands.

ModelOne agent turnTool calls
GLM-5.3 Uncensored$0.01model page
GLM-5.3 Flash Uncensored$0.0047model page
DeepSeek V4.1 Flash Abliterated$0.04model page
DeepSeek V4 Pro Uncensored$0.04model page
GLM-5.3 Abliterated$0.09model page
GLM-5.3 Flash Code Uncensored$0.25model page

40,000 input and 1,200 output tokens at the catalog prices on 2026-11-09. Tool calls as the catalog publishes them; where it does not, the model page says.

Uncensored models and their prices per million tokens
GLM-5.3 Uncensoredglm-5.3-uncensoredUncensored$0.282$0.846
GLM-5.3 Flash Uncensoredglm-5.3-flash-uncensoredUncensored$0.1053$0.3685
DeepSeek V4.1 Flash Abliterateddeepseek-v4.1-flash-abliteratedAbliterated$0.8488$1.6975
DeepSeek V4 Pro Uncensoreddeepseek-v4-pro-uncensoredUncensored$0.97$1.94
GLM-5.3 Abliteratedglm-5.3-abliteratedAbliterated$2.1825$4.365
GLM-5.3 Flash Code Uncensoredglm-5.3-flash-code-uncensoredUncensored$6.00$6.00

Prices per million tokens, read from the live catalog on 2026-11-09.

Kilo keeps separate roles: the main model, a Small Model for session titles and commit messages, a Subagent Model for the task tool. All three are set under Settings → Models or as small_model and subagent_model in kilo.jsonc. A fast build as the small model and a strong one as the main model keeps the housekeeping calls off the expensive id. For coding specifically, the uncensored coding AI guide compares the code builds and costs a full coding day on each.

Check it

List the models your key can call; this is the same request the dialog’s model picker makes, so every id it offered should be in the answer:

shell
1curl https://api.uncensoredllm.ai/v1/models -H "Authorization: Bearer sk-ullm-live-…"

Then send one request the way Kilo Code does. -i prints the headers: x-uplink-request-id names the request, and on a non-streamed answer x-uplink-charge is what it cost in USD.

shell
1curl -i https://api.uncensoredllm.ai/v1/chat/completions \
2 -H "Authorization: Bearer sk-ullm-live-…" \
3 -H "Content-Type: application/json" \
4 -d '{"model": "glm-5.3-uncensored", "messages": [{"role": "user", "content": "Reply with the single word ok."}]}'

On the CLI side, confirm the block loaded:

shell
1kilo models openai-compatible

It lists the ids under models; kilo config check reports anything wrong in the file. Then send a message in Kilo with one of your ids selected. The request shows on the console’s usage page with its tokens and its charge.

Errors and fixes

  • 401 invalid_api_key, or “Invalid API Key” in the dialog: the key is wrong or revoked, or UNCENSOREDLLM_API_KEY was not set in the shell that started Kilo, so apiKey came through empty. Copy it again from the console, or export it and start Kilo again.
  • 404 model_not_found, or “Model Not Found” in the dialog: the id is not on the models page. Check the spelling against the page; in the file, the key under models is what is sent, not name.
  • 402 insufficient_balance: the balance does not cover the request. Top up in the console. 402 monthly_limit_reached means the key hit the monthly spend limit you set on it.
  • 403 scope_denied: the key is limited to certain models and this is not one of them.
  • 429 rate_limited: the key hit its rate limit. The response carries retry-after.
  • The dialog’s model list stays empty: the fetch runs only once the base URL and the key are both valid. Fix either, click Fetch models, or add the ids by hand.
  • A warning that {env:UNCENSOREDLLM_API_KEY} was ignored: the reference sits in a project kilo.jsonc. Move the block to ~/.config/kilo/kilo.jsonc, or pass the file through KILO_CONFIG.
  • kilo models does not list the provider: the key in model does not match provider key / model key in the block, or the CLI was not restarted after the edit. kilo debug config prints what loaded.
  • The agent explains an edit but never makes it: tool_call is unset on that model, so Kilo sends no tools. Add "tool_call": true to the entry once the model page lists tool calls.
  • The conversation grows until requests fail: limit.context is unset, which Kilo reads as zero and stops compacting. Set limit from the model page.
  • Connection errors with a full URL in Base URL: the path has to end in /chat/completions. https://api.uncensoredllm.ai/v1 alone is the simpler form.

Questions

Yes. The Providers settings end in a Custom provider dialog whose Provider API field has an OpenAI Compatible option for Chat Completions endpoints, and kilo.jsonc takes the same provider as a block with a baseURL and an apiKey. This API is such an endpoint, so either path above is the whole setup.

A key from this console, in full, with the sk-ullm- prefix. In the dialog it goes in the API key field; in the file it is read from an environment variable through {env:…}, which Kilo resolves only in the global config or a file passed through KILO_CONFIG, never in a project file.

Yes. Providers sit side by side in the model selector and in /models, so the custom one is a second entry, not a replacement. The whitelist key on a provider block narrows what it offers, and the per-agent model keys pin a subagent to a cheaper id while the main agent stays on a strong one.

They work on the builds that take tool calls, and Kilo only sends tools when tool_call is true on the model. The table above says which builds the catalog confirms; for the rest, the model page says, and the flag goes into the entry once it does. See the models page.

Every model above is on the uncensored model list with its live price per million tokens. Per-token pricing sets the whole catalog side by side, and the family directory groups the builds by base model.

Get a keyPrepaid from $10, no subscription.

New models and price changes, once a month.

New uncensored builds with their prices, price moves, and what the daily model check found.

Join on Telegram