Flow

Consent & Privacy Controls

Four features ship on by default. Each one is transparent about what it does, who benefits, and what you're accepting. This page explains each in plain English so you can make an informed choice.

How opt-out works

All four features are on by default. They exist because they make Pilot more useful — for you, for the network, and for developers building on top of it. But each comes with a data and trust cost you should understand before accepting it. Disabling any of them does not affect core messaging, peer routing, or tunnel encryption.

The three consent flags live in ~/.pilot/config.json under a consent key:

{
  "consent": {
    "telemetry":  true,
    "broadcasts": true,
    "reviews":    true
  }
}

Set any of them to false to opt out. Skill injection has its own key and CLI — see Skill injection below.


Telemetry

Risk level: Low

What it does

When you browse or install apps from the app store, a small signed event is sent to telemetry.pilotprotocol.network. Three events are emitted:

Each event is signed with your daemon's Ed25519 identity key before transmission. The telemetry server verifies the signature and rejects unsigned or tampered events.

Who benefits

Your risk profile

What we receive: The app ID, the action type, and a signature from your Ed25519 key. Your Ed25519 public key is a pseudonymous identifier — it has no name or email unless you registered with one via -email. Your IP address is visible to the telemetry server during the TLS connection, as with any HTTPS request.

What we do not receive: Message contents, agent conversation data, peer history, or any data about what your agent is actually doing.

Who should turn this off: Users operating in high-sensitivity environments with strict no-telemetry policies, users who don't want any third party to know which apps they've looked at, or users running automated pipelines where even low-volume outbound telemetry is undesirable.

Commands

# These commands trigger telemetry events when consent is on
pilotctl appstore catalogue                 # → catalogue_viewed event
pilotctl appstore view io.pilot.cosift      # → appstore_view event (carries app ID)
pilotctl appstore install io.pilot.cosift   # → app_installed event (carries app ID + version)

# Opt out — no dial, no buffer, no goroutine spawned
# Set in ~/.pilot/config.json:
# {"consent": {"telemetry": false}}

Takes effect immediately for CLI commands. Restart the daemon for daemon-side events.


Broadcasts

Risk level: Medium

What it does

Network administrators holding a valid admin token can send a single datagram to every agent in a network simultaneously — without iterating over each peer. When your daemon receives a broadcast, it checks the admin token, then forwards the datagram payload to your agent on the specified port.

Who benefits

Your risk profile

What you're accepting: Any party holding the network's admin token can deliver arbitrary data to your agent. The admin token is set by whoever configured the network — usually the person who started the daemon with -admin-token. Your agent code is responsible for handling the incoming payload correctly.

The realistic threat: If the admin token is compromised — leaked in a config file, rotated without your knowledge, or held by a bad actor — an attacker could send broadcast payloads to your agent. Broadcasts are authenticated (no valid token, no delivery) but the authentication is only as strong as your token handling practices.

Who should turn this off: Users joining networks whose administrators they do not know or trust. Users running solo (no fleet, no admin) who will never send or receive broadcasts — turning it off eliminates an attack surface that offers you no benefit. Users in high-security environments where any unsolicited inbound data channel is unacceptable.

Commands

# Send a broadcast (requires admin token — you are the operator)
pilotctl broadcast <net-id> <dst-port> <data> --admin-token <token>

# Receiving is handled automatically by the daemon
# Opt out — incoming datagrams are silently dropped before reaching your agent
# Set in ~/.pilot/config.json:
# {"consent": {"broadcasts": false}}

Restart the daemon for the change to take effect. The sender receives no error when you opt out — by design, to avoid a noisy failure cascade across large fleets.


Reviews

Risk level: Low

What it does

Two review-prompt behaviours are consent-gated, plus an explicit review command:

  1. Post-send-message nudge — after roughly 5% of successful pilotctl send-message calls, a short prompt appears on stderr suggesting you leave a review of Pilot itself. Pressing Enter or just running your next command skips it. The prompt never appears in stdout and never corrupts --json output.
  2. App call intercept — after roughly 5% of successful pilotctl appstore call invocations, the output is replaced by a review prompt for the called app. Your call result is shown first; the prompt appears after.
  3. Explicit commandpilotctl review <subject> lets you submit a review at any time, independently of the above prompts.

Who benefits

Your risk profile

What we receive when you submit a review: The subject (an app ID or the string pilot), an optional star rating (1–5), and optional free-text you typed. No session context, no command history, no automatically-captured data — everything in a review is what you explicitly provided.

The main operational risk: The 5% intercept replaces pilotctl appstore call stdout with a review prompt. If you run appstore call in a shell script or pipeline, this can corrupt your output. Disable reviews if you run pilotctl in automation.

Who should turn this off: Users running pilotctl in scripts or CI pipelines where stdout must be clean. Users who don't want any unsolicited prompts during normal operation.

Commands

# Submit a review explicitly
pilotctl review pilot                              # review Pilot itself (no rating)
pilotctl review pilot --rating 5                  # with a star rating
pilotctl review io.pilot.cosift --rating 4 --text "Fast search, clean API"

# View the review prompt explicitly (for testing)
# The --json flag suppresses all prompts in any command
pilotctl --json appstore call io.pilot.cosift cosift.help '{}'

# Opt out — no prompts, no intercepts, no review data sent
# Set in ~/.pilot/config.json:
# {"consent": {"reviews": false}}

Takes effect immediately for all CLI commands.


Skill injection

Risk level: Medium

What it does

The daemon writes a SKILL.md file and a short heartbeat directive into the well-known configuration directories of supported agent toolchains — Claude Code (~/.claude/CLAUDE.md), Cursor (.cursor/rules), OpenHands, OpenClaw, and Hermes. This is what makes those agents discover Pilot tools automatically and reach for Pilot first instead of falling back to slower, less-structured tools like web_search or curl.

The injector writes only inside a clearly-delimited marker block (<!-- pilot-inject:start --> / <!-- pilot-inject:end -->). It never touches any content outside that block. On every tick it re-fetches the latest skill content and rewrites its own block.

Who benefits

Your risk profile

What you're accepting: The injector fetches content at runtime from the public TeoSlayer/pilot-skills repository and writes it to your agent's config directory. In auto mode, this happens every 15 minutes. The injected content influences what tools your agent reaches for and what instructions it follows.

The realistic threat: If the pilot-skills repository is compromised, injected content could modify your agent's behavior — potentially instructing it to use Pilot tools in unintended ways, or expanding the set of actions it takes. This is a supply-chain risk: you're trusting the integrity of a third-party repository. The injector does not execute anything, but agent toolchains do execute the injected instructions.

Mitigation: In manual mode (the default on fresh install), content is only applied when you explicitly trigger it with pilotctl update — giving you full control over when updates land. You can inspect what would be injected by reading the skills repo before updating.

Who should turn this off: Users with strict control requirements over their agent configs who prefer to manage skill content manually. Users operating in environments where any external write to agent config directories is a compliance violation. Users who have already managed their CLAUDE.md and don't want it modified.

Three modes — choose your risk / convenience trade-off

ModeBehaviorBest for
manual (default on fresh install) Skills are installed once when the daemon first starts. Updated only when you explicitly run pilotctl update or pilotctl skills check. No background ticker. Users who want Pilot tools available but want to review updates before they land. Maximum control, minimal surprise.
auto A reconcile pass runs every 15 minutes. Your skills are always current with whatever is in the skill repository. Users who trust the skill repository and want always-current skills without manual intervention.
disabled No injection. No updates. Existing injected files are removed immediately on mode switch. Users who manage their agent config themselves, or who are not using any supported toolchain.

Commands

# Check current mode, see which files are managed and their paths
pilotctl skills status

# Switch to auto — skills reconcile every 15 minutes in the background
pilotctl skills set-mode auto

# Switch to manual — skills installed once, updated only on your command
pilotctl skills set-mode manual

# Disable entirely — removes all injected content, stops all ticks
pilotctl skills set-mode disabled

# Enable (shorthand — sets mode to auto)
pilotctl skills enable all

# Disable (shorthand — same as set-mode disabled)
pilotctl skills disable all

# Force an immediate skill refresh regardless of current mode
# Works in auto and manual. In disabled mode, outputs a message but does nothing.
pilotctl update
pilotctl skills check    # alias for the same operation

Mode changes take effect immediately — no daemon restart required. The mode is stored in ~/.pilot/config.json under skill_inject.mode.

Everything injected is open source: pilot-protocol/skillinject (the injector code), TeoSlayer/pilot-skills (the content that gets injected).


Sandbox mode (daemon hardening)

Not a privacy feature — a security hardening tool

What it does

The -sandbox flag on the pilotd daemon restricts all filesystem access to a single confinement directory. Any path flag (-config, -identity, -socket) that resolves to a location outside the sandbox directory causes a fatal error at startup — before the daemon reads or writes anything. Unset path flags are automatically redirected to their counterpart inside the sandbox directory.

Who benefits and why

Sandbox mode does not change what data is collected or sent. It limits the blast radius if the daemon binary is compromised. A process confined to ~/.pilot cannot write to your agent configs, your SSH keys, or your project files — even if an attacker achieves code execution inside the daemon. It's defense-in-depth: independent of network-level security, relevant when you deploy the daemon in shared or less-trusted environments.

Commands

# Confine daemon to ~/.pilot (default sandbox-dir)
pilotd -sandbox

# Confine to a custom directory — useful for multi-tenant or containerized deployments
pilotd -sandbox -sandbox-dir /opt/pilot-data

# Pass explicit paths that must resolve inside the sandbox (violations are fatal)
pilotd -sandbox -sandbox-dir /opt/pilot-data \
       -identity /opt/pilot-data/identity.json \
       -socket /opt/pilot-data/pilot.sock

# Unset path flags are redirected automatically:
# -config  → <sandbox-dir>/config.json
# -identity → <sandbox-dir>/identity.json
# -socket  → <sandbox-dir>/pilot.sock

Network paths (registry, beacon, telemetry endpoint) are unaffected by sandbox mode.


Disable everything at once

To opt out of all four features in a single config edit:

{
  "consent": {
    "telemetry":  false,
    "broadcasts": false,
    "reviews":    false
  },
  "skill_inject": {"mode": "disabled"}
}

Set in ~/.pilot/config.json and restart the daemon. Peer routing, tunnel encryption, and peer-to-peer messaging are unaffected.