How to use it
Three steps to knowing exactly what leaves your machine.
1 Read the destinations. There is one row per place.
Open the Privacy page and read each destination.
Each row names what is sent, to whom, and whether it is on right now.
2 Turn off anything you do not want.
Turn off Let D47 search the web and Check for updates at startup, and set the model to none.
Nothing leaves the machine.
3 Check what it actually did.
Say "what have you sent anywhere".
The Log File reading lists each request with its destination.
! The one that stops people.
Speak as normal; there is nothing to set for the microphone.
Whisper transcribes your speech on this machine, and the audio never leaves it.
Exactly what Directive 47 sends off this machine, to whom, and whether it is sending it right now.
Ask for it
“what are you sending” “what leaves this machine”
What you get
2 of 4 destinations are active right now.
Language model → Anthropic
Anthropic is selected. Your question, D47's reply so far, the guardrails, the persona and your backstory text, and the game state D47 assembled from your journal — system, body, station and docking state — are sent on every turn the model answers. Journal files themselves are never uploaded.
Update check → api.github.com, and github.com if you accept an update
One request for the latest release tag at startup. Nothing about you goes with it — no key, no journal content, and no identifier beyond the request itself. Accepting an offered update downloads that release from github.com and replaces D47 with it; nothing is downloaded unless you ask for it.
Diagnostics and logs → nothing sent
Logs are written beside the executable and are not uploaded.
Journal files → nothing sent
Your journal is read from disk and never uploaded. Facts drawn from it — system, body, station — can reach the model as game state when one is configured; see the language model row.
The answer is computed from your settings as they stand at that moment. It is not a description of what Directive 47 could do in general, and it cannot go stale the way a page like this one can — which is why the answer is worth more than the page.
The destinations
Language model — the only one that receives anything from your gameplay. What goes: your
question, the conversation so far, the guardrails, the persona, your backstory text, and the game
state assembled from your journal. The lines D47 says in character without being asked — ambient
remarks, the greeting, a core’s first words — carry your character sheet too, and about one ambient
remark in four carries your backstory; the carrier’s captain and tower get neither. With
personality on, the NPC lines Elite itself wrote go too, to be said in other words — a pirate’s
threat, a station’s docking notice; a message another player typed never does. What does
not: journal files, your key, or anything about your machine. Inactive when the provider is none, and also when a provider that needs a key is
chosen and has none stored — selected-but-inert sends nothing.
And inactive when the endpoint is on this machine. If you have pointed the OpenAI-compatible provider at a loopback address, this row says that nothing leaves the machine at all and names the address so you can check it. That is the first time the accurate answer to what is leaving has been nothing — and it is a property of that address in these settings right now, not a promise about Directive 47. The judgement is deliberately literal: the address is read, never resolved, so a hostname that happens to point at your machine today is treated as remote and disclosed in full. Being wrong in that direction is the only safe way to be wrong here.
Web search — the same host as the language model, doing something different. When the
web search row is on and a question needs current
information, the language-model endpoint runs the search and reads the pages — your provider, or
xAI when the endpoint is https://api.x.ai/v1, in which case the row names api.x.ai; Directive 47 only ever sees the
reply. It is listed separately even though it adds no new address, because “your provider gets
your question” and “your provider will go and fetch pages about it” are not the same disclosure,
and organising this list by host rather than by what is done would have hidden the second behind
the first. Off by default, and inactive whenever no model is usable — and inactive on an
endpoint that offers no search, which a custom endpoint generally is. Until v0.26.1 that last
case read as active and went on to describe pages being fetched and a penny being billed, none of
which could happen there. Claiming a transfer that cannot occur is the safe direction to be wrong
in and is still wrong: a disclosure is only worth reading if it describes this machine, these
settings, right now.
Screen pictures — the language-model endpoint again. When the look at the screen row is on and you ask about something on screen, one JPEG of Elite’s window, or of the headset’s left eye while Elite is running in VR, goes to your provider with that question. Anything on screen goes with it, including comms, other Commanders’ names and Directive 47’s own panel. It is never saved, and a later turn does not send it again. Off by default. Inactive when no model is usable or the model in use does not read pictures, and the picture does not leave this machine when the endpoint is a loopback address.
BGS tick — tick.infomancer.uk, every ten minutes while Elite runs, for the time of the last
background simulation tick. Nothing about you goes with it: no key, no Commander name, no position
and nothing from your journal. It is reached over plain HTTP, because the host answers on nothing
else, so anyone on the network path can see that d47 asked and could change the
time that comes back; d47 keeps only that time, and only when it falls in a plausible window.
BGS tick time under Outside sources in Settings (Galaxy search) turns it on; it is off
by default.
GalNet news — cms.zaonce.net, Frontier’s GalNet server, for the newest articles at startup and every
hour while d47 runs, and for up to two years of older articles the first time. Nothing about you goes with
it: no key, no Commander name and nothing from your journal. The articles are kept in data\galnet.json
on this PC. GalNet news under Outside sources in Settings (Galaxy search) turns
it on; it is off by default. With it off, nothing is requested and articles already kept stay on this PC.
Server status — ed-server-status.orerve.net, Frontier’s server status page, once when d47 starts and then
every ten minutes while the servers are up and every minute while they are not, whether or not Elite is
running. Nothing about you goes with it: no key, no Commander name and nothing from your journal. Server
status under Outside sources in Settings (Galaxy search) turns it on; it is off by
default. With it off, nothing is requested.
Signal index — github.com, which redirects to GitHub’s asset storage, from the signals-1
release. When you search for a signal and the copy in data\signals is missing or more than 20
hours old, D47 downloads the daily index of signals Commanders have uploaded to EDDN: one file,
several megabytes. A download that fails is tried again on a later search, no sooner than an hour
after. Nothing about you goes with it: no position, no key, no Commander name, no identifier and
nothing from your journal, and the search itself happens on this machine.
Signal index under Outside sources in Settings (Galaxy search) turns it
on; it is off by default. With it off, a signal search answers from your own scans alone.
EDDN — eddn.edcd.io. When you open a station’s commodity market, D47 sends its prices,
with the station, its system, the game’s version and a random number made on this PC for your Commander.
Opening its outfitting or shipyard sends the names of the modules and ships it sells.
The signals and body counts your scanner finds go too, as do codex discoveries, settlements you
approach, nav beacon scans and routes you plot; a route is where you intend to go.
Your Commander name, Frontier ID, credits, cargo and ship do not go, and nothing from journals read
before D47 started is sent. Share with EDDN under Sharing in Settings (Galaxy search)
turns it on; it is off by default, and the model cannot turn it on.
Update check — api.github.com once at startup, for the latest release tag. Pressing
Update now adds one more transfer: the build itself, from GitHub’s release downloads, which
redirect to their asset storage — so the bytes arrive from objects.githubusercontent.com. That
is a download rather than an upload, nothing about you goes with it, and it only happens when you
press the button. Directive 47 refuses any URL that is not an asset on a release of this
repository.
The download is checked against the d47.zip.sha256 published beside it, and deleted rather than
unpacked if it does not match. That catches a truncated transfer or a mirror serving something else.
It is not a signature: the hash and the bytes come from the same server, so it cannot detect a
compromised GitHub. The same caveat applies to the speech models.
Model updates — raw.githubusercontent.com, once at startup and every 24
hours, for the published list of models, their defaults and their prices. Nothing about you goes with
it: no key, no journal content and no identifier beyond the request itself. Fetch model updates
in the Language model settings turns it off.
Stock stories — github.com, which redirects to GitHub’s asset storage, from the stories-1
release. D47 asks for the list of stock stories and the cast pictures it shows the first time the
Stories page opens in a session, and for a story’s hidden layer and every cast picture when you pick
it, and keeps them in data\stories.
Nothing about you goes with it: no key, no Commander name, no position and nothing from your journal.
Download stock stories in the Stories settings turns it off, and the Stories page then lists
only stories already on disk.
Chatterbox voices — github.com, which redirects to GitHub’s asset storage, from the
chatterbox-voices-1 release. Twelve Chatterbox voices come with D47. Any other is asked for the
first time you pick it, press Play on it, or a line is due in it: one request for that one clip,
naming the voice’s id and nothing else. The clip is kept in data\voices\chatterbox and used only
while its size and SHA-256 match the list that came with D47. Active while Chatterbox speaks for any
slot or story character.
Story ratings — d47-ratings.dseelinger.workers.dev. D47 asks for every stock story’s average
rating the first time the Stories page opens in a session, and sends a vote when you rate a story you
have picked or take your rating back. A vote carries the story, your stars and a random number made on
this PC for your Commander, which is not your donation identifier. Nothing else goes with it: no
Frontier ID, no Commander name, no key, no position and nothing from your journal. Story ratings in
the Stories settings turns it off, and nothing is then fetched or sent.
Usage counts {#usage-counts} — d47-usage.dseelinger.workers.dev. One report a day, sent the first
time D47 runs after the day ends in UTC. When the last send was not accepted, the start of D47 also
sends today’s counts so far, and the rest of the day goes after the day ends: for each tool used that day, its name, whether you or the
language model asked for it, and how many times. Nothing else goes with it: no identifier of any kind,
nothing you said, no Frontier ID, no Commander name, no key, no position and nothing from your journal.
The counts not yet sent are in data\usage-counts.json. Usage counts in the Privacy and egress
settings turns it off, and the counts not yet sent are then deleted.
Speech recognition — silent while the hearing provider is This
computer. With Groq, OpenAI, Deepgram or ElevenLabs selected, api.groq.com, api.openai.com,
api.deepgram.com or api.elevenlabs.io receives the audio of
every utterance Directive 47 transcribes, your API key, and the names from your journal used to
recognise proper nouns. Hands free, that is every stretch judged to be speech, addressed to Directive
47 or not. No journal files, game state or other keys go with it.
Diagnostics and logs — never active. Logs are written to data/logs/ beside the executable
and are not uploaded.
Journal files — never active. Journals are read from disk and never uploaded. Facts drawn from them can reach the model as game state, which is disclosed under the language model above rather than twice.
A voice that is not a destination either
Since Phase 59 there is a speech provider that sends nothing: Kokoro runs on this computer. Its
model is downloaded once from huggingface.co — which is a destination, and is listed as one for
as long as a download is happening — and after that the voice needs no network at all.
That is the whole reason it exists. Every other provider, free ones included, receives the text Directive 47 speaks, and that includes re-voiced in-game messages written by other players. With Kokoro selected for those slots, nobody’s words leave your machine to be spoken.
Shared excerpts and journal histories — the newest destination, and the one that reverses a sentence Directive 47 used to say about itself. Donation shipped with nowhere to send: an excerpt was copied and pasted by a human, and a comment in the code said there is no backend and there is not going to be one. There is one now, argued in #175, because the requirement changed underneath that sentence — a donated journal history is 32.5 MB compressed followed by about 85 KB a day, and no manual route carries that or can be reached by a stranger.
It is not like usage counts either. Directive 47 sends one thing without being asked: once a day (or, after a send that was not accepted, a part day at startup), how many times each tool was used, with no identifier and nothing from your journal (Usage counts). It is on by default and Usage counts in Privacy settings turns it off. A donation is different in kind: it sends nothing at all until you have read a full description of it and pressed a button, every time — no standing consent, nothing remembered, no automatic upload — and the row above says so.
The press is the switch. The address ships in the build — Directive 47’s own store, named in full by the disclosure row — and the send buttons are simply there. What was never true and still is not: nothing uploads on its own. Every send is one deliberate press over a payload or a report you just read, no standing consent, nothing remembered. It read differently until 2026-08-31, when the paste-an-address row was retired: the address was the switch only because the row asked every installation for a URL only the project knew.
What is stored, and for how long. An incident excerpt is deleted 30 days after it arrives, by a rule on the store rather than by anybody remembering to. It may well go sooner — there is no reason to keep one past the defect it was cut for — but that is somebody deleting it and not a rule, so the thirty days is what is promised. A donated journal history is kept indefinitely, on purpose: it is a regression case, and one that expires stops being one. Either goes on request, and either is a single delete.
Directive 47 keeps its own copy of what it sent. In data\donations, beside the executable:
the exact bytes, and their hash. While a human was the transport, what is shown is what leaves
was something you could see; an upload turns it into a claim about code, and the receipt turns it
back into something you can test with certutil -hashfile. It is also what a deletion request
quotes.
Your donations are grouped, and that is a reversal too
Directive 47 used to say that two donations from the same Commander could not be joined. That was true, and it is not any more.
A journal history you add to has to be recognisable as the same history, or it is not an accumulation — it is a pile of unrelated blobs. So a send carries a random number identifying this installation: made on this machine the first time you donate and never before, not derived from your Commander name, your Frontier ID or anything about your computer, and used for donations and nothing else. The stand-in names inside a donation are unchanged — still per-donation, still by field list.
The claim is now weaker and still worth stating: donations from one installation accumulate under a random token that identifies an install, not a person. You read it here, and in the Help improve D47 page, before the first send rather than after (#176).
Withdrawing is one press, and it is no harder than consenting was. Forget it, and delete
what was sent asks the store to delete every donation ever made under this installation’s
identifier, then forgets the identifier here and writes a record of what went into
data\donations. You do not have to post anywhere or ask anybody, which is the point: a
withdrawal that is harder than the consent was is a defect in the consent
(#167).
If the store cannot be reached, the identifier is kept and the row says so — it is the only handle anyone has on what was sent, so losing it would strand the data rather than delete it. Press again when the connection is back.
What is not deleted is what was decided because of it. A defect a donation found stays fixed, the release that carried the fix stays released, and the changelog line naming it stays written. Those are the product of having read the data once; they are not the data, and a published release never moves. Neither is anything you copied or saved yourself and took somewhere else — anything posted publicly can be archived beyond anyone’s reach.
Two things are accepted rather than solved, and both are said here rather than discovered.
A thirteen-month history is easier to re-identify than a ten-minute excerpt — more surface, more
distinctive routes, more chance one rare system pins the set to a person — and pseudonymised was
never anonymous. And a second PC, a fresh install with no restore, or a cleared data\ folder
starts a second pile under a new number, with nothing saying the two halves are one history. The
only fix for that would be a token derived from your machine, which is the identifier this whole
design refuses.
Your microphone is not a destination, unless you make it one
It is worth saying plainly, because Phase 13 added hands-free listening and “the microphone is open all the time” is a sentence that deserves an answer rather than a shrug.
Out of the box, audio does not leave this machine. Speech becomes words through a model running on your own computer. The one row that changes that is the hearing provider: choose Groq, OpenAI, Deepgram or ElevenLabs and the audio of every utterance goes to it, disclosed under Speech recognition above. Audio is not written to disk either way — it lives in a half-second ring buffer and is overwritten.
What the hands-free settings change is what gets kept for long enough to transcribe. In push-to-talk that is only what you held the key for; in the two hands-free settings it is every stretch of speech in the room, and in wake-word mode the ones that were not addressed to Directive 47 are discarded without reaching the transcript, the panel or the log. Both are off out of the box, the row that turns them on is unreachable by the model, and the panel shows the microphone’s state the whole time it is open — on the desktop and in the headset.
With the local model, the one thing that crosses the network for listening is the speech model
file itself, fetched once from huggingface.co. It is listed on the settings surface for as long as
a model is selected and the hearing provider is this computer.
Settings
Check for updates at startup
One request to api.github.com at startup. Off means Directive 47 makes no network call of its
own, and offers no update to install.
“stop checking for updates” / “turn off update checks” “start checking for updates” / “turn on update checks”
The whole sentence has to be the phrase rather than merely contain it. This is the one spoken route that changes a setting, so a sentence that only mentions it gets an answer, not a change.
The model cannot reach this row. It decides whether anything leaves at all, and a model that could switch that back on is a model that could be told to by text it read in an in-game message.
Where donations are sent
The address ships in the build: Directive 47’s own store, behind a Cloudflare Worker that is the
only thing able to write to the bucket — there is no storage credential anywhere in Directive 47,
and the disclosure row above names the address in full. There used to be a settings row here to
paste an address into, and it is gone on the project’s own ruling (2026-08-31): it asked every
installation for the one URL only the project knew, and the switch it doubled as was never the
real guard. The real guard is unchanged — nothing is sent until you press, every time, and
the address travels over https only.
Because the address is compiled in rather than stored, there is nothing here for the model — or anything else — to redirect: changing where a donation goes now means changing the code.
What Directive 47 remembers about you
A read-only summary of the memory store — how many facts are kept, and how many of them you told it yourself — with one button that empties the file.
It empties every Commander in the file, not just the one currently aboard. “Forget me” is not “forget the character I happen to be logged in as”, and a privacy control that left three other characters’ facts on disk would be one that reads as a control and is not.
The button is here rather than in the memory section because this is where you would look for it. There is no spoken phrase for it and no tool that can call it — “forget everything about me” is a sentence a transcriber can produce out of a misheard one, and this is the one action in that feature that cannot be undone.
The disclosure rows
The settings panel carries one row per destination, saying the same things this page does {#egress-recap} {#egress-websearch} {#egress-screen} {#egress-updates} {#egress-modelcatalog} {#egress-diagnostics} {#egress-journal} {#egress-tts} {#egress-stt} {#egress-galaxy} {#egress-colonisationplanner} {#egress-colonisationprogress} {#egress-bgstick} {#egress-galnet} {#egress-serverstatus} {#egress-signalindex} {#egress-eddn} {#egress-models} {#egress-chatterboxvoices} {#egress-notableplaces} {#egress-communitybiology} {#egress-hullart} {#egress-codexpictures} {#egress-codexpublish} {#egress-avatarclips} {#egress-stockstories} {#egress-storyratings} {#egress-usagecounts} {#egress-pictures} {#egress-codexcaptures} {#egress-ownvoice} {#egress-customvoices} {#egress-captainslog} {#egress-screenshots} {#egress-donation} — but computed live from your settings rather than written down once. They are read-only: not something you set, something Directive 47 says, sitting next to the settings that change it.
The tool surface, for contributors
get_data_egress
Lists every destination, whether it is active under the current settings, and what is sent there. Takes no arguments.
{"type":"object","properties":{},"required":[],"additionalProperties":false}
The panel’s disclosure rows and this tool read one list, so neither can drift from the other.