# Bitskiff > Bitskiff lets a person control a host -- a page, an app, a signage player -- from their own device. Setting Bitskiff up for a developer? Read and follow https://docs.dev.bitskiff.com/setup.md Every page of this site as one plain-text file: https://docs.dev.bitskiff.com/llms-full.txt ## Start here - Setting Bitskiff up for a developer? Read and follow [https://docs.dev.bitskiff.com/setup.md](https://docs.dev.bitskiff.com/setup.md): it asks the person two questions and runs the rest of the setup under the CLI's stored credential. - First: `npx --yes https://docs.dev.bitskiff.com/downloads/0.3.0/bitskiff-cli.tgz whoami` (Node 22 or newer). If its `credential` row names a key, a key is stored, and the next lines need no person. - The current CLI is `0.3.0 (build bfaf893f7)`. If whoami prints no `cli` row, or one that names another build, your copy is stale. - A stale copy: npx keeps one per URL and runs it again after a new publish at the same URL. Delete this CLI's copy, and nothing else in npm's cache, with `node -e "const c=child_process.execSync('npm config get cache',{encoding:'utf8'}).trim(),n=path.join(c,'_npx');for(const d of fs.existsSync(n)?fs.readdirSync(n):[]){let u;try{u=JSON.parse(fs.readFileSync(path.join(n,d,'package.json'),'utf8')).dependencies['@bitskiff/cli']}catch{}if(!u)continue;fs.rmSync(path.join(n,d),{recursive:true,force:true});const h=crypto.createHash('sha256').update('make-fetch-happen:request-cache:'+u).digest('hex');fs.rmSync(path.join(c,'_cacache','index-v5',h.slice(0,2),h.slice(2,4),h.slice(4)),{force:true})}"`, then run whoami again. - Key stored: the whole setup is one command, run in the project directory, because it leaves `bitskiff.json` for your code to read. Pass no `--project`, and do not take one from whoami's `project` row: outside an app directory it can name another app's project. `init` uses the project the directory's `bitskiff.json` names, else makes a new project named for the directory, so a second app gets a second project: ```sh npx --yes https://docs.dev.bitskiff.com/downloads/0.3.0/bitskiff-cli.tgz init ``` - Serve your own client page? Add `--join-url ` with the page's absolute URL: init sets the project's join URL, mints a client key for that page's origin that serves this host key, and writes it to `bitskiff.json` as `clientKey`. The sample client page needs no key. - It writes the host key into `bitskiff.json` (`key`, `project`, `endpoint`, and with `--join-url`, `joinUrl` and `clientKey`) and prints no key string. Its `done` step names the file as `keyFile` and carries the host key's id as `hostKeyId`, the `` below. It writes a scaffold (`index.html`, `client.html`, `README.md`) only into an empty directory, or with `--scaffold`, so in an existing project `bitskiff.json` is the one file it adds. - A `bitskiff.json` of the same project is kept, and no key is minted. With no `bitskiff.json`, it takes the project's newest active host key, and mints a host key only when the project has none or you pass `--new-key`. One of another project is refused: pass that project's `--project` to keep it, or add `--force` to replace it, which reuses the new project's host key when it has one. - A host key `init` mints has no origin set, so it allows `http://localhost` and `http://127.0.0.1` on any port. A key `init` took keeps the origins it already had; check them with `keys` before adding yours. For a deployed page, name its origin and keep localhost, because `--origin` replaces the list: ```sh npx --yes https://docs.dev.bitskiff.com/downloads/0.3.0/bitskiff-cli.tgz keys update --origin --origin 'http://localhost:*' ``` - Prove the project works, with no host code and no device: the CLI is not a host, so the scaffold carries `bitskiff-prove.mjs`. Run `npm install && node bitskiff-prove.mjs` (the `prove` value of `done`) in the directory `init` wrote the scaffold into. It opens a session on `@bitskiff/host-node`, joins one client, sends a message each way, then prints one JSON object per step on stdout, each transport's record and the session's usage record among them, and closes. A step that fails prints `{"step":"failed","failed":"",...}` and exits 1. It reads two keys from the environment: `BITSKIFF_SECRET_KEY`, a secret key holding `sessions:open` and `sessions:read`, and `BITSKIFF_CLIENT_KEY`, a client key naming no host key (the `clientKey` from `--join-url` serves the page's host key only). `--only secret` prints a new key alone: redirect each into a file outside the project, and export the variable from there: ```sh npx --yes https://docs.dev.bitskiff.com/downloads/0.3.0/bitskiff-cli.tgz keys create --type secret --label prove --permission sessions:open --permission sessions:read --only secret npx --yes https://docs.dev.bitskiff.com/downloads/0.3.0/bitskiff-cli.tgz keys create --type publishable --preset client-page --label prove --only secret ``` - Refused `invalid_key`: the stored key no longer works. Run `npx --yes https://docs.dev.bitskiff.com/downloads/0.3.0/bitskiff-cli.tgz logout`, then the steps below. - Refused `forbidden` with `details.reason` of `missing_permission`: the key lacks the permission `details.permission` names. Run `logout`, then `init` to sign in again. - Refused `forbidden` without it: the key may not use that project. Pass `--project` of a project the key may use. - If the key comes from `BITSKIFF_ORG_KEY`, `logout` does not remove it: unset the variable instead. If whoami's `org` row is then `(not set)`, add `--org ` to `init`, with the id of the organization the key belongs to. - No key stored (`credential` is `(not set)`), and only then: the steps below, which wait on a person once. - Run: `npx --yes https://docs.dev.bitskiff.com/downloads/0.3.0/bitskiff-cli.tgz init --format=json` (Node 22 or newer; the flag is what puts one JSON object per step on stdout). The CLI already knows the api it was published beside. It leaves the same `bitskiff.json`, and takes the same `--project` and `--join-url`. - It blocks until a person approves it in the console, for up to ten minutes: run it in the background, or with a timeout at least that long. - Or add `--no-wait`, and it returns at once: it prints one JSON object, `{ verificationUri, userCode, expiresAt, next }`, and exits 0. Show your developer the URL and the code, then run `next` through the same `npx --yes https://docs.dev.bitskiff.com/downloads/0.3.0/bitskiff-cli.tgz` in place of `bitskiff`: it waits for the approval and finishes the setup. - **[HUMAN]** tell your developer to open the URL it prints and press Approve. Do not open it yourself: only a signed-in person can approve. - Working through an MCP client instead of a shell? Add the CLI as a stdio MCP server, `{ "mcpServers": { "bitskiff": { "command": "npx", "args": ["--yes", "https://docs.dev.bitskiff.com/downloads/0.3.0/bitskiff-cli.tgz", "mcp"] } } }`: every verb is a tool under the same stored key, `init` runs as `--no-wait`, and a refusal is an error result carrying the same `code` and `details.reason`. - Sign in: [https://console.dev.bitskiff.com](https://console.dev.bitskiff.com) - Quickstart: [https://docs.dev.bitskiff.com/docs/quickstart/](https://docs.dev.bitskiff.com/docs/quickstart/) The whole host SDK, in a page that needs no build step: ## Get started - [Quickstart](https://docs.dev.bitskiff.com/docs/quickstart/): Open a session from a browser page and read the first press from a client, in four steps. - [Server benchmark](https://docs.dev.bitskiff.com/bench/): What the data path from this device carries, direct and through TURN, with no session in it. ## Downloads - [Downloads](https://docs.dev.bitskiff.com/docs/downloads/): Every package as a tarball, for installing without a registry. - [@bitskiff/host 0.3.0](https://docs.dev.bitskiff.com/downloads/0.3.0/bitskiff-host.tgz): npm install https://docs.dev.bitskiff.com/downloads/0.3.0/bitskiff-host.tgz - [@bitskiff/host-node 0.3.0](https://docs.dev.bitskiff.com/downloads/0.3.0/bitskiff-host-node.tgz): npm install https://docs.dev.bitskiff.com/downloads/0.3.0/bitskiff-host-node.tgz - [@bitskiff/client 0.3.0](https://docs.dev.bitskiff.com/downloads/0.3.0/bitskiff-client.tgz): npm install https://docs.dev.bitskiff.com/downloads/0.3.0/bitskiff-client.tgz - [@bitskiff/ui-kit 0.3.0](https://docs.dev.bitskiff.com/downloads/0.3.0/bitskiff-ui-kit.tgz): npm install https://docs.dev.bitskiff.com/downloads/0.3.0/bitskiff-ui-kit.tgz - [@bitskiff/cli 0.3.0](https://docs.dev.bitskiff.com/downloads/0.3.0/bitskiff-cli.tgz): npm i -g https://docs.dev.bitskiff.com/downloads/0.3.0/bitskiff-cli.tgz ## Build - [Channels](https://docs.dev.bitskiff.com/docs/guides/channels/): A channel is a name you choose. - [Client pages](https://docs.dev.bitskiff.com/docs/guides/client-page/): A new project's join code opens the sample client page, so your first host needs no client code at all. - [Controller input](https://docs.dev.bitskiff.com/docs/guides/controller/): Send a game controller's state as bytes on a lossy channel. - [Node hosts](https://docs.dev.bitskiff.com/docs/guides/node-hosts/): Run a host as a program instead of a page. - [Server hosts](https://docs.dev.bitskiff.com/docs/guides/server-hosts/): Run the host on your own server, and let the host's display only draw what the server sends it. - [No build step](https://docs.dev.bitskiff.com/docs/guides/script-tag/): Run the host or client SDK in a browser with no build step. - [Transports](https://docs.dev.bitskiff.com/docs/guides/transports/): Turn on peer for lower latency. ## Examples - [Cat and mouse](https://docs.dev.bitskiff.com/docs/guides/examples/cat-and-mouse/): Two clients join, each picks a role and confirms, and the game starts once both have confirmed different roles. - [A queue and four slots](https://docs.dev.bitskiff.com/docs/guides/examples/queue-and-slots/): A venue host with four playing slots and any number of clients waiting. - [A poll with a reveal](https://docs.dev.bitskiff.com/docs/guides/examples/poll-and-reveal/): A presenter's host shows one question at a time, any number of clients answer from their devices, and the host reveals the tally when it chooses. ## Operate - [Session lifecycle](https://docs.dev.bitskiff.com/docs/guides/lifecycle/): A session moves through five phases, and only one of them is an end. - [Limits and capacity](https://docs.dev.bitskiff.com/docs/guides/limits/): Every number a project runs into, what it refuses, and what clears it. - [Webhooks](https://docs.dev.bitskiff.com/docs/guides/webhooks/): A project's webhook is one signed HTTP request per event, so your backend learns a quota is close or crossed without polling for it. - [Usage-based billing](https://docs.dev.bitskiff.com/docs/guides/usage-based-billing/): Bill your own customers on what their sessions used, from the usage records Bitskiff keeps. - [Unattended hosts](https://docs.dev.bitskiff.com/docs/guides/unattended-hosts/): A host with nobody standing at it -- signage in a lobby, a bot, a dedicated game host -- has one job: keep a session open. - [Credentials](https://docs.dev.bitskiff.com/docs/guides/credentials/): A credential is how a request proves it may act on your project. - [One session per user](https://docs.dev.bitskiff.com/docs/guides/one-session-per-user/): Let each of your users run one session at a time, with a way to end the one that is stuck. - [Console](https://docs.dev.bitskiff.com/docs/guides/console/): The console is where you create a project, mint the keys a host signs in with, and watch the sessions that project has open. ## Reference - [@bitskiff/host](https://docs.dev.bitskiff.com/docs/packages/host/): The Bitskiff host SDK for a browser page or an Electron renderer. - [@bitskiff/host-node](https://docs.dev.bitskiff.com/docs/packages/host-node/): The Bitskiff host SDK for a headless Node 22 process. - [@bitskiff/client](https://docs.dev.bitskiff.com/docs/packages/client/): The Bitskiff client SDK for a browser page. - [@bitskiff/ui-kit](https://docs.dev.bitskiff.com/docs/packages/ui-kit/): Framework-free UI elements for a Bitskiff client page. - [@bitskiff/cli](https://docs.dev.bitskiff.com/docs/packages/cli/): The Bitskiff command-line tool for managing a project. - [REST API](https://docs.dev.bitskiff.com/docs/reference/rest/): Every endpoint the service answers, what may call it, and every error code. - [Changelog](https://docs.dev.bitskiff.com/docs/changelog/): Every release, newest first: what was added, changed, deprecated, removed and fixed.