v0.8.7-beta.5 is out · 5 Novsee the release
Browse guides / Privacy policy
DOCS

Privacy policy

docs/privacy.md on GitHub

Aether is self-hosted software. Nothing about you reaches the people who publish it unless you sign in to the edge they run, at auth.onaether.dev and edge.onaether.dev (What an edge stores). This page is the privacy policy for the Aether Android app (package io.aether.android), whether it came from a GitHub release or from Google Play, for the dashboard the app shows, and for that edge. Effective 2026-10-16.

Who publishes it

Aether is published by 3xDevOps, https://github.com/3xDevOps. Questions about this policy go to https://github.com/3xDevOps/Aether/issues. Privacy requests about what the project's edge holds, such as a copy or a deletion, go to team@onaether.dev; deleting your own account needs no request (What an edge stores).

What the app stores on the phone

  • Which mode you chose and, in Tailscale mode, the server name you type on the first screen, in the app's private storage.
  • In Aether Edge mode, the CLI's state, under the app's private files directory in .config/aether/: config.json (the servers you linked), edge-device-key (this phone's SSH private key, mode 0600), edge-tokens.json (the edge's sign-in token for this device, mode 0600) and edge.lock. Beside them, resolv.conf holds the DNS servers of the phone's current network, which the app reads (permission ACCESS_NETWORK_STATE) and rewrites when the network changes. Nothing else the app writes is its own.
  • The WebView's ordinary cache of the dashboard's files (none in Edge mode, which turns it off), and the dashboard's own local record of how you use it. That record holds how the dashboard looks (theme, text size, sidebar width and whether it is collapsed, whether a run's Details panel is open, the embedded Environment terminal's height, terminal font size, line wrapping in Changes, whether single-key shortcuts are on); where you were (the workspace you last opened, whether the sidebar lists only your own runs); the mode you last launched each agent in; which update notices you dismissed, by version; and the onboarding wizard's progress. The dashboard writes these preferences in origin-local aether.ui storage: they are separate for each server origin, including its port. Nothing reads them but the dashboard, and they last until you uninstall the app. Both are private to the app.

In Tailscale mode the app stores no account, password, token, cookie or key: there is no dashboard sign-in, and the phone's Tailscale login identifies it to your server (networking.md). In Edge mode the device key and token above are credentials, kept only on the phone. An app login in the remote development browser is separate server-side state, as described below. Uninstalling the app deletes everything stored on the phone, which in Edge mode includes the device key: the phone then signs in again as a new device and needs approval again where the server requires it. None of it is backed up: the app opts out of Google's cloud backup and of device-to-device transfer (allowBackup=false and data_extraction_rules.xml), so setting up a new phone starts again.

What leaves the phone

  • To your server. In Tailscale mode every request the dashboard makes goes over HTTPS to the server whose name you typed, which you or your team run; in Edge mode the dashboard talks to the gateway on the phone (127.0.0.1), which reaches the server over SSH through the edge (next items). That includes what you type into a terminal, the messages you send an agent, an image you pick from the phone to paste into a terminal, the contents of files you edit in the dashboard, approvals, and the run controls you use. The server keeps them as part of each run's record, on its own disk (install.md); who on your team can see them is in teams.md and security.md. The app refuses a plain http:// address, permits cleartext only for 127.0.0.1 (the Edge mode gateway), and refuses mixed content, so nothing leaves the phone unencrypted.
  • In Edge mode, to the edge and through it. The bundled CLI contacts the edge to sign in, list your servers and relay the SSH connection to the one you linked; the edge holds what What an edge stores lists and cannot read the stream, which is encrypted end to end between the phone and your server. The GitHub sign-in happens in the phone's browser, under GitHub's own policy. While the dashboard is open, the gateway also asks github.com for the newest release's tag, as the next item describes, reusing an answer for an hour, retrying a failed request after five minutes at the soonest, and asking again when it restarts. The CLI resolves host names with plain DNS over port 53 to the active network's DNS servers, bypassing Android Private DNS (DNS-over-TLS), so that network can see which names it looks up.
  • In both modes, to github.com for the newest release. When the app comes to the front, about once an hour, and when you tap Check for updates, the bundled CLI asks github.com for the tag of the newest Aether release, so the app can say an update exists. GitHub sees the phone's IP address and that request, nothing about you or your server. The app downloads nothing itself: you install a release from Google Play, or download its APK in the browser.
  • In Tailscale mode, your identity reaches the server through Tailscale, not through the app. The server asks its own tailscaled which tailnet login owns the connecting device. The app sends no name, email, or identifier of its own. In Edge mode the phone's device key and your edge account identify you instead (edge.md).
  • Your server records you as a member on the app's first request. In Tailscale mode, from that answer it stores your tailnet login, which is an email address, and a display name taken from the part before the @, and writes one log line carrying that login and your device's Tailscale node ID. The record is how your administrator approves you and how your teammates see who did what (teams.md). It is kept by your own server, not by the publisher, and lasts until an administrator removes it.
  • Your teammates see when you are online and what you have open. The dashboard tells the server every 15 seconds that you are there and which workspace you have open, and an open run terminal adds you to that run's Watching list; the other members of that server see both (teams.md). It is not kept as history.
  • Optional GitHub authorization opens GitHub in your external browser. If an administrator chooses Connect GitHub during onboarding or in Settings, that browser visits GitHub to approve the native GitHub CLI's device authorization. GitHub receives the browser's requests under its own policy; the resulting token is kept in the member home on your server, not in the dashboard or Android shell.
  • No app analytics or advertising. The app has no analytics, no crash reporting, no advertising, and no third-party library that talks to a network. WebView Safe Browsing is turned off in the app, so no visited URL, and no hash of one, is sent to Google. A link that leaves the dashboard opens in the phone's browser, under that browser's own policy.

Dashboard requests above go to the server you chose, not to an Aether-operated analytics service. Optional GitHub authorization and the server-side connections described below are separate external requests. Nothing is sold.

Optional GitHub repository access

Connecting GitHub uses the native gh CLI in your member Environment on your own server. Your server contacts GitHub to verify the account, list repositories the account can access (including private collaborator and organization repositories), look up a selected repository, and fetch its selected source branch over HTTPS. GitHub receives these authenticated requests under its own policy. There is no new Aether-operated authorization broker or analytics service, and this connection is separate from signing in to an edge and from an agent's model-provider account.

The native token is stored in homes/<member>/.config/gh/hosts.yml on your server. The server reads it for GitHub API requests and source fetches. A source mirror stores only the authorizing member and numeric GitHub account binding with its source metadata, not a copy of the token. Aether does not send that token to the dashboard, the edge, or other members, or put it in workspace database records, on-disk Git configuration, URLs, or command arguments. It is used in server memory and the fetch child's temporary environment.

This is fetch-only source access, not a read-only token scope: native gh permissions can include broad repository access. Your own agents already have access to your native login in your member home. Imported code is deliberately shared with the workspace's authorized members and runs; the token is not. Repository data remains on your server until the relevant workspace/run data is deleted; removing upstream access does not erase already imported code.

Logout, token expiry or revocation, member removal, or an account switch prevents further refresh with that binding without moving the accepted source revision. Disabling or deleting a source mirror does not delete the native login or revoke authorization at GitHub. To remove the native login and revoke GitHub authorization, see GitHub credentials and signing keys.

Push notifications

Off until you turn on Notify this device when a run needs me in the dashboard's Settings, in a browser or in the dashboard added to a home screen (networking.md). The Android app cannot receive them, so it never registers with a push service; the one thing in this section it does send is the last paragraph's report to your server.

Turning it on makes that browser register with its vendor's push service - Google's for Chrome, Mozilla's for Firefox, Apple's for Safari, Microsoft's for Edge - and hand your server what the service issued: an address for that browser and two keys. Your server stores those three values with your member ID. It removes them when you turn the switch off on that device, when the push service reports the address gone, and when your member record is removed.

When one of your runs starts needing you, or a run your assistant launched or messaged finishes, or needs you and is another member's, your server sends one HTTPS request per subscribed browser to that browser's address. Nothing is sent for a member with no subscribed browser, and nothing is sent to the publisher. The push service receives:

  • The address, which is its own identifier for your browser, and your server's IP address.
  • The notification, encrypted on your server so that only that browser can read it (RFC 8291): the run's title or the first line of its task, one line saying why it needs you, and the run's ID. The push service sees its size, at most 4096 bytes, and when it was sent.
  • A signed token (RFC 8292): the public half of a key your server generated for this purpose, the push service's own address, an expiry, and the fixed contact https://github.com/3xDevOps/Aether. It names neither your server nor you.
  • Delivery settings: a 24-hour time to live, high urgency, and a topic, which is a hash of the run's ID, so that a newer notification for a run replaces an undelivered older one.

The push service relays the message to your browser under its own policy. Send test notification sends the same request with the text Notifications work on this device. and no run.

While you use a dashboard, in any browser, the desktop app or the Android app, it tells your server so at most every 20 seconds. Your server keeps the time of the latest such report in memory, to hold your notifications while you are there. It is not stored, and no other member sees it.

What an edge stores

An edge is the relay and sign-in service that lets a computer running aether reach a server over SSH without Tailscale (edge.md). The Android app uses it only in Edge mode. Whoever runs an edge, the publisher for auth.onaether.dev and edge.onaether.dev, holds the following. The edge cannot read terminal, agent, file or dashboard content: all of it travels inside SSH, which is encrypted end to end between your computer and your server.

What Why Kept
Your GitHub account: an account id the edge assigns, GitHub's user id, your login, verified primary email and display name, and when you last signed in with GitHub To sign you in and to match invitations Until you delete it on the edge's Account page, or its operator deletes it with aether-edge accounts delete
Each signed-in device: its label (the machine's host name unless you chose one), its public key, a hash of its token, when it signed in and was last used To let that device connect Until you revoke it with aether logout or the edge's Devices page
Browser sessions at the edge: a hash of the cookie To keep you signed in there 30 days after last use
A pending sign-in from aether login: the device label, public key and the IP address it started from To show you on the confirmation page where the sign-in came from Until the device collects its token or is denied; an expired one (after 10 minutes) until the next sign-in starts
Each server you claim: its id, its host name, the access policy it announces, you as its owner To route connections and show you your servers Until the owner removes it, or the edge's operator removes or blocks it. Deleting your account removes you as its owner
Each server the edge let your account connect to: its id and your GitHub user id To tell every server that may hold your identity when you delete your account Until you delete your account
A deletion owed to a server that was offline when you deleted your account: that server's id and your GitHub user id To tell that server to remove your identity Until it is sent, when the server next connects; at most 1000 per server
Each server's directory: the GitHub user id, login, email and role of its members and open invitations To refuse strangers before they reach the server Replaced every time the server sends it
Bytes relayed per month, not per person To enforce the operator's bandwidth budget Indefinitely
A server id the operator blocked, and when To refuse that server Until the operator unblocks it
An account the operator blocked: its GitHub user id, and when To refuse its sign-ins and claims Until the operator unblocks it, also after the account is deleted
The edge's log: server ids, error messages, and the IP addresses of refused connections and failed TLS handshakes To operate and defend the edge For the retention period its operator sets

Rate limits count requests per IP address, or per /64 for IPv6, in memory only; nothing is written. While you are connected, the edge also sees your IP address, which server you reach, when, and how many bytes flow. Your server logs the IP address of each connection the edge relays to it (edge: relayed connection ... client=<address>), as it does for direct connections.

Revoking your devices removes them from the edge; the account record stays. To delete it yourself, open the edge's Account page, https://auth.onaether.dev/account for the project's edge; aether logout --delete-account prints that address. The page asks you to sign in with GitHub in that browser within the last 5 minutes and to type your login (edge.md). The edge then deletes the account, its devices and sessions, and tells each server it reached to remove your identity there; what a server holds is its administrator's. You can also ask the edge's operator, team@onaether.dev for the project's edge, who runs aether-edge accounts delete.

Remote-development data

An enhanced run, and a background run over ACP, records its agent session on your server in <data-dir>/transcripts/<run_id>.items.jsonl: the prompts members send, the agent's messages and thoughts, tool call inputs, command output and diffs, permission requests and their answers. Whatever the agent or a tool prints, a secret included, can land there. Anyone with View on the run can read it through the dashboard; answering or messaging the agent needs the steer permission and the run's control lease. The log and terminal recordings persist until the run is explicitly deleted, including through workspace or swarm deletion. Checkout cleanup and archiving do not remove them. Standard runs keep their terminal recording; older servers may already have trimmed history.

Files selected or pasted into chat are uploaded to the run's persistent member home before sending. So is the picture of each page element annotated in a run's Browser, when its note is sent; the note's text names that file and carries the element's markup and visible text as the page had them. Sending an Enhanced prompt passes image bytes to the agent and its configured model provider; any other file reaches the agent as its path, which the agent can read and pass on. Room records and the session item log retain small attachment references and file paths, not copies of the bytes. Members with View can fetch images attached to that run's retained messages. Removing a draft thumbnail or deleting a run does not remove the member-home file; see image retention.

The shared app browser runs on your server, not in the phone's WebView. Browser input, app-terminal input, observations, frames, and explicit capture requests travel through your Aether server. A page opened there makes its own network requests from the run's network namespace; those app endpoints and any third parties the page contacts receive the usual browser requests under their own policies. This is separate from the Android shell's lack of analytics or third-party reporting.

An app session can contain test-account cookies, tokens, personal data, page URLs, or secrets printed by an app or terminal. Reading the live session, streaming it, or taking a transient capture requires the steer permission and access to the backing account, not merely permission to view a run. Deliberately retained copies instead use capture access and expiry; review what you retain for that audience. Human members and the run agent have distinct per-surface control identities; taking over a shared app surface does not isolate that run's other processes or credentials from it.

The companion has no member-home or source-checkout mount. Its browser context/profile is transient companion state, outside source control. Resetting the browser context removes its pages and session state; a lost browser process does not silently restore an authenticated session. Private control sockets and lifecycle journals live below <data-dir>/scheduler/browser/, not in the checkout or the run's visible coordination files. See security.md.

Captures are explicit PNG files, not continuous recording. Each run can keep at most 64 captures, 128 MiB of PNG bytes in total, and 8 MiB per image. Reaching either aggregate limit refuses a new capture with run capture limit reached; delete captures before taking another; it does not silently evict old captures. Files and their metadata are stored below <data-dir>/coord/<run-id>/captures/, exposed read-only to the run as /run/aether/captures/<random-id>.png. Metadata identifies the run, terminal or page, session/revision, capture time, dimensions, and page URL where applicable. Optional Git HEAD and dirty-state fields describe only what was actually observed at capture time; absent fields mean unknown, not a clean checkout or the packet's later retained revision.

These captures remain transient run-owned files until explicit deletion or cleanup of that run's coordination mount. A retained Standard run keeps its mount and captures until expiry or deletion. The live browser's frame stream is not automatically archived. Browser diagnostics are bounded observations, not a full traffic recording: the companion retains up to 100 console warning/error entries and 100 failed/error-response request entries per page. URLs and logged messages can still reveal sensitive information.

To preserve a reviewed capture before cleanup, open Captures… from the run's More menu or a terminal's Tools, select it under Select transient captures to retain, optionally enter verification notes, and choose Retain selected captures. An agent with the advertised capability uses aether-internal artifact retain with selected artifact_ids, optional verification_notes, and an idempotency_key. This copies only the selected PNGs into the existing retained packet storage and returns a packet_id; it does not verify the application or report an outcome. Agents can pass that packet ID to the existing report --evidence-ref. Retain before a success/failure report, capture deletion, or other cleanup can remove the transient originals. A capture handle or live frame alone is not a durable record.

Retained copies remain readable after development processes stop, subject to capture access and expiry. Each run's retained copies are separately bounded to 64 captures, 128 MiB total, and 8 MiB per PNG across packets; deleting transient captures does not reclaim retained-copy space. Verification notes are bounded to 4096 UTF-8 bytes. Original source, capture time, session, geometry, URL and any observed Git boundary travel with the copy. The packet's later retained Git revision does not rewrite or attest to an earlier screenshot's Git boundary. Missing, truncated and expired captures are not a successful verification result.

Nothing is retained automatically. Resetting the browser does not delete already-written PNGs, and retaining an image does not upload it to a public pull request. There is no credential-entry recording. Do not capture credentials or publish app logins, cookies, tokens, or customer data; Aether cannot reliably redact secrets an app renders in pixels or text, or those you include in verification notes. A member who explicitly downloads, exports or publishes a capture creates a separate copy under that destination's access and retention rules.

Messages one agent sends another stay on your server as workspace history until the sending or receiving run is deleted. Every member of the workspace can read their bodies, the same audience the Activity page has. Do not ask agents to pass credentials to each other.

Permissions

INTERNET lets the app reach your server, or in Edge mode the edge. ACCESS_NETWORK_STATE lets Edge mode read the active network's DNS servers, because Go's resolver finds no /etc/resolv.conf on Android; the app reads no other network state. The androidx library adds one signature-level permission the app defines for its own receivers, which no other app can hold and which grants nothing.

Deleting your data

  • On the phone: uninstall the app, or clear its storage. In Edge mode, also revoke the device at the edge (What an edge stores), since the edge keeps its record of the device until you do.
  • At an edge: see What an edge stores.
  • On the server: the server's administrator owns the data directory and can delete a run, a member home, or the whole directory (install.md). aether member remove removes your environment container, deletes your member record and erases your member home. It refuses while anything still points at you - a run you launched, a schedule you own, or an agent profile you pushed - so an administrator deletes those first; what a run wrote stays in the data directory until it is deleted too (teams.md). The publisher holds no copy and cannot delete anything on your behalf.

Children

The app is not directed at children and has no age-specific content or features.

Licence and open source notices

The app and the dashboard are under the GPL-3.0, and the libraries they use are listed with their licences in notices.md. The app's first screen links to both that page and the licence text.

Changes

Changes to this policy are commits to this file; its history is public at https://github.com/3xDevOps/Aether/commits/main/docs/privacy.md.