Dev blog 2026-10-22 · Keel 0.5.3.1 development

Inside the 0.5.3.1 update

Incursions, Rifts, Dreadnoughts, wings, and a Keybinds tab.

Keel 0.5.3 went live on 2026-10-22 with a long list. Keel 0.5.3.1 puts one more screen on top of it, Settings > Keybinds. This post tours the whole update in one read, then looks at the keybinds code in detail, because that is the one part our deep dives have not covered.

Shipped in 0.5.3: everything in the tour. Coming in 0.5.3.1: the Keybinds tab, with its map drag and wheel options.

The Settings panel with the Keybinds tab selected. Zoom speed reads Normal, and Invert wheel and Smooth zoom are unticked. The list shows Move the active ship on Left click, Order the escorts on Right click, and Take control of ships 1 to 8 on the keys 1 to 8, each row with a Clear button. Reset all sits at the foot.
Settings > Keybinds, a capture of the 0.5.3.1 development build, cropped to the panel. The tab is open over the login page, and the list shows the first rows of the Map and Fleet groups.
The problem

A long list of gaps, closed in one update.

Incursions, Rifts, the hull ladder, fleet control, logging out, standing, reports and the keys each got work in this update. Four of the items carry a report number in our code comments: 145, 151, 157 and 160.

The keybinds were meant for the same build. They missed it, so they follow in 0.5.3.1. The patch notes for 0.5.3.1 will be one entry that holds the whole list, and this post has the same shape: the 0.5.3 tour first, then the keybinds as the newest part.

Each tour item is two or three sentences with the numbers that define it. We checked every number against the code on main, and the keybinds numbers against the merged keybinds code. If you want one mechanic in depth, the deep dives are named near the end.

Shipped in 0.5.3

The 0.5.3 tour, headline by headline.

Ten headlines from the patch notes, each with the numbers that define it.

3waves in every incursion
6fixed Rifts, one for each layer
6hull classes, with the Dreadnought
4wings, A to D
Incursions in three wavesAn incursion is a screen swarm, a battle line and a command group, holding about 50, 33 and 17 percent of a sector's ships. Pilots on the layer get a banner and a map outline 60 seconds before the ships appear. The next wave launches when the last is cleared or after 300 seconds, and the clear pays once, at the end. Every contributor over 5 percent of a clear gets PvE Salt: 1, 1, 2, 3 and 4 on Layers 2 to 6.
Six fixed RiftsRift 1 to Rift 6 replace the temporary Rifts. Each matches a layer, sits on a 28 by 28 box, flies twice the layer's ships in each sector and pays twice its loot, four times in a Rift incursion. A Rift has no Haven and open fire, and one static exit leads back to the layer. Each Rift reshapes in its own storm every 12 hours, and a wormhole from any layer can lead into any Rift.
DreadnoughtsA charter's sixth hull class, kept in the new Charter > Hangar tab. The Keel blueprint is one-use and spends 10 standing with a faction merchant. The build takes 72 hours, and the first Dreadnought needs a charter Shard sum of 300, the second 750. Deployed, it burns 200 Helium-3 an hour and flies alone. Its Siege roots it for 60 seconds, triples its damage and adds 0.30 to its resists. A destroyed Dreadnought is gone for good.
TitansYou meet a Titan only inside its own pocket. A one-use Titan Beacon costs 5 standing at the Enclave of the faction its faction beats, and a Dreadnought lights it away from Layer 1. A wormhole and a pocket then open for 60 minutes, a square nine sectors a side, for anyone to follow, and at most 4 pockets are open at once. A Titan kill puts the Dreadnought pilot's standing with that faction at -2.5.
Four wingsThe F1 to F4 control groups became wings A to D. A ship is in one wing, and ships in none are Main on F5. Each wing keeps its own stance and formation. Orders, Focus Fire and Regroup go to the picked wings, or to every escort when none is picked. Wing-mates cover a Clamped mate for up to 20 seconds, and the contact cards follow the sector you view.
Logging out and landingLog out, and 15 seconds later your ships in space retreat and berth at Haven with their cargo. A dropped connection gets the same treatment once it has stayed gone for 20 seconds. Ships on Layer 6 or in a Rift have no Haven and stay put. Arriving through a wormhole gives 5 seconds of grace, and Esc cancels a fleet's jump, which blocks the next jump for 15 seconds.
A way back from HostileWhile you are Hostile or KOS with a faction, its merchant lists a Restitution hunt against its rival. You take it, hand it in and abandon it from anywhere with no docking. It pays that layer's normal standing and costs the rival nothing, until you are Neutral again.
Reports reach DiscordBugs and ideas filed in game now also become threads in Keel's Discord, with a Me too button, a pinned log and merged duplicates. The report form says it posts publicly, and a fixed report's thread says which version fixed it. Earlier reports are being posted too.
Remember meTick the box on the login page and the game keeps a token on this PC for 30 days, never your password. An account keeps at most 8 tokens, and logging out with the box unticked forgets yours.
Protocol 5, and the fixesThe wire protocol moves to 5, so an older client is told to update at login. The fixes include contracts that follow the deepest layer you fought on, a shield number beside each ship tile's bar, Industry Jobs and Blueprints tabs, and a sector card that lists every structure built there.
Incursions on the map

Two incursions, outlined in purple.

Layer 2 in a scratch world with two incursions on it. Each is a block of outlined sectors, the right one carries its INCURSION tag, and the top bar counts them. The wing chips sit at the bottom, and the pilot's own ships are in the hex at the centre.

The Keel map on Layer 2 with a small hex neighbourhood in the centre and two groups of purple outlined sectors, one near the top left and one near the top right, and the right one is tagged INCURSION. The top bar reads 2 incursions. The fleet cards sit on the left and the command bar with order, stance, formation and group chips at the bottom.
Layer 2, a capture from the keel shots set, taken on a scratch server with dev tools on an early 0.5.3 build. The command bar row at the bottom still reads GROUP, which the released build calls WING.
Coming in 0.5.3.1

Every key is a setting now.

Settings gets a second tab, Keybinds. It lists 39 actions, each with one key or mouse button you can change. The defaults do not move: left click still moves, right click still orders, the middle button still drags the map and the wheel still zooms toward the cursor.

39actions you can rebind
1binding for each action, no key combinations
6 pxa held button must move before it becomes a drag
1.10zoom for one wheel notch by default, 1.05 Slow and 1.20 Fast

A tester in Discord suggested a Keybinds screen, asked for the map drag on the left button, and said the middle scroll button feels funky. This is our answer to all three.

As a pilot lives it

  1. Open the tabSettings has two tabs, General and Keybinds. Both open from the login page too, because they only edit a file on this PC.
  2. Press RebindClick a row's button. It reads Press a key and the list dims. Press a key or click a mouse button. Esc cancels, and after 5 seconds nothing changes.
  3. Settle a clashIf another action holds that input, the notice names it. Swap trades the two, Replace leaves the other unbound, Cancel changes nothing.
  4. Move the dragPan the map is middle click by default. Give it Left and a quick click still moves the ship, on release, while a drag of 6 px or more pans.
  5. Tune the wheelZoom speed, Invert wheel and Smooth zoom sit above the list. Reset puts one row back, and Reset all puts back every key and the wheel options.
WaitingPress a key or click a mouse button for Follow. Esc cancels.
ClashD is Defend. Swap trades them. Replace leaves Defend unbound.
Shared buttonLeft click is also Move the active ship: a quick click still acts, a drag pans.
RefusedThat key cannot be used.
TimeoutTimed out. Nothing changed.

The wording is copied from keybinds_tab.gd and keymap.gd. The key and action names are filled in by the tab.

You can rebind

  • Map: move and order, 2 actions.
  • Fleet: take control of ships 1 to 10, and next ship, 11 actions.
  • Orders: Follow, Attack move, Focus, Hold, Defend, Retreat, Regroup, 7 actions.
  • Wings: wing A to D and Main, 5 actions.
  • Powers: Brace, Clamp, Unclamp, Jam, Siege, 5 actions.
  • Camera: the map drag, four pan keys, centre, zoom in and zoom out, 8 actions.
  • Other: help for the open screen, 1 action.

Stays fixed

  • Esc, which backs out of things in a fixed order.
  • Enter and Keypad Enter, which send chat and forms.
  • Caps Lock, and Shift, Ctrl, Alt and Meta as bindings. Shift still queues and adds a wing, and Ctrl still stores one.
  • Clicks on fleet cards, wing chips, banners and buttons.
  • Move and Order can be moved or swapped, but never cleared.
The map drag, on any button or keyThe drag is an action called pan_drag. On a button nothing else uses, such as Middle or a side button, the pan starts at once. On Left or Right the press waits: past 6 px it becomes a pan that carries everything moved so far, and if the button comes up first it is a click, sent at the hex you pressed. On a held key the mouse pans while the key is down and clicks work as usual. The wheel cannot be the drag, because it cannot be held. A release lost to Alt-Tab ends the drag with no click.
The wheel optionsZoom speed is 1.05, 1.10 or 1.20 per notch. Invert wheel turns the wheel round and leaves a zoom key alone. Smooth zoom, off by default, moves a target zoom and eases the camera to it while the hex under the cursor stays put. The wheel's own factor now counts too. Before, every wheel event zoomed by exactly 1.1, so a wheel that sends many small events got a full step for each. Now a step is the zoom step raised to the factor, held between 0.05 and 3, and a missing factor counts as one notch.
What follows a rebindThe badge on a power button shows up to three characters of your key. The order chips and wing chips show your keys, the fleet card tooltip names your number key and your next-ship key, and the CLAMPED tag shows your Unclamp key. Help and the tutorial still name the default keys, and the Controls help says so.
Saved on this computerBindings live in user://keel_settings.cfg under [keys], and only the ones you changed are written. The wheel options live under [map]. A default we change later therefore reaches everyone who never touched it. A hand-edited file that gives two actions one input leaves the later one unbound and shows it in the warning colour, and Move or Order can never load as none.
Under the hood

One server, one new client table.

The 0.5.3 rules sit in one server module for each system. The keybinds sit in one client table and two helpers. The server still owns hits, sectors, inventory and what a scanner can see, and the client still draws.

Serverrules.py holds the constants. Each system has a module: rifts.py with 212 lines, titans.py with 734, fleet.py with 1159, structures.py with 1176, factions.py with 657 and storms.py with 420. world.py, at 4256 lines, builds the World from those mixins and runs the tick.
Wire and Discordkeel_server.py holds the protocol number and the remember token handshake. intake.py, 330 lines, and discord_ops.py, 506 lines, are the bot's only way in. In the bot, gamethreads.py and backfill.py post the threads.
Clientcommand_bar.gd draws the orders and wing chips, and settings_panel.gd hosts the tabs. main.gd, 6472 lines on main, draws the map and routes input. The keybinds add keymap.gd, map_pointer.gd and keybinds_tab.gd.

One keypress, as a call chain

  1. StartKeymap reads the defaults, then the player's file, then registers every action in Godot's InputMap.setup, load_from, _register
  2. Askmain.gd asks which action a key or button is, then runs it. A move or order sends the same op as before.action_of, _run_action
  3. PointMouse presses go to the map pointer, which keeps a click apart from a drag and emits clicked or panned.press, motion, release
  4. CaptureOn Rebind the tab takes the next input, and no hotkey fires while it waits.begin_capture, feed, capture
  5. ClashIf another action holds the input, nothing changes until Swap, Replace or Cancel.holder_of, resolve
  6. SaveEach change is saved at once, and only the changed bindings are written.set_binding, save_to

The main functions

action_ofkeymap.gd

Asks the InputMap which keel action a pressed key or button is. It skips key repeats and leaves the drag to be read apart.

press, releasemap_pointer.gd

The click versus drag rule. A button that is both the drag button and a click button waits for 6 px, then pans, or clicks on release at the hex it was pressed on.

zoom_multiplierkeymap.gd

The step for one wheel event or zoom key, from the zoom speed, the wheel's factor and Invert wheel.

feedkeybinds_tab.gd

Takes one input while the tab waits, asks Keymap what it means, and shows bound, refused, cancelled or a clash.

Choices we are happy with

One tableDecision D95 sets a standing rule: a new key or button goes in Keymap.ACTIONS, never as a key constant in code. Before this, the client had no input actions at all.
A pointer we can testThe map pointer is a small object with two signals, so the click versus drag rule is checked without a window or a mouse.
Defaults checkedThe self-test checks a table of the keys the old handler used against the new defaults, and that no two defaults share an input. It samples the old keys, so it does not cover all 39 defaults.
The server never learnsA rebound key sends the same op as the old one. The keybinds merge changes nothing under server except the version line in keel_server.py, and no protocol number.
The client side

The server owns the result. The client picks the key.

  • keymap.gd is static and has no node. It answers which action an event is, and what to print on a badge.
  • main.gd, in _unhandled_input, turns an event into an action and calls the same handlers as before.
  • keybinds_tab.gd captures in its own _input, marks the event handled and sets a flag that main.gd checks, so the key you press for Follow does not also give an order.
What the code looks like in numbers
558lines in keymap.gd, self-test included
385lines in keybinds_tab.gd
147lines in map_pointer.gd
1server file changed by the merge, and only its version line
What the tests prove

What is pinned, and what is not.

The server tests run on every commit through the pre-commit hook, and the client self-test prints ALPHA_OK. On the build we checked, which does not yet hold the keybinds, the unit suite counts 570 tests, alpha_check 38 checks and playtest_check 117 checks, and load_check kept the 95th percentile of its 50 ms step under 25 ms.

Pinned

  • test_waves_launch_on_a_clear_in_order_and_pay_only_after_the_last: the wave order and the single payout.
  • test_pilots_get_a_warning_before_the_ships_appear: the 60 second warning.
  • test_siege_roots_triples_damage_adds_resist_and_blocks_recall_until_it_ends: the Dreadnought's Siege.
  • test_logout_retreats_at_once_and_berths_after_the_berth_seconds: the 15 second berth.
  • test_a_hostile_or_kos_board_carries_one_restitution_offer_and_a_neutral_board_none: the way back from Hostile.
  • The client self-test: the old handler's keys still run the same actions, no two defaults share an input, a drag of 20 px pans by all of it, a click under 6 px moves on release, and one wheel notch zooms by 1.1 and holds the spot under the cursor.

Not pinned, or thin

  • The checks feed synthetic events. None runs on a real mouse, a touchpad, a side button or a non-US keyboard layout.
  • Nothing measures how Smooth zoom feels. The check only shows it settles on its target.
  • Help and the tutorial name the default keys, so after a rebind they will say F while your key is J.
  • A mouse button only reaches the map. Over a panel it does nothing.
  • Incursion ships leave no wrecks, so the four times wreck pay listed for Rift incursions reaches nothing. Our design notes keep that as an open question.
What we learned and what is next

Budgets, tables and questions we could not answer.

A wave needs a tick budgetA Layer 6 wave can hold up to 180 ships, so a launching wave puts at most 24 into the world on each 50 ms tick. A test pins that the incursion waits for them, and load_check has an option that forces an incursion on a layer or a Rift.
A constant is a decisionEvery key was a constant in code, so every rebinding wish was a code change. Now there is one table and a rule that new keys go in it.
One report, several readingsThe code could not tell us what a funky scroll button meant. One reading had a real fault, the ignored wheel factor. For the rest we gave options: a full drag rebind, three zoom speeds, Invert wheel and Smooth zoom. We did not ask the tester which one it was.

Where we would push next

  • Hear how the Keybinds tab feels on real hardware, and fix what it gets wrong.
  • Publish the Controls help after the new client is out, so nobody reads about a tab they do not have.
  • Decide whether Rift incursion ships should leave wrecks. That is a design question for after 0.5.3.
  • We are open to suggestions on handling a dropped connection better. Tell us in the ideas channel.

One open question on the keys: do you want a second binding for an action, or key combinations? Today there is one binding for each action and no combinations.

Further reading

  • Incursions: “Three waves, one warning”.
  • Rifts and storms: “Six Rifts that stay put” and “The map that will not sit still”.
  • Dreadnoughts, Titans and charters: “Building a Dreadnought”, “Lighting a beacon” and “Charters and their structures”.
  • Fleet and combat: “One fleet, four wings” and “How a shot lands”.
  • Factions and the economy: “Three factions, one loop”, “Marks, Notches, and Salt” and “From ore to hull”.
  • The wire and the art: “One server decides” and “Art by script, colour by one file”.
  • Reports: “Reports, client and Discord”.
Join the open alpha

Tell us what the update did to your evening.

Keel is free to play on PC, and the open alpha is where this update lives. Find us in the Keel Discord, tell us what the update did to your evening, and file a report from inside the game when something looks wrong.

Players whose reports become fixes are credited in game. When 0.5.3.1 is out, rebind the one key you always misclick, and tell us what the tab got wrong.