Skip to content
| Marketplace
Sign in
Visual Studio Code>AI>K2 for VS CodeNew to Visual Studio Code? Get it now.
K2 for VS Code

K2 for VS Code

Der Adrian

|
3 installs
| (1) | Free
An unofficial coding agent for IFM's K2 models and local OpenAI-compatible servers. Not affiliated with IFM.
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

K2 for VS Code

Use IFM's K2 models in VS Code, through api.ifm.ai, or models on your own OpenAI-compatible server.

K2 for VS Code is an unofficial extension. It is not made by or affiliated with IFM.

Written by K2 and Claude, with direction from the repository owner.

Getting an API key

IFM's K2 models need an API key from IFM.

  1. Go to platform.ifm.ai and sign up.
  2. Create an API key there.
  3. Open the K2 chat window in VS Code. When it asks for your key, click Set API key and paste the key into the text field that appears.

Models on your own server need no IFM key; see Local models.

The K2 panel

The panel sits in the Secondary Side Bar next to other AI assistants. Set k2.useActivityBar to move it to the Activity Bar.

  • Sessions. The top bar shows the current session's title. After the first reply, the session's model gives it a short title for what you asked; until then it shows the first line of your message. Double-click the title to rename the session: Enter or clicking elsewhere keeps the name, Escape cancels, and your name is never replaced. Session History lists every session, newest first; the bin next to one deletes it, asking first when it has a conversation. New Session starts a fresh one. A session you leave without writing in it is removed, so the list does not fill with empty sessions. Sessions are kept per workspace folder, as one file each in ~/.k2/sessions.

  • Replies as a timeline. Each reply lists what happened, in order:

    • how long K2 thought (click it to read the reasoning);
    • each command it wanted to run, with its state: the command under IN and its output under OUT, where long output folds behind Show more;
    • the answer itself.
  • Code. Code blocks are coloured with your editor theme's syntax colours when the reply names the language. Every language highlight.js (BSD-3-Clause) knows is included: the common ones load with the panel, the others the first time a reply uses them. Hover a block and click the copy button to copy just the code.

  • File changes. When K2 writes or edits a file, the reply shows the change as a diff, with the lines added and removed, before you apply it. Open diff opens it in VS Code's diff editor, also after the change.

  • Images and pages. When K2 writes ![caption](https://github.com/adrianderstroff/k2-code/raw/HEAD/path), an image from inside the workspace is shown in the chat. Images from the web are never loaded; they appear as links. A link to an .html page in the workspace gets a card with Open preview, which opens the page in VS Code's Simple Browser, and Open in browser. Pages are served only to your own machine and never run inside the chat.

  • Model. The button below the text box shows the current model. Click it to pick another; the session keeps its model and new sessions use the last one chosen.

  • Thinking. The bulb next to + opens a menu that switches thinking on or off and sets its effort (low, medium, high) for the session. What the session's model cannot do is greyed out, with the reason:

    • IFM's models take an effort but cannot switch thinking off.
    • A llama.cpp server says through its chat template what the model can do.
    • For other servers, set thinking and reasoningEffort for the model in k2.providers.

    The effort slider's first stop, Default, leaves the effort to the model; Low, Medium and High set it. The Programs switch below them turns off the tools K2 uses to start programs, type into them and watch them, for this chat, which keeps every request about 750 tokens shorter for a small local model, and about 1,300 where watches are offered.

  • Files. Click + to attach files, or drag them onto the panel. Hold Shift while dropping if VS Code opens the file instead. Text files are sent to K2 with your message (the first 100 KB). For images and other files K2 gets the path. Files from outside the workspace are copied into .k2/attachments/.

  • Sending. Enter sends and Shift+Enter adds a new line; k2.sendWithShiftEnter swaps them. While K2 answers, the send button becomes Stop; Ctrl+C in the text box does the same when no text is selected.

  • Messages while K2 works. A message you send meanwhile waits at the bottom of the conversation. Steer hands it to K2 at its next step, and K2 carries on below it; otherwise it is sent when K2 is done, and its x takes it back. After a stop or an error, waiting messages go back into the text box.

  • Interruptions. If you stop a reply or the model's server goes away, everything that arrived is kept and unfinished reasoning is marked interrupted.

Instructions

Write instructions for K2 in Markdown files, the way Codex reads AGENTS.md and Gemini CLI reads GEMINI.md:

  • For every project: ~/.k2/AGENTS.md or ~/.k2/K2.md. Set K2_HOME to keep the folder somewhere else.
  • For a project: AGENTS.md and K2.md in the workspace root. Commit them with the project.
  • For part of a project: the same files in a subfolder. They add to the ones above while K2 works in that folder.

With every message K2 reads the files from the workspace root down to the folder it is working in, which moves when a command changes directory. In each folder AGENTS.md comes before K2.md, and deeper files come after the ones above them, so they win where they disagree. Other coding agents read AGENTS.md too; keep what only K2 needs in K2.md. Files in folders K2 is not working in are only named, so K2 reads one when it starts working there.

  • When the files in use change, the reply notes which ones they are.
  • Edits apply from the next message.
  • k2.instructionFiles sets the file names; an empty list turns instruction files off.
  • Keep them short for small local models: with an 8K context, long instructions leave little room for the conversation.

Local models

Models running on your own machine can be used just like IFM's, and they appear in the same model picker. Start the server yourself, then either:

  • choose Add local model... at the bottom of the model picker (or run k2: Add local model), pick the kind of server and confirm its address; or
  • add it to k2.providers in your settings:
"k2.providers": [
  { "id": "llamacpp", "name": "llama.cpp", "baseUrl": "http://127.0.0.1:8080/v1" },
  { "id": "ollama", "name": "Ollama", "baseUrl": "http://127.0.0.1:11434/v1" }
]

Any server with an OpenAI-compatible API works, for example Ollama, LM Studio, llama.cpp's llama-server, vLLM or SGLang.

  • Models. They come from the server's own model list, so a model you add to the server later shows up without changing settings.
  • Keys. Local servers need no API key. If yours does, set apiKeyEnv to the name of the environment variable that holds it.
  • Tools. If a server refuses tool calls, K2 answers without them and marks the model chat only.
  • Reasoning. Reasoning in a <think> block is shown as the thought, like IFM's models.
  • Context. When a conversation nears the model's context (llama.cpp's -c), K2 compacts it: the model summarises the conversation before your message, and later requests carry that summary instead. The reply shows Compacting the conversation... and then how many messages were compacted; open it to read the summary. If compacting fails, or a request still does not fit, K2 shortens long command output from earlier messages and leaves out the oldest ones, and says so. Whether the summary is used is decided for each request by the model's context, so after switching to a model with room for the whole conversation, every message is sent again. The chat in the panel keeps everything, and page reads come in smaller parts for a small context. llama.cpp servers report their context size. For other servers, and for IFM's models, K2 takes 128,000 tokens unless the model's contextWindow says otherwise, and a smaller size from an error that names one. A larger -c keeps more of the conversation word for word.
  • Per-model details go under models:
    • name;
    • tools (true or false);
    • reasoning (auto, field, think-tags or none);
    • request: extra fields for every request, for example {"reasoning_effort": "high"};
    • thinking and reasoningEffort (true or false): whether the Thinking menu can switch the model's thinking off (chat_template_kwargs.enable_thinking) and set its effort (reasoning_effort). Leave them out for a llama.cpp server, which reports this itself.
    • contextWindow: the model's context size in tokens, as described under Context. A server that reports a smaller one wins.

To make a local model the default, set k2.model to provider:model, for example llamacpp:K2-Horizon-0.9B.

IFM's own models take the same details under an entry with the id ifm and nothing but models, for example to give K2-Horizon more room than the 128,000 tokens K2 takes by default. A larger context keeps more of a long conversation word for word, and every request then carries more of IFM's daily tokens:

"k2.providers": [
  { "id": "ifm", "models": [{ "id": "IFM/K2-Horizon-375B-A23B", "contextWindow": 200000 }] }
]

Example: K2-Horizon-0.9B with llama.cpp

K2-Horizon-0.9B runs on a laptop. On an RTX 3050 Laptop GPU (4 GB) it generated about 70 tokens per second, and about 16 on the laptop's CPU alone. It is fine for trying things out, but weak at multi-step tool use.

  1. Download the model. Get K2-Horizon-1B-BF16.gguf from IFM/K2-Horizon-0.9B-GGUF.

  2. Build a server that knows the model. Upstream llama.cpp and Ollama cannot load the K2 Horizon architecture yet, so build llama-server from IFM's fork:

    git clone --depth 1 --branch model/K2Horizon https://github.com/MBZUAI-IFM/llama.cpp.git
    cd llama.cpp
    

    On Windows, build with GCC rather than Visual Studio, whose regex library cannot read the model's tokenizer pattern. You need git and CMake. Install a current GCC and the Vulkan SDK, which runs the model on your GPU through its normal graphics driver:

    winget install BrechtSanders.WinLibs.POSIX.UCRT
    winget install KhronosGroup.VulkanSDK
    

    Open a new terminal and check that gcc --version reports GCC 14 or newer. If an older MinGW comes first on your PATH (Strawberry Perl ships one), put WinLibs' mingw64\bin folder in front of it for this terminal. Then build:

    cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DGGML_VULKAN=ON -DGGML_OPENMP=OFF -DLLAMA_CURL=OFF -DBUILD_SHARED_LIBS=OFF -DCMAKE_EXE_LINKER_FLAGS=-static -DCMAKE_C_FLAGS=-D_WIN32_WINNT=0x0A00 -DCMAKE_CXX_FLAGS=-D_WIN32_WINNT=0x0A00
    cmake --build build --target llama-server
    
    • _WIN32_WINNT=0x0A00 targets Windows 10, which the bundled HTTP library needs. MinGW defaults to Windows 7.
    • GGML_OPENMP=OFF and -static make build\bin\llama-server.exe run without extra DLLs.

    On Linux and macOS, follow llama.cpp's own build instructions for your GPU.

  3. Start the server:

    llama-server -m K2-Horizon-1B-BF16.gguf --host 127.0.0.1 --port 8080 --jinja -c 32768 -np 1 -ngl 99 --alias K2-Horizon-0.9B
    
    • -ngl 99 puts every layer on the GPU; leave it out to run on the CPU.
    • -c 32768 -np 1 gives one conversation 32,768 tokens of context; the model can take up to 131,072. Without -np 1, several parallel slots share the context. On a 4 GB GPU this setup uses about 3.5 GB.
    • If the computer has more than one GPU, llama-server --list-devices lists them and --device picks one, for example --device Vulkan1.
    • --jinja uses the model's own chat template, so reasoning and tool calls come back parsed.
    • --alias is the name K2 shows.
  4. Add it in K2. Open the model picker and choose Add local model..., then llama.cpp server. Keep http://127.0.0.1:8080/v1. K2 finds K2-Horizon-0.9B and switches the session to it.

Chat participant

Type @k2 in the Chat view to talk to K2 there. It works like the panel, with the same tools and the model from k2.model. A call that needs approval asks in a notification: Allow, Allow all for the rest of the reply, or Skip. A chat keeps its conversation while VS Code runs, and /clear starts it over.

The k2 command

The extension brings k2, K2 in the terminal: the same agent and the same sessions as the panel, in the folder you start it in. It runs with VS Code's own runtime, so it needs no Node.js.

  • In VS Code's terminal, type k2. A terminal that was already open when the extension started does not have it yet; open a new one.
  • In other terminals, add ~/.k2/bin (%USERPROFILE%\.k2\bin on Windows) to your PATH once. The extension keeps the command there up to date.
  • k2 --help lists the options, such as -p to answer one prompt and exit, and /help at the prompt lists the commands.

Where the API key is kept

K2 keeps the key in ~/.k2/auth.json, as {"K2_API_KEY": "..."}; set K2_HOME to keep the folder somewhere else. Without a key, the panel asks for it and saves it there.

Keys for other services stay where they were: a local server's apiKeyEnv names an environment variable, and a web search key comes from its environment variable or from the same file.

This is how other AI tools keep their credentials, for example ~/.claude/.credentials.json and ~/.codex/auth.json. A key saved by an earlier version of this extension in VS Code's secret storage is moved to the file once. k2: Forget API key removes it.

Tools

  • run_command: K2 can run commands on this machine.

    • On Windows they run in PowerShell 7 (pwsh) when it is installed and in Windows PowerShell 5.1 otherwise. PowerShell 7 accepts && and ||, which models often write, and K2 gets a table of Unix commands and their PowerShell equivalents.
    • On macOS and Linux they run in the shell in $SHELL when it is a POSIX shell such as bash or zsh, and in /bin/sh otherwise.

    The tool tells K2 which shell it is and says to use the file tools for reading, searching and changing files. Every command waits for your approval in the panel (Run, Run all for the rest of the reply, or Skip). The working directory carries over from one command to the next, and files K2 makes for you go into .k2/scratch/. When K2 asks a third time in a row for a command whose last two runs gave the same result, it is not run and K2 is told why; asking once more ends the reply.

  • start_process, send_input, read_output and stop_process: for a program that keeps running or asks for input, such as a game K2 plays, a REPL or a server whose output it follows. K2 starts the program, types lines into it and reads what it prints in reply. Starting a program and sending input wait for your approval like commands; reading its output and stopping it do not. At most five programs run at once. They are stopped when the reply ends, unless K2 starts one with keep_running, such as a dev server or a long build; that one runs until you stop it, you switch to another session, or VS Code closes.

  • watch and unwatch: instead of checking again and again, K2 can ask to be woken up later: when a program it keeps running ends, prints lines matching a pattern or prints nothing for a while; when a file or folder changes, or a log gets matching lines; when a timer goes off; or when a check command gives another result. K2 Code checks the watches itself, and K2 gets a request only when something happened. That starts a reply of its own, or joins the reply K2 is working on. The conversation shows it folded as Woken up by watch N, not as a message from you.

    • Watches do not ask for approval, except a check command, which runs again and again, and a path outside the workspace.
    • Limits keep a chat from using up your quota on its own: at most 10 watches per chat and 20 wake-ups per hour. After 5 wake-ups in a row without a message from you, the chat's watches pause until you write again. A wake-up carries at most 4,000 characters. The k2.watches.* settings change these limits.
    • Switching to another session drops the watches. @k2 in the Chat view has none, since nothing there can start a reply by itself, and neither do models whose context is known to be below 16,000 tokens.
  • Running bar: while a program runs, a bar above the text box lists it with its command, how long it has run and a stop button. Click a line to see its latest output. Watches are listed too; click one to see how often it is checked and why K2 set it, or stop it to remove it. Programs a command left running, such as a server started with Start-Process on Windows or with & on macOS and Linux, are listed as well, marked background; they stay until they exit or you stop them, and are stopped when VS Code closes.

  • read_file: reads a file with line numbers, all of it or a range of lines, in parts that fit the model's context.

  • find_files and search_files: find files and folders by name, and text inside files, in the workspace folder or another folder. Inside the workspace they run without asking.

  • write_file and edit_file: create or replace a file, or replace an exact piece of one. Line endings and a byte order mark are kept. The change is shown as a diff for you to Apply or Skip. After a change, K2 is told about errors your language extensions report in the file that were not there before, as shown in the Problems view. Nothing is built for this.

Relative paths in the file tools start from the workspace folder, even after a command changed the shell's folder.

  • web_search: searches the web and gives K2 titles, links and short snippets, so it can look up what it does not know, such as how to install a tool. It uses DuckDuckGo and needs no setup. That is not an official API, so DuckDuckGo can refuse automated searches from your machine for a few minutes; K2 is then told so, and that it is not about the query, and does not search again in that reply. For a dependable service set k2.webSearch.provider to brave or tavily, with BRAVE_SEARCH_API_KEY or TAVILY_API_KEY in the environment or in ~/.k2/auth.json, or to searxng with k2.webSearch.searxngUrl. off turns search off.
  • fetch_url: reads a web page as plain text, without scripts, menus or styling, 10,000 characters at a time.

Commands, file changes, searches and page reads wait for your approval (Run all, Apply all or Allow all covers the rest of the reply). Reading a file inside the workspace does not; reading one outside it does.

Settings (all under k2.*)

Setting Default What it does
k2.model IFM/K2-Horizon-375B-A23B The model new sessions start with; provider:model for a local model.
k2.sendWithShiftEnter false Send with Shift+Enter and add a new line with Enter, instead of the other way round.
k2.providers [] Local or other OpenAI-compatible servers whose models appear in the model picker.
k2.showThoughts false Show the model's reasoning inline in @k2 chat responses.
k2.enableTools true Whether K2 may ask to run commands.
k2.commandTimeoutSeconds 600 How many seconds a command may run before it is stopped (5 to 86400). Commands get no input, so a program that asks for some ends at once.
k2.webSearch.provider duckduckgo The service behind web_search: duckduckgo, brave, tavily, searxng or off.
k2.webSearch.searxngUrl Address of your SearXNG instance, for searxng.
k2.instructionFiles ["AGENTS.md", "K2.md"] Instruction file names, read from ~/.k2 and from the workspace root down to K2's working folder. An empty list turns them off.
k2.useActivityBar false Show the K2 panel in the Activity Bar instead of the Secondary Side Bar.
k2.watches.maxActive 10 Watches one chat may have at the same time (1 to 50).
k2.watches.maxWakeUpsPerHour 20 Wake-ups one chat may have per hour (1 to 120).
k2.watches.maxUnattendedWakeUps 5 Wake-ups in a row without a message from you, after which the chat's watches pause (1 to 50).
k2.watches.maxWakeUpChars 4000 The most characters one wake-up carries (500 to 20000).
  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
  • Your Privacy Choices
  • Consumer Health Privacy
© 2026 Microsoft