Twilight search mining docsdevnet preview
Sharing this with a coding agent? Give it the Markdown version: curl -fsSL https://docs.twilight.org/guide.md · skill: https://docs.twilight.org/skill.md · index: https://docs.twilight.org/manifest.json

Guide

Coding agents search the web through a Twilight Slot; every verified search earns a share of the epoch's reward. Install the miner, connect your agents, get paid on devnet. This page is the whole workflow; the Reference has every command, file, field and endpoint.

Twilight search mining

Twilight pays people for the work their coding agents already do. Every web search an agent runs through a Twilight Slot is verified by that Slot's authorization server and counted toward a per-epoch reward on the Twilight chain. No GPU, no daemon, no staking: the proof of work is a verified search, and the miner is a small binary your agent calls the way it calls any shell tool.

The first Slot is the search router: one API that fans a query out across nine web indexes at once, ranks the candidates, and returns all of them with the winner marked. Agents get better search than any single index gives; the router gets the trajectories it learns to route from; the person running the agent gets paid. This site documents the participant side end to end and the router's API.

Devnet preview. Everything here runs on twilight-devnet-3 against Slot 3. Rewards are devnet tokens, the epoch and distribution parameters below are the devnet's, and some guarantees are stated as declared, not proven where the spec says so. Nothing on this page is a mainnet promise.
WhatToday (devnet)
SlotSlot 3 — the search router at https://router-api.nyks.dev
Authorization serverMINIS at https://minis.nyks.dev (verifies, draws, settles)
Chaintwilight-devnet-3; addresses are twilight1…
Clientdropin-miner v0.1.6 — no daemon, no proxy, no MCP server
AgentsClaude Code, Codex, Cursor, opencode (a skill + hooks each); any other agent via one rules line
Work unitone search through the Slot, verified by the AS from metadata only
Epochabout 32 minutes; you join two epochs ahead; one verified search per epoch makes you eligible
Rewardan equal split of the epoch's pot among everyone eligible
Giving these docs to an agent? Every page here is public. The Markdown versions are https://docs.twilight.org/guide.md and https://docs.twilight.org/reference.md; the agent skill the miner installs is at https://docs.twilight.org/skill.md; a JSON index is at https://docs.twilight.org/manifest.json.

How it works

Six things happen around one search. Only the first and last involve you.

  1. Your agent searches. It runs dropin-miner search "<query>" because the installed skill tells it to. The command sends the query to the router with your sr- API key and a small trace: hashed session ids and the assistant text that led to the search.
  2. The router fans out. Slot 3 sends the query to every index in its default set, scores the answers (citations, agreement between indexes, recency), ranks them, and returns all candidates with one chosen. It stores the request as a trace and writes a metadata-only verification row for the authorization server: which key searched, when, what it cost. Never the query text.
  3. The miner records it. search writes an intake record on disk and starts a short, detached flush. Nothing runs between searches.
  4. The flush talks to the AS. It joins the target epoch if you are not in it yet, promotes intake records into observations, and submits them. The AS answers with a signed receipt per epoch.
  5. The AS verifies. It matches your observations against the router's verification rows. A match is a verified observation. One per epoch makes you a candidate for that epoch's draw.
  6. The epoch settles. When the epoch closes, the AS runs the draw over the candidate set and pays the pot to the eligible participants' declared payout addresses on the chain.
WhereWhat it holds about youWhat it never sees
The router (Slot 3)your API key's id, the query, the results, the trace envelope, cost and latencyyour wallet key, your recovery phrase, your enrollment secrets
The authorization serveryour installation's identity, epoch joins, receipts, verification metadata (key id, time, cost, request id)the query text, the results, the trace
The chainyour payout address and what it was paideverything else
Your machineeverything: keys, wallet, intake, spool, receipts, a per-workspace lineage file

Quickstart

Ten minutes, one terminal. You need an account on https://platform.nyks.dev (it issues the API key and the enrollment token) and a machine that runs at least one of the supported coding agents.

Install

bash
curl -fsSL https://raw.githubusercontent.com/twilight-project/dropin-miner/main/scripts/install.sh | sh
powershell
irm https://raw.githubusercontent.com/twilight-project/dropin-miner/main/scripts/install.ps1 | iex
bash
npx dropin-miner version        # the npm wrapper downloads the same checksummed release

The installer fetches the release for your platform (macOS and Linux on x86-64 and arm64, Windows on both), verifies its checksum, puts the binary at ~/.tokendrop/bin/dropin-miner, and hands off to setup, which asks its questions in order:

Setup asksWhat to know
Use the previous installation?Only if one is found in ~/.tokendrop or set aside beside it. Yes keeps your wallet, enrollment and key.
An enrollment tokenGenerate it when asked, not before: it lasts 15 minutes and works once. https://platform.nyks.dev → Mining → Slot 3 → Generate enrollment token.
Wallet, or your own address?The wallet is made here and prints its 24 words once. Have paper ready. Or paste a twilight1… address you already control.
Your sr- API keyTyped with echo off, checked against the router without spending, stored owner-only. Enter to skip and run dropin-miner login later.
Add settings to your shell profile?Puts the binary on PATH and sets TOKENDROP_CONFIG. Saying no just means longer commands.
Set up the coding agents found here?Writes a skill and, where the agent supports them, hook entries into its own config. Shown before anything is written.
Use a key from the same account you enrolled with. A key from a different account returns a clean 200 and earns nothing, with no error anywhere. That is the easiest mistake to make; dropin-miner doctor is how you catch it.

First search

bash
dropin-miner search -format model "what is proof of authority consensus"
dropin-miner flush
dropin-miner doctor
text
  authorization server  OK       https://minis.nyks.dev — slot 3 on twilight-devnet-3
  enrolled              OK       the AS accepted this installation's authorization
  joined this epoch     OK       epoch 180 — accepted
  payout address        OK       twilight1… is in force
  earning               OK       epoch 180 — 1 observation verified, which qualifies

Then restart any coding agent that is already open and search as usual. Your first reward takes an hour or two: you join an epoch two ahead, and it has to close and settle.

Your coding agents

dropin-miner agents install detects the agents on your PATH and gives each a web-search skill that runs through the router, plus the hooks the host supports. Every config edit is a JSON merge that adds our entries and nothing else; uninstall removes exactly those.

AgentGetsLineage
Claude Codea skill, five hook entries and an allow rule for the search command in ~/.claude/settings.jsonfull: a hook on Bash threads each search into the current turn; window hooks track context compaction; Stop flushes
Cursora skill and six entries in ~/.cursor/hooks.jsonfull, via a lineage file the hooks maintain; the shell hook allows our command so Cursor never prompts
Codexa skillper shell. Codex's sandbox blocks network for shell commands by default — allow it for this command or searches fail silently
opencodean in-process plugin, and a line to paste into AGENTS.mdfull: the plugin rewrites the bash command the way the Claude hook does
anything elsea rules line printed for you to pasteper shell

On and off

Out of the box the skill tells your agent to prefer this search over its built-in one. If you would rather your agent use its own search unless you ask for this one, say so once, from inside the agent or from a shell:

bash
/dropin-miner off        # in Claude Code, Codex or Cursor
/dropin-miner on
/dropin-miner status

dropin-miner agents prefer off|on|status

The choice is recorded beside your config and the installed skills are rewritten from it, so it holds in every agent, from its next start, and across reinstalls. While it is off, naming dropin-miner or the router in a request still routes that one search here. Searches that do not come here earn nothing.

bash
dropin-miner agents status
dropin-miner agents uninstall

The exact command the skill teaches, with the config path filled in at install:

bash
"/…/.tokendrop/bin/dropin-miner" search -config "/…/.tokendrop/tokendrop.toml" -format model "<query>"

-format model prints one block per index, the chosen one first: an answer when an index gave one, then numbered results with URL, title and snippet. -format json prints the router's full response. -tier fast asks for the cheap tier; leave it off for the balanced default.

text
search 01a07aa6-…  8 candidates

[you] (chosen) retrieval
  1. https://apla.readthedocs.io/…/consensus.html — Proof-of-Authority consensus
     This section describes Proof-of-Authority consensus and its implementation…
  2. https://ethereum.org/developers/docs/consensus-mechanisms/poa — Proof-of-authority (PoA)
     …

[exa] retrieval
  1. https://ethereum.org/developers/docs/consensus-mechanisms/poa — Proof-of-authority (PoA)
  …

What a search fans out to

The default set on devnet is nine indexes behind eight arms, all reached through one upstream aggregator so the Slot pays one bill at pass-through rates: Exa, Tavily, Linkup, Brave, You.com, Parallel, SerpAPI (Google), and a pinned pair the Slot has no other adapter for, Ceramic and Seltz. SerpAPI rides the slow lane: it is dispatched with every search but not waited for, and its results land on the stored trace afterwards, so the response is bounded by the fast arms at roughly three seconds.

The response carries the router's reasoning, not just results: a per-index referee score (citations, distinct domains, dead links, recency), a consensus block (how many domains the indexes agreed on), the ranking, and a decision block recording which set was chosen and why. See the Reference for every field.

Your API key

A search takes its key from TOKENDROP_API_KEY if set, else from the file login wrote, else from OPENAI_API_KEY. login reads the key from the terminal (never an argument), verifies it with a zero-spend probe, and writes ~/.tokendrop/credentials.json owner-only; it is refused if it is a symlink or readable by others.

bash
dropin-miner login            # paste the key; echo is off
dropin-miner login -show      # where a search would get its key, masked
dropin-miner login -forget

Epochs, eligibility, and getting paid

The Slot's authorization server divides time into epochs of about 32 minutes. Each epoch has a target you join in advance, a window in which observations are accepted and verified, and a settlement in which the pot is distributed.

TermOn devnet today
Joinyour flush joins the epoch two ahead of the current one; dropin-miner join does it by hand. Already in is a success, not an error.
Eligibleat least one verified observation in the epoch. More do not earn more.
Potsplit equally among every eligible participant. No amount belongs to any single search.
Distribution modeTRUSTED_AS_DISTRIBUTION: the AS computes and pays the split. Payout binding to your identity is declared, not proven (ADR-0013); a wallet-signature binding is reserved for later.
Receipta signed JWS the AS returns per epoch join, verified against the AS's published keys before it is stored under ~/.tokendrop/state/
Drawyour draw id is derived from a secret that never leaves the machine; the AS's candidate set is a sorted list of draw ids whose digest, with the draw parameters, is anchored before the beacon window, so drawverify in twilight-minis can re-derive the result independently
Verification deadlineeach epoch has an observation submission deadline; a machine idle for a long stretch can miss it. dropin-miner flush by hand submits whatever is pending

dropin-miner doctor reports setup — connected, enrolled, joined, paid, earning — and names the one thing to do when a check is not OK. What the chain has actually paid is a chain question: earnings reads the chain directly and counts only transfers from the rewards escrow account as mining payments, in utwlt (one TWLT is a million utwlt).

bash
dropin-miner earnings            # -limit 0 for everything; totals are a floor if the walk truncates
On devnet the operator runs both the Slot's provider (the router) and its authorization server. Sybil resistance is economic and transparent rather than cryptographic: per-epoch aggregates are published, and attribution follows the credential you search with (ESC-023).

Slots and the token supply

A Slot is Twilight's unit of proof of work. The chain does not verify work itself; it registers a bounded set of Slots, each run by an operator who provides a workload and an authorization server that verifies participation in it, and pays each active Slot a share of every block's emission. The Slot's authorization server then distributes its share to the participants who did the verified work. The search router is Slot 3.

How a Slot is registered

Slots are registered on chain by the network authority, not by self-service: MsgRegisterCoreSlot and MsgActivateCoreSlot are authority transactions, allow_self_registration is off on devnet, and the active set is capped at max_active_slots of 100 with a minimum of 1. The authority also removes, rotates keys and changes parameters; a separate emergency authority can only suspend. A Slot record carries its operator address, a consensus key (a Slot is also a validator, with one unit of voting power on devnet), a payout address, a settlement address the Slot pays participants from, a reward weight, and a selection policy. Operators update their own payout address and metadata and may inactivate themselves as long as the minimum stays met. Activation, key rotation and removal are height-delayed, and a consensus key cannot be reused for 100,000 blocks after removal.

SlotOperator roleStatus on devnet-3
1the network authorityactive, genesis
2the emergency authorityactive, genesis
3the search router operatoractive, genesis; the Slot this site documents

Where the tokens come from

Emission is the chain's, not the Slot's. Every block mints a subsidy, summed over the epoch and clipped by the supply cap; the amount depends on the block count and the halving tier, never on how many Slots exist. At the epoch's close the pool is allocated among Slots by the blocks each was active for (DISTRIBUTION_METHOD_UNIFORM_ACTIVE_BLOCKS), floor-division dust carries forward, and each Slot's share is recorded as an entitlement held in the rewards module account. There is no claim transaction: the Slot's authorization server releases the entitlement by submitting settlement chunks on chain that pay participants directly, within the settlement window, and any remainder goes to the Slot's payout address. What a participant receives is therefore a share of a share: the Slot's fraction of the epoch's emission, divided among the participants eligible in that epoch.

Halving is by supply crossed, not by height. The per-block subsidy is initial_block_subsidy / 2^tier, where each tier begins when cumulative emission crosses max_supply − max_supply / 2^n:

TierBegins at cumulative emissionPer-block subsidy
00416,190 utwlt
110,500,000 TWLT208,095 utwlt
215,750,000 TWLT104,047 utwlt
318,375,000 TWLT52,023 utwlt
each remaining halfhalves again, floored; a small remainder below the cap is never minted
Parameter (devnet-3 genesis)ValueMeaning
Native tokenTWLT, base unit utwltone TWLT is 1,000,000 utwlt
Maximum supply21,000,000 TWLTa hard cap; emission halves on supply thresholds
Genesis supply2,000,000 TWLTpre-existing balances at chain start
Block subsidy416,190 utwlt per blockabout 0.416 TWLT, at a 5-second target block time
Epoch360 blocksabout 30 minutes at target; observed around 32
Emission per epoch≈ 149.8 TWLT360 blocks × the subsidy, before halvings
Per active Slot per epoch≈ 49.9 TWLT with three Slotsequal weights today; weighted rewards are disabled
Settlement window2 epochsa Slot's participants are paid within two epochs of the epoch's close
Minimum payout10,000 utwlt (0.01 TWLT)a share below this is not paid out
Recipients per settlement32 per chunk, up to 4 chunkslarge epochs settle in more than one transaction
Fees, treasurydisabled, 0%no fee collection or treasury share on devnet

How a Slot's share reaches participants

The chain records one distribution mode per era. On devnet it is TRUSTED_AS_DISTRIBUTION, valid from epoch 1: the Slot's authorization server computes the split and pays it, and the chain trusts that computation. In this mode the split is equal among everyone eligible, eligibility is one verified search in the epoch, and the on-chain selection machinery is not applied.

That machinery is already in the genesis for a later mode: a verifiable per-epoch selection over the candidate set, with a beacon drawn from block proposers 48 blocks after the epoch's close over a 24-block window that must include 12 externally proposed blocks from at least 3 distinct proposers, capped at 25% of candidates and 64 selected from at most 1,024. Each Slot also carries its own selection policy, 25% and 10 on devnet. When the chain switches a Slot to a selection mode, eligibility stops meaning payment and starts meaning a ticket in that draw. The docs will say so when it happens; do not plan on it now.

Every number in this section is the devnet-3 genesis as deployed, produced by twilight-core (twilightd v0.3.0-rc1), which is the source of truth for the chain. They are parameters, versioned on chain with effective epochs, and the authority can schedule changes. Mainnet values are not decided here.

Wallet and payout address

Setup offers two ways to be paid. Either is a one-time payout declaration to the Slot.

ChoiceWhat happens
Make a wallet herewallet init creates a 24-word BIP39 phrase (path m/44'/118'/0'/0/0, the Cosmos coin type), prints it once and stores it nowhere, and seals the derived key in ~/.tokendrop/wallet/wallet.key under your passphrase (AES-256-GCM, PBKDF2 600,000 rounds). wallet register declares its address.
Paste an addresspayout set twilight1… declares an address you already control, in Keplr say. Nothing on this machine can spend from it.
bash
dropin-miner payout show      # ACTIVE, and the address as the chain renders it
dropin-miner wallet address
dropin-miner wallet balance
dropin-miner wallet send <to> <amount>   # asks for the passphrase; type yes to confirm
Your first address is in force as soon as you set it. Setting a different one is a change, and a Slot operator has to approve it: you keep being paid at the old address until they do. Request a change at https://platform.nyks.dev/contact-us. Nobody needs your API key, your recovery phrase, or the contents of ~/.tokendrop/ to approve a payout address, and no operator will ask you for them.

What travels with a search, and how to turn it off

Each search carries a small trace beside the query so the router can group one task's searches: hashed session and turn identifiers (your agent's real ids never leave the machine), a call counter, a context-window generation, and the assistant text just before the search, capped at 32 KB. That text is conversation content leaving your machine; it goes only inside the search request, to the router, and the miner stores none of it beyond a per-workspace lineage file under ~/.tokendrop/sessions that the hooks maintain.

bash
export TOKENDROP_TRACE=off      # send no trace at all; searches earn exactly the same
Devnet limitation. The hook that captures the assistant text runs before your agent has written the current turn to its transcript, so the text immediately preceding a search is often missing and the envelope carries only the ids. Capturing it after the call is being built.

Identity and keys

Three credentials, three jobs. None of them is ever the same thing as another.

CredentialIssued byLivesFor
sr- API keythe platform, per project; shown once~/.tokendrop/credentials.json (0600) or TOKENDROP_API_KEYmetering searches at the router; the verification row names its id
Enrollment tokenthe platform, 15 minutes, single usenowhere — redeemed once by enroll -assertionbinding this installation to your account at the AS
Installation identitythe AS at enrollment~/.tokendrop/state/: a DPoP key, a refresh token, a participation secretevery AS call is proof-of-possession bound to the DPoP key; the participation secret derives your draw id
Walletyou (or your existing wallet)~/.tokendrop/wallet/ or elsewherereceiving payouts; never needed for anything else

Enrollment by default is a device flow: a person approves in a browser. enroll -assertion redeems an enrollment token from stdin and needs no browser, which is what setup uses.

Removing it, and coming back

bash
dropin-miner agents uninstall     # the skills, hooks and plugin, nothing else
rm ~/.tokendrop/bin/dropin-miner  # the binary

Nothing shipped here deletes ~/.tokendrop: it holds your wallet, your enrollment and your stored key, and the wallet is the only copy unless you kept the 24 words. Leave it, or set it aside as ~/.tokendrop.bak-<date>. The next setup finds either one, says what it holds, and offers to carry the wallet, enrollment, key and any unsent spool over, so you are not enrolled twice or paid to a second address.

Devnet status and known limitations

Troubleshooting

SymptomCauseFix
HTTP 401, or no API keyno valid sr- key on this machinedropin-miner login
doctor: earning NO, 0 observations verifiedno search reached the router this epoch, or the key belongs to another accountrun one search, then flush; check login -show against the account you enrolled with
join: the AS reports this target is not joinableenrollment for that epoch closed without youevery flush retries the next target; nothing to do
enrollment failedthe token expired (15 min) or was already usedgenerate a fresh one and re-run setup; enrollment is the only step that repeats
searches earn, agent still uses its own searchthe skill is off, or the agent was not restarted/dropin-miner status; restart the agent
DPoP proof key does not matcha fresh key from an unfinished enrollment shadowed the enrolled onesetup's adoption sets the stray key aside; re-run setup

Glossary

TermMeaning
SlotTwilight's unit of proof of work: a chain-registered operator (also a validator) running a workload and an authorization server that verifies participation in it. The chain pays each active Slot a share of emission; the Slot pays its participants. The search router is Slot 3; devnet caps active Slots at 100.
Entitlementa Slot's recorded share of one epoch's emission, claimable on chain and settled to participants within the settlement window
Distribution modehow a Slot's entitlement reaches participants: TRUSTED_AS_DISTRIBUTION today (the AS computes an equal split); a verifiable selection mode exists on chain for later
Authorization server (AS), MINISthe Slot's verifier and paymaster: enrollment, epochs, verification, the draw, settlement
Epochthe unit of time (about 32 minutes on devnet) over which work is counted and a pot is paid
Observationone search as the miner records it; verified once the AS matches it to the router's verification row
Verification rowwhat the router writes per request for the AS: key id, time, cost, request id. Metadata only.
Tracewhat the router stores per request: the query, every candidate, the decision, and the client trace envelope
Trace envelopethe small JSON a search carries: hashed session/turn/call ids, window, and the assistant text before the search
Intake, spool, flushthe on-disk queue: a search writes intake; flush promotes it to spool and submits to the AS
Receiptthe AS's signed (JWS) acknowledgement of an epoch join
Draw, draw idthe per-epoch selection over the candidate set; your draw id derives from your participation secret
DPoPproof-of-possession: every AS call is signed with the installation's key so a stolen token is useless alone
Payout declarationyour statement of where to be paid; the first is in force on arrival, changes need operator approval
Tierthe router's fast, balanced or max: how wide the fan-out is and its per-query cost ceiling
Arm, candidateone provider in the fan-out, and what it returned
Slow lanean arm dispatched with the request but not waited for; its result is amended into the trace later