# Kimodo.cpp on Windows: setup from scratch

Kimodo turns a text prompt into human motion. You type "a person does a cartwheel"
and get an animation you can retarget onto any humanoid rig. This is the C++/GGML
port, so it runs locally with no Python and no network calls at generation time.

- Port: <https://github.com/localai-org/kimodo.cpp>
- Original model: <https://github.com/nv-tlabs/kimodo>

Everything below was run on Windows 11 with an RTX 4070 SUPER. Every command is
copy-paste ready.

---

## 1. What you actually need

| Resource | Minimum | Comfortable |
|---|---|---|
| Free disk | 25 GB | 35 GB |
| System RAM | 4 GB | 32 GB, see the speed note at the end |
| VRAM (GPU path) | 1.2 GB | 2 GB |
| CPU | 2 cores | 6 cores |
| Admin rights | required to install the toolchain | |

**A graphics card is optional.** The whole run is dominated by streaming the
15.2 GB text encoder, not by arithmetic, so a fast card buys much less than you
would expect. On the author's bench an RTX 5090 was only about 1.3x faster than a
16-core processor on a short clip.

Peak memory stays under 2 GB in every configuration, GPU or CPU.

---

## 2. Which models you can actually download

This part changed on 26 August 2026 and most write-ups are already out of date.

| Model | Skeleton | Licence | Download |
|---|---|---|---|
| **SOMA RP v1.1** | SOMA, 30 joints | NVIDIA Open Model License | free, commercial use allowed |
| **SOMA SEED v1.1** | SOMA, 30 joints | NVIDIA Open Model License | free, commercial use allowed |
| **G1 RP v1** | Unitree G1, 34 joints | NVIDIA Open Model License | free, commercial use allowed |
| **G1 SEED v1** | Unitree G1, 34 joints | NVIDIA Open Model License | free, commercial use allowed |
| SMPL-X RP v1 | SMPL-X, 22 joints | NVIDIA Internal Scientific R&D | **converted locally only** |

The SMPL-X GGUF was published and then withdrawn: the upstream NVIDIA licence
forbids redistributing derivative models, so the converted weights came down. The
model card that replaced them explains it rather than 404-ing. You can still use
SMPL-X by accepting NVIDIA's licence on Hugging Face yourself and converting the
checkpoint with `scripts/convert_motion_to_gguf.py` in the repo. That licence
limits it to internal, non-production research.

**If you want something you can ship, use SOMA or G1.**

---

## 3. Install the toolchain

Open PowerShell as Administrator.

```
winget install Git.Git
```

```
winget install Microsoft.VisualStudio.2022.BuildTools --override "--quiet --wait --norestart --add Microsoft.VisualStudio.Workload.VCTools --add Microsoft.VisualStudio.Component.VC.CMake.Project --includeRecommended"
```

`Microsoft.VisualStudio.Component.VC.CMake.Project` is not optional. Without it you
get a compiler but no CMake and no Ninja, and the error you eventually see will not
mention that.

```
winget install KhronosGroup.VulkanSDK
```

Skip the Vulkan SDK only if you intend to run on the processor.

```
winget install GoLang.Go
```

Go is only needed for the local web interface. Skip it if you are happy with the
command line.

**Close every terminal and open a new one now.** The Vulkan installer sets
`VULKAN_SDK` machine-wide, and a terminal opened before that will never see it. The
symptom is a configure error reading
`Could NOT find Vulkan (missing: Vulkan_LIBRARY Vulkan_INCLUDE_DIR glslc)`.

---

## 4. Clone the repository

```
git clone --recurse-submodules https://github.com/localai-org/kimodo.cpp
cd kimodo.cpp
```

`--recurse-submodules` matters. GGML is a submodule, and a plain clone leaves it
empty. Downloading the repository as a ZIP from GitHub does not work at all, for
the same reason.

---

## 5. Open a build terminal

The compiler is not on `PATH` in a normal terminal. From any terminal:

```
cmd /k "C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Auxiliary\Build\vcvars64.bat"
```

Adjust the path for your edition: `Community`, `Professional`, `Enterprise`, or the
`BuildTools` path above. Verify before going further:

```
where cl & where cmake & where ninja
```

All three must print a path. If any says it could not find the command, you are in
the wrong terminal.

> If the machine has more than one Visual Studio installation, the Start menu will
> contain several entries called *x64 Native Tools Command Prompt for VS 2022*,
> distinguished only by a `(2)` suffix. They point at different installations, and a
> half-removed installation keeps its shortcut while having no compiler at all. The
> `where` check above catches that in two seconds.

---

## 6. Two source fixes for the Microsoft compiler

Both are correct on every platform. They simply have not been merged upstream yet.

**Add `#include <stdexcept>`** to these three files, alongside their other
`#include <...>` lines:

- `src/denoiser.cpp`
- `src/generate.cpp`
- `src/llm_tokenizer.cpp`

All three use `std::runtime_error` without including the header that declares it.
Other compilers pull that header in indirectly, which makes this a latent bug
everywhere rather than a Windows quirk. Without the fix:

```
error C2039: 'runtime_error': is not a member of 'std'
```

**In `src/llm_text_encoder.cpp`**, around line 63, change:

```cpp
result->file = gguf_init_from_file(path.c_str(), params);
```

to:

```cpp
result->file = gguf_init_from_file(path.string().c_str(), params);
```

`std::filesystem::path::c_str()` returns `const wchar_t*` on Windows and
`const char*` elsewhere. `.string().c_str()` is `const char*` on both. Without the
fix:

```
error C2664: cannot convert argument 1 from 'const std::filesystem::path::value_type *' to 'const char *'
```

---

## 7. Build

In the build terminal from step 5:

```
cmake -S . -B build-win -G Ninja -DCMAKE_BUILD_TYPE=Release -DKIMODO_ENABLE_VULKAN=ON -DKIMODO_BUILD_TESTS=OFF
```

```
cmake --build build-win
```

Use `-DKIMODO_ENABLE_VULKAN=OFF` for a processor-only build.

If an earlier attempt failed, delete the build folder first. CMake caches the failed
configuration and will otherwise keep reusing it:

```
rmdir /s /q build-win
```

---

## 8. Download the weights

The helper in the repository is a shell script, so on Windows fetch the files with
the Hugging Face command line tool.

```
pip install huggingface_hub
```

The text encoder is shared by every model, so you download it once:

```
hf download LocalAI-io/Llama-3-Kimodo-GGML --local-dir . --include "generated/llm2vec-text-bundle/*"
```

That is 15.2 GB across 32 layer files plus an embedding table. Then pick a motion
model, about 1.13 GB each:

```
hf download LocalAI-io/Kimodo-SOMA-RP-v1.1-GGML --local-dir . --include "models/*"
```

```
hf download LocalAI-io/Kimodo-SOMA-SEED-v1.1-GGML --local-dir . --include "models/*"
```

```
hf download LocalAI-io/Kimodo-G1-RP-v1-GGML --local-dir . --include "models/*"
```

```
hf download LocalAI-io/Kimodo-G1-SEED-v1-GGML --local-dir . --include "models/*"
```

Adding all four costs about 4.5 GB, not four times 17, because the encoder is shared.

**A gotcha worth knowing.** If a repository has been emptied upstream, `hf download`
with `--include` matches nothing and exits successfully. You get no error and no
files. Always check that the `.gguf` actually landed in `models\`.

---

## 9. Run it from the command line

The GGML DLLs live in the build tree's `bin` folder, not next to the executable:

```
set PATH=%CD%\build-win\bin;%PATH%
```

Without this the program exits instantly with no output and no error, which looks
exactly like a crash but is really Windows failing to load a DLL.

The command line is positional:

```
build-win\kmd-generate.exe MOTION.gguf TEXT_BUNDLE PROMPT.txt FRAMES STEPS SEED OUTPUT_DIR
```

Write your prompt into a plain text file first, then:

```
build-win\kmd-generate.exe models\kimodo-soma-rp-v1.1-f32.gguf generated\llm2vec-text-bundle prompt.txt 90 20 41 out
```

`90` frames is three seconds at 30 fps. `20` is the denoising step count, and 20
works well for both drafts and final output. Cost is linear in steps, so 100 steps
costs five times as much for no visible gain.

---

## 10. Run the web interface

```
go run ./demo -addr 127.0.0.1:8094 -generator build-win/kmd-generate.exe
```

Then open <http://127.0.0.1:8094>.

The interface has a model picker, a prompt box, a frame count, a 3D preview and a
**Download GLB** button. The GLB is built by the demo server, so you get a file that
opens straight in Blender without touching the raw output.

**The model list is built once at server start.** If you download another model
while the server is running, it will keep saying the file is missing until you
restart it.

---

## 11. Settings that matter

| Variable | Values | Effect |
|---|---|---|
| `KIMODO_BACKEND` | `cpu` | Force the processor path in a Vulkan build |
| `KIMODO_TEXT_LAYER_CHUNK` | 1 to 8 | Encoder layers resident at once. The memory dial |
| `KIMODO_THREADS` | integer | Thread count, defaults to every logical core |
| `GGML_VK_VISIBLE_DEVICES` | index list | Filter and renumber the Vulkan device list |

`KIMODO_TEXT_LAYER_CHUNK` is the only memory control, and it is **layers, not
gigabytes**:

| Chunk | Peak VRAM | Verdict |
|---|---|---|
| 2 | 1.2 GB | Safe on a 2 GB card |
| 4 | 1.8 GB | Recommended for 4 GB cards |
| 8 | 3.5 GB | The default |
| 32 | - | Crashes, the computation graph is a fixed size upstream |

Raising it does **not** make generation faster. The encoder is read once per run at
any chunk size.

To run on the processor instead:

```
set KIMODO_BACKEND=cpu
set KIMODO_TEXT_LAYER_CHUNK=4
```

The program takes the first Vulkan device it can see. On a desktop with one discrete
card that is the right one. On a laptop it is usually the integrated GPU. List them
with `vulkaninfo --summary`, which ships with your graphics driver, and then pick:

```
set GGML_VK_VISIBLE_DEVICES=1
```

---

## 12. Frames and steps

**FRAMES** runs at 30 fps, so 90 is three seconds. Output stays coherent up to
**300 frames, or 10 seconds**. At 400 the clip develops jitter, and at 600 it
collapses into noise after roughly frame 300. For anything longer, generate segments
and blend them.

Longer clips come out calmer. The same prompt at 120 frames produces sharper, more
athletic motion than at 300, because the model fills the extra time rather than
repeating the action at the same intensity. If you want one punchy move, generate it
short.

**STEPS** is the denoising count. 20 is the working default. This is the only stage a
graphics card meaningfully accelerates, so a high step count is where a discrete card
earns its keep.

---

## 13. What comes out

Two raw little-endian 32-bit float files land in the output directory, plus a GLB if
you went through the web interface.

| File | Shape | Contents |
|---|---|---|
| `local_rotations_xyzw.f32` | `[FRAMES, JOINTS, 4]` | Local rotations as XYZW quaternions |
| `root_positions.f32` | `[FRAMES, 3]` | Root translation in metres |

**`JOINTS` depends on the model, and getting this wrong is silent.** SMPL-X is 22,
SOMA is 30, G1 is 34. A 90-frame SOMA clip is exactly 90 x 30 x 4 x 4 = 43,200 bytes.
If you read it with a 22-joint stride you get garbage with no error.

The coordinate frame is Y-up with Z forward. Rest orientations are identity, which
means the rest pose is a T-pose and every animated global quaternion doubles as the
world-space delta from rest. That property is what makes retargeting onto another
skeleton straightforward.

---

## 14. Why your first run is slow

Every run streams the 15.2 GB encoder. If your file cache cannot hold it, that read
happens again on every single generation.

Measured on a Ryzen 7 7800X3D with 31 GB of RAM and the weights on a SATA SSD: a
three-second clip took **399 seconds**, of which about **380 was disk reading** and
only **10 seconds was CPU**. The graphics card sat idle the whole time.

The fix is not a faster card. It is one of these:

1. **Put the weights on an NVMe drive.** Biggest single win.
2. **Free up RAM before generating.** The encoder needs about 16 GB of free file
   cache to stay resident. A machine with 32 GB and a busy desktop will only have 7
   GB of cache available, and behaves like a 16 GB machine.
3. Run one generation to warm the cache before you start working.

---

## 15. Troubleshooting

| What you see | What it means |
|---|---|
| Program exits instantly, no output at all | The GGML DLLs are not on `PATH`. Add `build-win\bin` |
| `'cmake' is not recognized` | Not in a build terminal, or the CMake component was not installed |
| `No CMAKE_CXX_COMPILER could be found` | Same cause. Check with `where cl` |
| `'C:\Program' is not recognized` | Command Prompt split a path on the space. Quote the whole path |
| `Could NOT find Vulkan (missing: ... glslc)` | The terminal predates the SDK installation. Open a new one |
| `error C2039: 'runtime_error' is not a member of 'std'` | The source fixes in step 6 are not applied |
| `cannot convert ... path::value_type * to const char *` | The same, for the second fix |
| `cannot allocate text component .../layer-NN.gguf` | Out of memory. Lower `KIMODO_TEXT_LAYER_CHUNK` |
| `cannot allocate text component .../embedding.gguf` | The hard floor. The embedding table is one 1.05 GB block that cannot be split. About 1.3 GB must be free |
| `GGML_ASSERT(cgraph->n_nodes < cgraph->size)` | Chunk size too high. Use 8 or lower |
| Downloaded weights but `models\` is empty | The repository was emptied upstream and `--include` matched nothing |
| Model shows as missing in the web UI | The list is built at server start. Restart the server |

---

## Licences

- kimodo.cpp: see the repository.
- SOMA and G1 checkpoints: [NVIDIA Open Model License](https://www.nvidia.com/en-us/agreements/enterprise-software/nvidia-open-model-license/). Commercial use permitted.
- SMPL-X checkpoint: [NVIDIA Internal Scientific Research and Development Model License](https://www.nvidia.com/en-us/agreements/enterprise-software/nvidia-internal-scientific-research-and-development-model-license/). Internal research only, not redistributable.
- The text encoder is Llama-3 derived and carries the Meta Llama 3 licence.

Check the licence of the specific checkpoint you generate with before you ship
anything made with it.
