TrueVoid Development LogoProjects

Claude in Kerbal Space Program

Learning Orbital Mechanics the Hard Way

May 17, 2026

Kerbal Space Program (KSP) is a game I started playing around 2012. The goal is to give your best attempt at building the largest stable rocket, send missions to each body in the Kerbol System and not kill too many Kerbals in the process. This was perfect timing, as I was at the time doing my bachellor in Physics. I vividly remember sitting in the faculty library, just about to start homework, when I finally managed to rendezvous with another vessel in Low Kerbin Orbit (LKO). I know no better example of the difference between intellectually understanding the radius of a circular orbit, and the feeling of circularizing your orbit or crash back into the planet. XKCD captures it very well.

A line graph titled 'How Well I Understand Orbital Mechanics' across time, with small peaks at 'took high school physics', 'got physics degree', and 'actual job at NASA', and a near-vertical spike labelled 'started playing Kerbal Space Program'.

xkcd #1356 — Orbital Mechanics · CC BY-NC 2.5

A line graph titled 'How Well I Understand Orbital Mechanics' across time, with small peaks at 'took high school physics', 'got physics degree', and 'actual job at NASA', and a near-vertical spike labelled 'started playing Kerbal Space Program'.

Goal

While nostalgia from playing games from 2012 is a worthy goal all by itself, the reason to toy around with KSP is a simple question: how well can Claude plan missions?

Developers prepare a plan before implementing changes in a codebase. This helps the model stay grounded while working, maintaining context and keeping it on track. Planning a mission in KSP shares some aspects: we set a goal, information is collected, certain actions are proposed, a document is written and then the work starts. For example:

  • Objective. Mission to the Mun.
  • Information. Delta-V calculations, parts available, time of day, vessel design.
  • Actions. Orbital maneuvers, milestones, transfers.
  • Document. Write the mission plan, and post-mission findings.

The implementation of this plan is then the careful execution of this. Easier said than done, of course. While setting a goal is very simple, collecting KSP data and planning actions is not exactly in the training data of these LLMs, which also represents an excellent opportunity to test their performance. We can, however, use Claude to build the scaffolding required to expose this information in a more manageable way.

Collecting Information

While Claude by itself can figure out how to read game files and search the internet, it is error prone and slow. Instead it is worth creating several tools that expose this information in a way that is easier to consume by the LLM. This takes the form of a CLI program, ksp-live, for reading game data, save files and exposing, well, live data from the current session. Combined with an offline dump of the KSP wiki to avoid hammering the site even more, Claude has easy access to all the information required to fully plan our mission.

Before we get to what we are doing here it is important to show how much the KSP community has done with a game at this point about 15 years old. Take exposing live data from the game, for instance. You may, as I did, think that you need to write a mod for reading internal game state and expose it over an API that you can reach from another process. However, user djungelorm released back in 2016 a mod exactly for this purpose. This mod includes a webserver to access the game state using protobuf over TCP, which is exactly what we need. Similarly, there is the krpc-client crate that includes the pre-generated structs and otherwise from the protobuf schema. This is not even the only mod. We can now easily convert the data received over protobuf from the game into easy-for-Claude-to-digest JSON in the CLI.

ksp-live — pull live state from a running KSP install

USAGE:
    ksp-live [OPTIONS] <SUBCOMMAND> [ARGS]

OPTIONS:
    --host HOST:PORT       Telemachus HTTP endpoint (default 192.168.2.23:8085)
    --krpc HOST:PORT       kRPC RPC endpoint        (default 192.168.2.23:50000)
    --krpc-stream H:P      kRPC stream endpoint     (default 192.168.2.23:50001)
    --sfs PATH             persistent.sfs (local path or ssh://host:PATH)
    --gamedata PATH        GameData/ root (local path or ssh://host:PATH)
    --backend NAME         override backend: telemachus | krpc (orbit, vessel)
    --pretty               indent JSON output
    --timeout SECS         per-request timeout (default 10s)

SUBCOMMANDS (live, active vessel):
    ping                   liveness for HTTP + RPC + SFS-reachable
    vessel                 active vessel snapshot                (kRPC | Telemachus)
    orbit                  Ap / Pe / ecc / inc / period          (kRPC | Telemachus)
    resources              whole-vessel resource totals          (kRPC)
    crew                   kerbals aboard                        (Telemachus)
    flight                 atmospheric / surface flight data     (kRPC)
    parts                  per-part list with mass/stage         (kRPC)
    engines                per-engine thrust / Isp / propellants (kRPC)
    comms                  comm-net status                       (kRPC)
    experiments            science experiments aboard            (kRPC)
    stages                 per-stage resource breakdown          (kRPC)
    flight-plan            maneuver-node list                    (kRPC)
    maneuver               next maneuver node                    (Telemachus)

Excerpt from the output of ksp-live --help. If you are wondering why ssh and not just 127.0.0.1: the game is running in a different computer than where Claude Code is.

How does Claude then use this tool? Like any other: it reads ksp-live --help to generate some documentation, whether in memories or in CLAUDE.md, and then when planning a mission to reach LKO it reaches for ksp-live delta-v to see how much oomph does the current vessel have:

{
  "total_vac_ms": 4954.782531738281,
  "total_asl_ms": 4000.5552673339844,
  "total_actual_ms": 4000.5552673339844,
  "stage_count": 5,
  "stages": [
    {
      "stage": 4,
      "delta_v_vac_ms": 1391.9361572265625,
      "delta_v_asl_ms": 1159.94677734375,
      "delta_v_actual_ms": 1159.94677734375,
      "start_mass_t": 37.553504943847656,
      "end_mass_t": 19.103504180908203,
      "fuel_mass_t": 28.19000244140625,
      "burn_time_s": 42.217628479003906,
      "twr_vac": 2.4429969787597656,
      "twr_asl": 2.0358312129974365,
      "isp_vac_s": 210.0,
      "isp_asl_s": 175.0,
      "thrust_vac_kn": 899.9998779296875,
      "thrust_asl_kn": 750.0
    },
    # ...
    {
      "stage": 0,
      "delta_v_vac_ms": 0.0,
      "delta_v_asl_ms": 0.0,
      "delta_v_actual_ms": 0.0,
      "start_mass_t": 1.4000000953674316,
      "end_mass_t": 1.4000000953674316,
      "fuel_mass_t": 0.24000000953674316,
      "burn_time_s": 0.0,
      "twr_vac": 0.0,
      "twr_asl": 0.0,
      "isp_vac_s": 0.0,
      "isp_asl_s": 0.0,
      "thrust_vac_kn": 0.0,
      "thrust_asl_kn": 0.0
    }
  ]
}

Another excerpt, this time running ksp-live delta-v | jq.

With this information, combined with its own knowledge and a helpful wiki article, Claude can figure out whether your rocket can achieve its goal.

Mission Planning

… Or can it?

The following is the start of the latest mission plan Claude wrote as a proposal to get to a stable circular orbit and complete a few contracts. This is career mode, which means you obtain rocket parts by accumulating science to unlock new technologies. Contracts additionally reward money to upgrade buildings and, of course, build larger rockets. The usual game loop.

Note that we are also using MechJeb2 and KRPC.MechJeb. This way Claude can also set up orbital maneuvers. Rendered using glow.

To set the scene: we have three contracts. The first is to achieve a stable orbit above 70km, the second is to use a certain decoupler part while in orbit, and a third one is to ignite a certain type of engine, the Valiant.

Now, this plan sounds reasonable until…

This table shows each stage in the rocket. If you imagine a rocket as a series of engines ignited one after the last, each row in the table corresponds to one of those engines.

There is an important detail to consider: this Valiant contract we are trying to complete requires the engine to be ignited for the first time above 390 km. Therefore, the plan is roughly: go up to about 80 km (this is the apoapsis, highest point in the orbit), circularize your orbit to 70 km (the periapsis, the other side of the orbit). Because both are above 70 km, which is the atmosphere upper limit, this counts as a stable LKO. After the orbit is circular, we can burn engine at the periapsis in the direction of travel to move our apoapsis above 390 km in a very eliptical orbit so that we can ignite the Valiant there to slow down and fall back down to Kerbin. Simple enough, right?

The rocket itself, First Light MkI, standing in the Vehicle Assembly Building (VAB). Those windows on the right show the calculated delta-V values in-game.

Screenshot of the rocket designed to fulfill the Valiant contract.

If you have ever played KSP you will notice several red flags here. The very first one being that getting to a circular orbit at 390 km (plus de-orbit!) from the ground on a total delta-V of 4 to 5 km/s is not going to happen. On top of that, claiming a margin of 440 m/s and calling the entire plan comfortable is the cherry on top. Another example of this behavior was when placing a heat shield. Claude suggested to have, from top to bottom: the pod, heat shield and science instruments. Can you guess where the heat goes in this design?

Regardless of that, we move the vessel to the launchpad and get ready for liftoff. Claude here uses ksp-live to configure MechJeb2 over kRPC with the plan to enter a stable orbit. A few minutes later the rocket sits (metaphorically) on a decaying orbit about 80 km high without any fuel left, even after igniting the Valiant. The following excerpt from the plan explains:

After several more attempts we conclude with an unfortunate game crash because of another mod that forces us to revert before we accepted any contracts so we can start over from scratch. The excerpt below is the summary Claude wrote. I think it is an appropriate point to finish this section and look at what we have learned from this.

If you have worked with Claude and other LLMs before you will notice tell-tale signs here of excuses (DLL stale: no it was not), assumptions and guesses (wrong CLI flag: too lazy to check), overconfidence in own’s predictions (ascent inefficiency: no, it cannot get much better).

Learning From Failures

While playing a game like Kerbal Space Program with Claude is definitely not what neither party was thinking about, I think it shows clearly many failure modes that arise when using these tools for more common purposes like development. Here they are particularly blown out of proportion in part because of the much longer iteration time. It takes 20 minutes or so to design a new vessel, move to the launchpad and oversee the ascent. It is not a 10-seconds-long run of a script or build. When iteration time is this long and consequences of failure are high, it is worth spending time thinking and planning before the attempt ends again crashing back on the ground.

During this experiment I noticed several factors that compounded into catastrophic failure, most of them are variations of behavior we noted above:

  • Overconfidence in guesswork. Perfect example here was to assume 3.4 km/s delta-V is sufficient, when reality is ~4.3 km/s. I have seen similar behavior in particular when trying to find a more optimal implementation of some code. Claude would “reason” through with numbers and estimates that always present a better result that what we find in practice . I personally find it astounding that these number-based explanation can entrench so much the rest of the conversation that at best we have wasted time and tokens, and at worst the model is just stuck optimizing the wrong thing. Luckily in normal development there are vast swaths of people-written knowledge to draw from: in KSP not so much.
  • Ad-hoc explanations and excuses. Above we saw one example of this with “the DLL is stale”. I have seen “the test does not pass because the resource is not available on the dev host”, shifting blame somewhere else “known behavior of an API”, defer work until later phases with “another agent will wire this API”. These are the most egregious the longer we are in the context window, requiring constant user interruptions and guidance. This issue compounds when these excuses become an intrinsic part of the session, as they are used to justify almost any other issue.
  • Guessing and baseless reasoning. Sometimes similar to excuses from the point above, but shows up differently. As an example from this mission is trying to use the wrong CLI flag to set the orbit apoapsis. During more normal development this shows as implicit microdecisions taken that are just slightly wrong but are pervasive because they don’t cause an immediate failure. The worst part is that these are not surfaced entirely until much later, when Claude mentions that something is out of scope, or some unexpected behavior, or anything else that may fundamentally defeat the purpose of what you were trying to do in the first place. This behavior is nothing new: people tend to do the same when we are not particularly familiar with the system. We just do not know what elements are important which ones are not, while for an experienced developer these stand out. Lastly, maybe in an effort to reduce utilization the model is sometimes overly lazy on checking files or finding more detailed information that would have helped the work.

Using these tools for development involves recognizing these signs and learning what to do to mitigate them. Most of the time this is solved by specifying in the context that Claude must ground its information, guide it to find the information, and pointing out when it is using excuses to get out of work. Unattended work, however, suffers heavily from these issues. While writing them in the plan and CLAUDE.md and similar files somewhat helps, they quickly get lost in context length unless they are repeated. I do not know whether it is a problem to be solved purely at model training level or harness, but it is the main source of required user input right now. It is a fine line to walk to decide whether the “simplest solution” or the most complex one is the better call.

I would personally like to avoid moving the goalpost and appreciate what we can do with Claude that we would not have been able to do otherwise. First and foremost: it is a new way of playing with a game that is over a decade old. Not only that, but using Claude allows us to very easily set up scaffolding that while doable it would have taken too much time and effort to do as a one-off fun experiment. For example, writing a small KSP mod in C# to expose additional information over kRPC from MechJeb. Similarly for reading game files and saves.

All in all, it was quite a fun experiment.