Skip to content
Quadstronaut edited this page Jul 28, 2026 · 3 revisions

ED-AFK

An experiment in AI-driven workflows and how well they can read, interpret, and act on an external data source in real time. Elite Dangerous: Odyssey is the test fixture, not the subject — it earns the role by emitting one of the cleanest machine-readable data feeds of any consumer application. The shippable tool, ed-autojump, drives the keyboard to fly a plotted hyperspace route unattended, recovering from the things that go wrong along the way.

Caution

Automating the live Elite Dangerous service violates its Terms of Service — do not do it. This repository is provided for LEARNING PURPOSES ONLY: a study of event-driven control, fail-closed safety, and data-as-config against a structured external log feed. Not endorsed by or affiliated with Frontier Developments.

This is not hypothetical. Accounts used to develop and test this project have been actioned by Frontier: 2 confirmed bans, and 2 further accounts suspected. If you run this on an account you care about, expect to lose that account.

Source: https://github.com/Quadstronaut/ED-AFK


At a glance

Platform Windows 10/11 (PC Elite Dangerous: Odyssey)
Language Python 3.11+
Status Alpha — the jump loop works well; exploration, combat and trading do not (see below)
License (repo root) MIT
License (ed-autojump distribution) AGPL-3.0-or-later (bundled compass model weights)
Shippable tool ed-autojump

What it does

The engine watches the game's live data feed, decides what state the world is in, and runs the procedure that matches. For the Elite Dangerous fixture it flies a repetitive multi-jump loop and recovers from the things that go wrong:

  • Arrival — throttle to zero, optionally scoop fuel at a scoopable star, honk the discovery scanner, lock the next route hop, clear the geometry, orient (nav-compass coarse + mouse-widget fine), and jump.
  • Traversal — the steady-state A→B hop: orbit-settle → lock next hop → orient → charge-aware engage_jump_clearance.
  • Smack recovery — a star-smack (a SupercruiseExit dropped inside a body's exclusion zone) pitches the star off-screen, re-charges supercruise, rides the world-space escape-vector marker back out, and rejoins the loop.
  • Docking / route completion — at a route-final station it docks (SC-assist → close to <7.5 km → request docking → station-services macro); at a route-final system it parks on the star.
  • Connection-error recovery — a server drop raises a CONNECTION ERROR modal with no journal event; the CV watcher clears it, re-enters the game in Solo (automatons can't play Open), and re-plots the saved route from the galaxy map.

A real-time scene monitor preempts the running procedure mid-flight on a fresh FSDJump, a star-smack, or the connection-error modal. A never-strand re-dispatch driver re-classifies from live state whenever a procedure aborts, and a heat-sink watchdog daemon runs alongside — so the bot rarely dead-ends.

What actually works

Stated plainly, because "alpha" covers too much ground. The jump loop is the finished part. Everything else ranges from partially validated to not built.

Subsystem State
A→B jump loop — arrival, traversal, orient, jump, scoop, honk Works, and works well. Live-validated over hundreds of consecutive jumps, including a cross-galaxy run toward Colonia and a ~24h run on stream.
Real-time recovery — star-smack, connection-error, FSD malfunction, never-strand re-dispatch ✅ Exercised live alongside the jump loop; the rarer branches see less traffic.
Docking / route completion 🟡 Under live validation. Works, with open edges that can occasionally strand a run.
In-system body toured-explore Does not work. Every body timed out at 120s with no AutoScan — the ship never flew to it. Disabled in config; pulled from the launcher menu in July 2026.
Combated-combat Not implemented. Phase-1 scaffold; registers nothing.
Tradinged-trading Not implemented. Phase-1 scaffold; registers nothing.

The offline unit + replay suite covers the engine, routing, step library, and CV — but offline green says nothing about the ❌ rows, which fail (or don't exist) at the point where they meet the live game.

Note

Further live testing is currently blocked — the accounts used to develop this were banned. The ❌ rows stay exactly as they are until that changes.


Perception: the CV/OCR suite

ed-vision turns screen frames into measurements (it sends no keys). The engine leans on it wherever the journal is blind:

Read Used for
Nav-compass cyan-dot orient (coarse) + mouse widget-ring fine align Point the ship at the next hop before firing the FSD
SC-assist center-HUD prompts (ORBITING / ALIGN WITH TARGET / ALIGN WITH ESCAPE VECTOR / FSD-SCO-MALFUNCTIONED) Confirm arrival, detect off-target, drive smack recovery
Nav-panel OCR (row-0 distance in Ls, first-unexplored body, station-name row, detail-page button, column-0 star-vs-station icon) Target selection and route-complete dock-vs-park routing
Right-side target-panel docking distance (km) The <7.5 km docking-request gate (fails closed)
World-space escape-vector sky marker · sun-brightness star-ahead probe Smack recovery and obstruction handling
CONNECTION ERROR modal detector Server-drop recovery

Engine = Windows WinRT OCR + OpenCV, with an optional bundled compass ONNX model. When [vision].enabled and the region is calibrated, orientation is live; otherwise the bot fails closed and never throttles forward blind.

Overlay: with [overlay].enabled, EDMCOverlay shows in-game status text (procedure / step / journal event). An optional CV-debug layer ([overlay].cv_debug, the launcher VISION toggle) flashes a labeled box wherever each CV/OCR read looks.


How it's put together

A layered, six-package Python workspace under projects/. The dependency direction is the load-bearing fact.

Edge convention: A --> B means "A depends on B" — the arrow points from the dependent package to the one it depends on.

flowchart TD
    autojump[ed-autojump<br/>shippable tool + TOML procedures<br/>WORKING] --> core[ed-core<br/>the engine]
    explore[ed-explore<br/>in-system exploration<br/>NON-FUNCTIONAL] --> core
    combat[ed-combat<br/>Phase-1 scaffold<br/>NOT IMPLEMENTED] --> core
    trading[ed-trading<br/>Phase-1 scaffold<br/>NOT IMPLEMENTED] --> core
    core --> vision[ed-vision<br/>pure perception leaf]
Loading
Package Role
ed-core The engine: dispatcher, interpreter, step registry, boot/scene determination, the real-time scene monitor, and the shared flight primitives every domain reuses.
ed-vision Pure perception leaf: frames in, measurements out. Sends no keys; depends on nothing else in the workspace.
ed-autojump The one shippable tool (AGPL-3.0-or-later) plus the editable TOML procedures. ✅ the working part.
ed-explore In-system body-tour exploration. ❌ non-functional — the tour never completes a body in live testing.
ed-combat Phase-1 scaffold — registers nothing yet. ❌
ed-trading Phase-1 scaffold — registers nothing yet. ❌

The runtime flow

Readers feed a dispatcher; the dispatcher selects a procedure and fires real-time preempts; the interpreter runs that procedure's ordered TOML steps and fails closed; each step calls exactly one tested function that sends DirectInput keystrokes to the game.

flowchart LR
    journal[Player Journal tail] --> dispatcher
    status[Status.json reader] --> dispatcher
    navroute[NavRoute.json reader] --> dispatcher
    cv[CV/OCR perception<br/>compass · widget · HUD · nav panel] --> dispatcher
    dispatcher{{Dispatcher<br/>event→procedure + real-time preempts}} --> interpreter
    interpreter[Interpreter<br/>runs ordered steps, fails closed] --> steps[Step library<br/>one function per action]
    steps --> keys[DirectInput keys]
    keys --> game([Elite Dangerous])
    procs[(procedures/*.toml<br/>editable step lists)] -.-> interpreter
Loading

The 11 procedures (startup, arrival, traversal, smack_recovery, exploration, sc_resume, dock, dock_resume, route_complete_park, honk, connection_recovery) are each a *.toml under projects/ed-autojump/procedures/. Dropping a *.toml in that directory is the registry wiring — tune the bot by editing data, not code. The loader validates each procedure at startup and refuses to run on an unknown action, an unbound key, or a bad skip_to/loop_to/retry_anchor reference.

Important

Fail-closed contract. Any step marked required = true aborts the procedure if it fails — no later steps run. The bot never throttles forward and never fires the FSD unless alignment is positively confirmed. When it can't confirm, it stops rather than guessing.


Licensing

  • Repository root: MIT — see LICENSE.
  • ed-autojump distribution: AGPL-3.0-or-later — see projects/ed-autojump/LICENSE.

The AGPL is viral over the combined work: the ed-autojump distribution ships the nav-compass detection model whose Ultralytics weights (compass.onnx / compass.pt, under projects/ed-vision/src/ed_vision/model/) are AGPL-3.0, so the distribution that bundles those weights carries AGPL-3.0-or-later obligations. If you do not ship the bundled model, the OpenCV fallback backend needs no weights and that obligation does not attach. Full third-party attribution chain in THIRD_PARTY_NOTICES.md.


Wiki pages

  • Installation — workspace editable installs, the bundled binds preset, compass + overlay calibration, [vision].enabled.
  • Usage — plot a route → launch.ps1 → Jump; Monitor-Only; the scenes it flies; the overlay.

Clone this wiki locally