@dwell-protocol/terminal
v0.2.2
Published
DWELL terminal integration for Claude Code.
Readme
DWELL Terminal
Standalone Claude Code terminal integration.
Install
npx @dwell-protocol/terminal claude setupMigrating from FreeAI: setup detects the old # >>> FreeAI Claude terminal
integration >>> block in your rc file and replaces it with the DWELL one — no
--force needed. The retired freeai backend serves no ads, so a leftover
freeai alias silently runs plain claude with no ad line; rerun setup (then
source your rc or open a new shell) to fix it. dwell claude restore removes
the legacy block too.
Commands
Local dev (from this repo):
cd terminal
npm test
node bin/dwell.js claude setup| Command | What |
| --- | --- |
| dwell claude setup | Locate the real claude, store it in ~/.dwell/claude/config.json, add a marked shell alias/function, then link your DWELL account by email. Linking is required — the prompt re-asks until a valid email is given (no skip). Pass --email [email protected] to link non-interactively, or the explicit --no-link to opt out (credits then stay unclaimable until you run dwell claude link). |
| dwell claude link [--email …] | Email yourself a magic link that attributes this machine's Claude Code credits to your DWELL account. Run it any time after setup. |
| dwell claude run [...args] | Internal wrapper used by the alias. It forwards args, cwd, env, stdio, signals, and Claude's exit code. |
| dwell claude restore | Remove the marked shell block. Safe to run repeatedly. |
| dwell claude doctor | Print the resolved Claude path, config/shell/rc paths, then probe the backend pipeline (config → ads → device → account → click-intent) and report an adsWillServe verdict. The account step shows whether this device is linked to your DWELL account. Pass --no-backend to skip the network probe. |
Account Linking
Credits earned in the terminal accrue to an anonymous device (~/.dwell/device.json)
until that device is linked to a DWELL account. Linking emails you a magic link
(POST /v1/auth/request-link); clicking it (/v1/auth/verify) sets the device's
user_id, after which Claude Code credits show up in your portal balance. This is
the same device→account flow the Chrome extension popup uses. Until you link, the
account step in dwell claude doctor reports linked: false.
Confirming the link. On a terminal, setup/link send the magic link and
then wait up to ~60s for you to click it, printing ✓ Linked to <email> once
confirmed (or a "didn't see a click yet" hint). Pass --no-wait to fire the
email and return immediately; non-interactive runs never block.
If you skip or abandon linking, dwell claude run prints a single reminder
to stderr (at most once per day) — … aren't linked to an account yet — run
dwell claude link — so credits don't pile up unclaimed. It's local-throttled,
never nags a linked user, and can be silenced with DWELL_NO_NUDGE=1.
Debugging "no ad shows"
The ad path is silent in normal use, so doctor can be green on the local
machine while no ad serves. Two diagnostics:
dwell claude doctor— theadsWillServefield plus per-stepok/errorshows whether the backend pipeline succeeds (network reachable, ad in rotation, device + click-intent created).DWELL_DEBUG=1 claude— traces to stderr whether the wrapper ran and which step, if any, caused it to fall back to plainclaude. Nodwell[debug]output means the shell alias isn't active (type claudeto confirm).
setup adds a marked, reversible shell alias/function so claude ... becomes
dwell claude run .... zsh/bash use:
alias claude="dwell claude run"fish uses an equivalent claude function that forwards $argv.
Uninstall
dwell claude restore # remove the shell alias/function
# restart your shell, or source your rc
npm rm -g @dwell-protocol/terminal # remove the CLI (if installed globally)
rm -rf ~/.dwell # optional: delete local state (device + config)restore removes only the marked shell block; it never touched your real
claude binary, the npm shim, or ~/.claude/settings.json, so Claude Code keeps
working unchanged. If dwell is already gone, delete the marked block from your
rc file by hand. Deleting ~/.dwell removes the device credentials — link your
account by email first (dwell claude link) if you want unlinked earnings to
follow your account.
Claude Code Integration
Reference surfaces:
- Claude Code status line docs: https://code.claude.com/docs/en/statusline
- Claude Code
--settingsCLI docs: https://code.claude.com/docs/en/cli-reference
The wrapper launches the real Claude Code binary with a temporary --settings
file containing a DWELL statusLine command. It preserves any user-supplied
--settings value by parsing and merging it into the temporary settings file,
then chains any pre-existing effective user/project/local statusLine.
The status line command receives Claude Code's JSON status payload on stdin. It
uses transcript_path plus structural transcript rows to decide whether Claude
is actively thinking. When active, it prints one clickable OSC 8 ad· <line>
that points at a /v1/go/:token URL from /v1/clicks/intent. When idle, it
prints only the user's original status line, or nothing.
It never edits the real Claude binary, npm shim, or persistent
~/.claude/settings.json. If config, ad fetch, device registration, click-intent
creation, settings parsing, or any other DWELL preparation step fails, run
executes Claude unchanged.
Hooks are intentionally not used in v1. The supported integration surface is
Claude Code statusLine plus a session-scoped --settings file.
State And Billing
Runtime state is stored under ~/.dwell/claude/sessions/<session-id>/ and is
removed when Claude exits. Device credentials are stored in ~/.dwell, matching
the existing Chrome extension device-credit backend.
An impression is emitted to /v1/events only after 5 continuous active seconds
with a fresh statusline heartbeat. Clicks use /v1/clicks/intent tracking URLs;
the terminal client does not self-report click counts through /v1/events.
Backend Configuration
The default API base is the production Supabase Edge Function. It can be
overridden with ~/.dwell/config.json:
{
"backendBaseUrl": "http://127.0.0.1:8787"
}or with DWELL_BASE when no config file override is set.
Tests
make test-terminal
# or
cd terminal && npm testEnd-to-end across surfaces ("watch your balance climb"): to earn against a local API and watch a portal balance update live, run the client with
DWELL_BASE=http://localhost:8787and follow../DEVNET.md(make devnet+make devnet-earn).
