Kepler Scripts
Kepler runs .ank scripts: small programs you write that drive your account the way you would by hand, but without you.
A script is for when the workers are not enough. Brain builds, Farming farms the inactives, Expeditions go out, but if you want to "recall my fleet when a specific player logs in", "send a Discord message as soon as my debris goes past a million", or "sweep three galaxies and note what I find there", then a script is what you need.
This reference describes 325 functions and 147 values, as the engine actually exposes them. It is checked against the program, not against an intention: every signature below is the one your script will encounter.
Where you write them, where they run
Open your bot, Scripts page. The + New button creates a file, the console below shows what it writes, and the Start, Pause, Resume and Stop buttons govern its life.
A script runs in its own thread, with its own environment. It cannot bring the bot down: an error stops the script itself, and the reason appears in the console. Tick run at startup to have it start again on its own at launch.
While you play yourself in the built-in browser, in manual mode, your scripts stop sending anything to the game. Each one stops on its first request: a function that asks the game for a page, a method of a celestial such as p.GetShips(), an action, TriggerFleetSave, and even PauseBot or LogOut, which would close your session. The console says so once, and the script picks up from the same line when the mode switches off, with its variables intact. Every script waits, including the ones you start by hand from the editor: a script that talks to the game while you play can change the planet under your fingers, wherever it was started from.
What does not go to the game carries on: Print, storage, calculations, reads of what the bot already holds in memory (GetCachedPlanets, Distance, IsLoggedIn...), CronExec or IntervalExec tasks that do nothing else, and HttpRequest or FetchURL to a site other than the game, a webhook for instance. Aimed at the game server or a Gameforge site, those two wait like everything else. The bot's settings go through too, since they ask nothing of the game: StartWorker, StopWorker, ClearAllConstructionQueues or AbortAllFarmingSessions. The workers, suspended during the mode, take them into account when it ends. Two more exceptions: flight time (FlightTime) asks the game about the target, so it waits; and a cargo, speed or price calculation also waits as long as the bot does not have your research, your lifeform bonuses or your alliance class in memory. It usually reads them in its first rounds; the alliance class, only when it needs it.
Waits count the time you spend playing: a SleepUntil("03:00:00") still wakes at three, and if the next line talks to the game, that line waits for the mode to end. A task held on a request runs once when the mode ends, not once for every time it was missed. The calls one script was holding go out one at a time, about a second apart; two different scripts each go their own way.
Stop cuts the wait at once, and the held call does not go out. The wait belongs to the script making the call, and its console is the one that says so, whether the call is written in the script, in one of its tasks, in a !global.ank function, or on a celestial another script kept in a shared variable. A go belongs to the script that started it, whether it starts from the script itself, from one of its tasks, from a !global.ank function or from another go, and for as long as it runs, whatever other scripts and other accounts do in the meantime. A task set up by a !global.ank function (ExecIn, IntervalExec, CronExec...) likewise belongs to the script that calls the function, from a go included: it stops with that script, and its pause and its errors are written to that script's console.
Only one exception remains, and it is deliberate: what the top level of !global.ank starts belongs to it, even when a script reloads it (see below).
Stopping the account also releases the call without letting it go out. A script stopped during the mode no longer touches the game, not even from OnExit: those calls return an error, and the console says so. The rest of OnExit runs as usual. Only the account whose browser you are holding is affected.
One thing does not wait: loading !global.ank. When you save it, when you start it from the script list, when a script reloads it with StartScript("!global.ank"), or when the account starts, its top level runs straight away, game calls included, even during manual mode. What it starts at that level, tasks and go alike, belongs to !global.ank, even when a script reloaded it: during the mode it waits on behalf of !global.ank, and stopping that script does not touch it. The functions it defines wait like everything else when a script calls them.
Three names are special:
| File | When it runs |
|---|---|
!global.ank | At startup, in the parent environment. What it defines is visible to every other script. |
!sleep.ank | At sleep time, while the session is still open. This is the moment to bring a fleet home. |
!wake.ank | At wake time, once the session is open again. |
The language
Scripts are written in anko, a language whose syntax looks a lot like Go, only looser: no type declarations, no compilation, and a loop is written the way you expect.
for i = 0; i < 5; i++ {
Print("pass " + i)
SleepSec(2)
}
A line cannot be broken just anywhere
A long call breaks after a comma, never after the opening bracket:
secs, fuel = FlightTime(origin,
target, HUNDRED_PERCENT, fleet, ATTACK) // ✓
secs, fuel = FlightTime(
origin, target, HUNDRED_PERCENT, fleet, ATTACK) ✗ syntax error
That is the most natural layout in Go, and anko refuses it. Its own message says only "syntax error"; the bot adds the line, the column and the offending text:
line 3, column 25: syntax error
secs, fuel = FlightTime(
Runtime errors say it too. A misspelled field, one argument too many, a value that is not the type you thought: none of them show on reading, and all of them are pointed at down to the line.
line 3, column 5: no member named 'ComputerTechnology' for struct
computer = techs.ComputerTechnology
Only a requested stop goes undecorated: there is no defect to look for.
These packages can be imported: bytes, encoding/json, errors, fmt, io/ioutil, math, math/rand, net/http, net/url, regexp, sort, strconv, strings, sync, time.
strings = import("strings")
if strings.Contains(name, "Xylo") { Print("there he is") }
The two pitfalls to know before you write a line
Both come from the same anko rule, and they raise no error at all. A script that falls into them does not crash: it does something other than what it says. This is by far the leading cause of scripts that "do not work".
1. A function that returns several values returns them in a slice
In Go, GetCelestials() returns two things: the list and an error. Anko has no such notion: it hands them back to you packed together.
c = GetCelestials() // ✗ c holds [<list> <nil>], not the list
Print(len(c)) // prints 2, always
c, err = GetCelestials() // ✓ c holds the list, err holds nil
Print(len(c)) // prints 24
The classic symptom: index must be a number, or a value that stubbornly reads 2. Every function in this reference states how many values it returns; take exactly that many.
2. Taking too many targets raises nothing, and that is worse
// ConstructionsBeingBuilt returns FOUR values, not five.
bid, bsec, rid, rsec, err = ConstructionsBeingBuilt(id) // ✗
if err != nil { ... } // "undefined symbol 'err'"... or worse
Anko does not report the extra target: the variable simply stays undefined. And if an earlier block had left an err lying around, your test is checking the error from another call, which you cannot catch by reading the code.
So the rule is simple: count the return values, no more, no fewer.
The implementation is under way, and here is where it stands
Completing this API is our priority, and not much is left.
This page states today's exact position, because a reference that promised what does not exist yet would cost you hours on symbols you cannot find. What follows is measured against the program, not announced.
What is covered is the whole heart of the job: reading the account, the celestials, the resources, the technologies; sending, following and recalling fleets; reading the galaxy, a single position, the highscore; building, tearing down, cancelling; driving the workers and composing their work; finding where to send a fleet for the night; storing values between passes; waiting, scheduling, being woken by an attack, a message, a fleet or a target that moves; writing to the log, alerting on Discord or Telegram.
What is missing, and why:
| What is missing | Why |
|---|---|
| The player marketplace | It no longer exists. Gameforge removed it from the game, and the library itself stopped following it above v7. OfferSellMarketplace, OfferBuyMarketplace, BuyMarketplace and CollectAllMarketplaceMessages have therefore been removed: they would have reported success without doing anything, which is worse than not shipping them. |
| The Telegram keyboards | Interactive replies and OnTelegramMessageReceivedCh require the bot to listen to Telegram continuously, which it does not: it writes there. SendTelegram works. |
OnRepatriateCompletedCh | The bot can say a fleet has left, not that it has arrived. A channel named "completed" that fired on departure would lie. OnFleetCh says what it knows, under its true name. |
SendMail | The bot has no SMTP settings: giving it some is a feature in its own right, not a line of API. Discord and Telegram cover the need. |
UnsafePhalanx | It scans without checking range, and the reference documentation warns about it itself: an out-of-range coordinate gets the account banned automatically, ten minutes the first time. Phalanx checks, and that is the only difference between them. We do not ship the one that does not check. |
| Files | TempFile, NewSheet, ListTempFiles and their siblings write to disk. A hosted client's scripts run on our machines: opening the filesystem to them is an architecture decision, not a line of API. Put/Get cover the persistence a script needs. |
| Other bots | AllBots, OwnBots, BotsCount, GetBotByID, StartRemoteScript, StopRemoteScript. A Kepler script sees its own account, and only that. Opening one account to another's scripts is a question of isolation before it is a question of API: two customers share our machines. |
| Ninja's own settings | EnableNJA, DisableNJA, IsNJAEnabled, SkipSuspiciousLoginWait, GetSlot, NewSheet. They drive mechanisms of their tool that have no equivalent here: naming them would not bring into being what they command. |
CalcFastCargoPF and IdealExpeditionCargoShips | Two computations whose exact rule is not stated in the reference documentation, only implied by its examples. CalcPreferredCargo covers the first need while saying what it does. |
ExecInCh and company | Nothing: they all exist now. |
What this means for you. A copied script that touches one of these families stops on undefined symbol 'X'. It is a clean error, at runtime, naming the missing symbol: you will know immediately which one. It breaks nothing else, and the rest of the script will not have run.
Tell us what you are missing. This list is emptying, and the order in which it empties depends on you: a function someone asks for jumps ahead of the others.
This page is updated with every release. The alphabetical index, in the left column, is the one place that cannot be wrong: it is built from the program itself, and a test refuses publication if it drifts from it.
What sets Kepler apart from Ninja
The API follows Ninja's, so that your existing scripts run without modification. Three deliberate differences:
SleepRandMincounts minutes, as its name says. If you come from a script that passed it milliseconds, useSleepRandMs.GetHighscoreno longer works in version 13 of the game: the page it read has changed. UseHighscoreData, which queries the game's API, returns the whole highscore at once and will not break at the next version.- The functions specific to Ninja's offering (
LICENSE_*,IS_CLOUD,VERSION) exist with our values, so that a script that reads them does not stop.
Writing your scripts with an AI
A coding assistant (Claude, ChatGPT, Cursor, Copilot...) can read this reference at the source, one function at a time, through our MCP server. How to connect it: MCP (AI scripting).
The reference, by family
| Family | What you find there |
|---|---|
| Output, log and storage | Print, the log levels, Put/Get, Discord and Telegram |
| Time and waiting | the Sleep family, schedules, durations |
| Scheduling | ExecIn, ExecAt, ExecInCh, ExecAtCh, IntervalExec, CronExec, RangeCronExec, RemoveCron |
| Celestials and resources | planets, moons, mines, buildings, technologies |
| Fleets, flights and combat | dispatches, durations, cargo, combat power |
| Driving the workers | StartBrain, StopFarmingBot, IsWorkerRunning, ListWorkers, AddHunterTarget |
| Account, galaxy, players and messages | system readings, highscore, mail |
| Toolbox | maths, strings, JSON, base64, ids |
| Constants and values | the id tables, the licence, the server |
| Ten scripts that work | whole scripts, to paste as they are |