NOCTURN
Download
Documentation

Run an AI agent on a machine you control

Nocturn is a self-hosted personal AI agent with a built-in CPU miner. One gateway runs on your computer or server, you drive it from the terminal, the desktop app, or your chat apps, and it asks before doing anything risky. These pages cover all of it, from the first install to the HTTP API.

What this website is

nocturnh.com is the product page and documentation for Nocturn. It is a static site. No agent runs here, no account exists here, and nothing you type on this site is sent to a server. The home page shows what Nocturn does, with a scripted demo that calls no model and no tool, and this page explains how to use it.

01Public site

The page you are reading, served from Cloudflare. The Connect wallet button only asks your browser wallet to switch to Robinhood Chain. Nothing is signed and nothing is sent.

02Your dashboard

The same page, served by your own gateway at 127.0.0.1:18790 with a private token. There it also edits the Trusted by list and links a wallet to your miner.

03The product

Nocturn itself is an npm package: a gateway, a CLI, chat channel adapters, a scheduler, a miner, and a pool server. It lives on your machine, never on this site.

So, if you came here wondering what the site does: it tells you about Nocturn and gives you the install command. The real work happens after you run that command on your own computer or server.

i

The link printed by nocturn dashboard contains your token. Treat it like a password and never paste it anywhere public.

Overview and architecture

Everything is one Node process called the gateway, plus a thin CLI that talks to it over HTTP. There is no database and no cloud account. State is JSON files in one folder.

The parts

Gateway

An HTTP server on 127.0.0.1:18790. Serves the dashboard, exposes the API, streams events, and owns everything below.

Agent

The loop that sends your conversation to the model, runs the tools it asks for, and pauses for approval when a tool needs it.

CLI

nocturn. Starts and stops the gateway, chats, manages channels, jobs, memory, skills, and config by calling the API.

Channels

Telegram, Discord, and Slack adapters. Each inbound chat becomes a session; replies and approval questions go back to the same chat.

Scheduler

Cron jobs that run a prompt on a schedule and can deliver the reply to a chat.

Tools

Files, shell, web fetch, headless browser, memory, skills, schedules, and outbound messages, each with its own permission policy.

Miner

nocturn mine. Hashes SHA-256 on worker threads, auto-tunes thread count by temperature, and reports shares to a pool.

Pool

nocturn pool run. Hands out jobs each round, verifies shares, and splits the round reward by work done.

How a message flows

  1. You send textFrom nocturn chat, the dashboard, a Telegram message, or a cron job. It lands on POST /api/sessions/:id/messages.
  2. The agent calls the modelAnthropic by default, with adaptive thinking, or any OpenAI-compatible endpoint such as Ollama. Text streams out as events while it is generated.
  3. The model asks for toolsEach tool call is validated, then checked against its policy. auto runs now, ask waits for you, deny is refused.
  4. You approve or denyIn the terminal, with nocturn approvals, in the dashboard, or by replying /approve in the chat that started the run. A question times out after 10 minutes.
  5. Results go back to the modelUp to 40 steps per turn. When the model stops asking for tools, the final text is the reply, and the whole conversation is saved to disk.

The data folder

Everything lives in ~/.nocturn (or wherever NOCTURN_HOME points). Keys are stored in plain text. Never commit or share this folder.

~/.nocturn/
├── config.json      provider, model, keys, persona, policies, channels
├── token            the bearer token for the API and the dashboard link
├── memory.json      saved memories, one entry per line of the system prompt
├── jobs.json        cron jobs with their last run and status
├── partners.json    the Trusted by list shown on the home page
├── wallet.json      the signed wallet proof, if you linked one
├── miner.json       miner name, pool address, pool token
├── pool.json        accounts and balances, only if you host a pool
├── gateway.pid      pid of the background gateway
├── gateway.log      its log, read with nocturn gateway logs
├── browser/         the headless browser profile
├── sessions/        one JSON file per conversation
└── workspace/       the only folder the file tools can touch
    └── skills/      one folder per skill, each with SKILL.md

Install

Nocturn needs Node 22 or newer and a model: a Claude API key, or any OpenAI-compatible endpoint. Install it once from npm, then run the guided setup.

Linux and macOS

$ npm install -g @morpheapp/nocturn
$ nocturn onboard

Windows

PowerShell blocks the .ps1 shims that npm installs, so call the .cmd versions.

$ npm.cmd install -g @morpheapp/nocturn
$ nocturn.cmd onboard

If you would rather use the short names, allow local scripts once for your account and open a new terminal:

$ Set-ExecutionPolicy -Scope CurrentUser RemoteSigned

What onboard does

  1. Picks a provideranthropic or an OpenAI-compatible endpoint. For Anthropic it asks for the key and a model name; for OpenAI it asks for the base URL, model name, and an optional key.
  2. Optionally connects TelegramPaste a bot token from BotFather. You can add Discord and Slack later with nocturn channels add.
  3. Starts the gatewayIn the background, and offers to install it as a login service so it survives reboots.

Check that everything is healthy with nocturn doctor, then talk to it with nocturn chat.

Desktop and mobile apps

You do not have to live in the terminal. The Download section of the home page has installers for each platform.

Nocturn Desktop · Windows and macOS

An Electron app in the desktop/ folder of the repository. It starts the gateway when it launches and opens the dashboard in its own window, so one double-click gives you the whole product. Windows gets an .exe installer, macOS a .dmg.

Nocturn for Android

Built as an .apk from the mobile/ folder through GitHub Actions. It is a remote client: you enter the address and token of a gateway you run elsewhere, reached through an SSH tunnel, and the dashboard opens in the app.

Installable web app

Open /panel.html on your own gateway and add it to the home screen of any phone. Like the Android app, it talks to a gateway on a computer or server.

!

The gateway itself needs Node and runs on a computer or a server, never on the phone. The mobile apps control a gateway; they do not contain one.

Command line

Every command calls the gateway's API with the token from ~/.nocturn/token. If the gateway is not running, most commands tell you so. Add --json to any listing command for machine-readable output, and --version prints the version.

Setup

CommandWhat it does
nocturn onboardGuided setup: provider, key, model, optional Telegram, gateway start, optional login service. nocturn setup is an alias.
nocturn doctorChecks Node version, dependencies, the state folder, the gateway, the model key, and each enabled channel. Exits 1 if something fails.
nocturn config get [key]Prints the config with secrets redacted. Dotted keys work: nocturn config get channels.telegram.
nocturn config set <key> <value>Sets one key. Values that parse as JSON are stored typed, so true is a boolean. Channel changes need nocturn gateway restart.
nocturn dashboardPrints the private dashboard link with the token, and the SSH tunnel command for servers.

Gateway

CommandWhat it does
nocturn gateway runRuns in the foreground. Ctrl+C stops it.
nocturn gateway startStarts a detached background process and writes gateway.pid. Logs go to gateway.log.
nocturn gateway stop / restartStops the background process by pid, or stops and starts it.
nocturn gateway statusSame as nocturn status.
nocturn gateway logs [--lines N] [-f]Prints the last 50 lines, or N. -f or --follow keeps printing new lines.
nocturn gateway install / uninstallRegisters a login task on Windows (schtasks) or a user service on Linux (systemd --user).
nocturn statusGateway, model readiness, channel status, session and job counts, pending approvals and pairing requests.

Talking to the agent

CommandWhat it does
nocturn chat [--session id]Interactive chat in the terminal. Starts the gateway if needed. /new starts a fresh conversation, /sessions lists them, /status shows status, /exit leaves, Ctrl+C stops a running task. Tool calls are shown as they happen and approvals are asked inline.
nocturn agent -m "text" [--session id] [--json]One task, streamed reply, then exit. With --json prints { sessionId, reply }. Without a terminal, approvals are printed with the id to approve from elsewhere.
nocturn sessionsLists conversations with origin, title, and last update.
nocturn approvals listShows tool calls waiting for you.
nocturn approvals approve <id> / deny <id>Answers one of them.
nocturn message send --to <target> -m "text"Sends a message through a connected channel. Targets look like telegram:123, discord:<channel>, slack:<channel>.

Channels and pairing

CommandWhat it does
nocturn channels listStatus of each channel and how many senders are allowed.
nocturn channels add telegram [--token t]Saves the bot token and turns the channel on. Without the flag it asks, with input hidden.
nocturn channels add discord [--token t]Same for a Discord bot token.
nocturn channels add slack [--bot-token xoxb] [--app-token xapp]Slack needs both tokens: a bot token and an app-level token with Socket Mode.
nocturn channels remove <name>Turns the channel off. The token stays saved.
nocturn pairing listSenders waiting to be let in, with their 6-digit codes.
nocturn pairing approve <code> / deny <code>Adds the sender to that channel's allow list, or drops the request.

Automation and knowledge

CommandWhat it does
nocturn cron listJobs with schedule, on/off, last run and status.
nocturn cron add --name n --cron "0 8 * * 1-5" -m "prompt" [--deliver telegram:123]Adds a job. The cron expression is validated before saving.
nocturn cron run|enable|disable|rm <id>Runs one now, toggles it, or deletes it.
nocturn memory list|add <text>|rm <id>The facts injected into every system prompt.
nocturn skills list|rm <name>Installed skills. Add one by creating a folder, see Skills.

Mining and website

CommandWhat it does
nocturn mine [--threads N] [--pool URL]Mines in this terminal until Ctrl+C. Needs a terminal because a person answers the check.
nocturn mine balancePrints your NOCT balance from the pool.
nocturn pool run [--port 18800] [--host 0.0.0.0] [--file path] [--trust-proxy]Runs a pool server. Put it behind HTTPS before sharing the address.
nocturn site build [--out folder]Exports the landing page with your Trusted by list for a static host.
nocturn helpThe full list, in the terminal.

Environment

NOCTURN_PORT changes the gateway port (default 18790). NOCTURN_HOME moves the state folder. Both must be set for the CLI and the gateway alike, because the CLI finds the gateway through them.

Chat channels

Connect a bot and Nocturn answers from your phone. Each chat becomes its own session, named telegram:<chat>, discord:<channel>, or slack:<channel>, with its own history.

Telegram

  1. Create a bot with @BotFather and copy its token.
  2. Run nocturn channels add telegram and paste it.
  3. Send your bot any message. It replies with a pairing code.
  4. Run nocturn pairing approve <code>. From now on that account can talk to Nocturn.

The adapter long-polls getUpdates and only accepts private chats. Replies are split at 4,000 characters.

Discord

  1. Create an application in the Discord developer portal, add a bot, and enable the Message Content intent.
  2. Invite it to your server with permission to read and send messages.
  3. Run nocturn channels add discord with the bot token.
  4. DM the bot, or mention it in a channel. Approve the pairing code.

The adapter connects to the Discord gateway over WebSocket with the guild messages, direct messages, and message content intents. In servers it only reacts when mentioned. Replies are split at 1,900 characters and never ping anyone.

Slack

  1. Create a Slack app with Socket Mode on. Add the app_mentions:read, chat:write, im:history, and im:read scopes, and subscribe to app_mention and message.im events.
  2. Install it to the workspace. Copy the bot token (xoxb-) and an app-level token (xapp-) with connections:write.
  3. Run nocturn channels add slack and paste both.
  4. DM the app or mention it in a channel. Approve the pairing code.

Pairing

Unknown senders never reach the agent. The first message from a new sender gets a 6-digit code and a note saying this Nocturn is private. The request shows up in nocturn pairing list, nocturn status, and the dashboard. At most 20 requests wait at once; after that new strangers are ignored until you clear some. Approving writes the sender id to channels.<name>.allow in the config.

Approvals from chat

When a run that started in a chat needs permission, the question is sent to that same chat, with the first 300 characters of the tool input:

Allow shell?
{"command":"systemctl restart app"}

Reply /approve or /deny

Reply /approve or /deny. If nothing is waiting, the bot says so. The dashboard and nocturn approvals can answer the same question.

Tools and permissions

The model gets twelve tools. Each has a policy in config.policies: auto runs without asking, ask waits for your answer, deny refuses and tells the model the tool is disabled.

ToolDefaultWhat it does
read_fileautoReads a UTF-8 file from the workspace. Output is clipped at 50,000 characters.
list_filesautoLists a workspace directory. Folders end with /.
memory_searchautoKeyword search over saved memories. An empty query lists everything.
memory_saveautoSaves a durable fact about you or your work.
load_skillautoReturns the full SKILL.md of an installed skill.
write_fileaskCreates or overwrites a file in the workspace, creating folders as needed.
edit_fileaskReplaces one exact occurrence of text. Fails if the text occurs zero or several times.
shellaskRuns a command in the workspace: PowerShell on Windows, sh elsewhere. Two-minute timeout.
web_fetchaskFetches a public http(s) URL and returns its text, with HTML tags stripped. Follows up to 5 redirects, 30-second timeout.
browseraskDrives a headless Chrome or Edge: navigate, text, click, type by CSS selector, and screenshot into the workspace.
schedule_taskaskCreates a cron job.
send_messageaskSends text through a connected channel.

Change a policy with nocturn config set policies.shell auto, or in the dashboard. Valid values are auto, ask, and deny.

The approval flow

  1. Validation firstTool inputs stream in eagerly and are not validated by the API, so Nocturn checks required fields, types, and enums itself before anything runs. A bad input is reported to the model without running.
  2. Then the policyAn ask tool emits an approval event with the tool name and full input. The run pauses.
  3. You answer anywhereTerminal prompt, nocturn approvals approve <id>, the dashboard, or /approve in the chat. A denied or expired request (10 minutes) tells the model the owner did not approve, and the model is instructed not to work around it.

Safety model

  • The gateway listens on 127.0.0.1 only, requires the bearer token for every API call, and rejects requests whose Host or Origin is not local. That blocks DNS rebinding and cross-site requests.
  • File tools resolve symlinks and refuse any path that leaves ~/.nocturn/workspace.
  • Web and browser tools resolve the hostname first and refuse private, loopback, link-local, and multicast addresses, including IPv4-mapped IPv6. The agent cannot reach your gateway, your LAN, or cloud metadata endpoints.
  • The system prompt tells the model that web pages, files, tool output, and relayed chat messages are data, not instructions from you.
  • Secrets are never returned by the API. The config endpoint redacts them, and a blank value in an update keeps the stored secret.
!

The shell tool is not sandboxed. An approved command runs with your user's full permissions, in the workspace folder but able to reach anything your user can. Read each command before allowing it, and do not set shell to auto on a machine with data you care about.

Skills, memory, and schedules

Skills

A skill is a folder in ~/.nocturn/workspace/skills/ with a SKILL.md inside. The name must be lowercase letters, digits, and dashes. Its description is listed in every system prompt; the body is loaded only when the model calls load_skill, so you can keep long instructions without paying for them on every turn.

---
name: weekly-update
description: How to write the Monday update for the team
---

Read notes/week.md, group the items by project, and write
briefs/update.md with three sections: shipped, in progress, blocked.
Keep each line under 15 words.

Create skills by hand, with POST /api/skills, or in the dashboard. Remove one with nocturn skills rm weekly-update.

Memory

Memories are short facts, one per entry, stored in memory.json and injected into every system prompt under “Saved memories”. The model can save them with memory_save and search them with memory_search; you can manage them with nocturn memory.

$ nocturn memory add "I prefer short answers"
$ nocturn memory list
$ nocturn memory rm <id>

Cron jobs

A job runs a prompt on a 5-field cron schedule, in the server's local time. Each run is its own session named cron:<job id>, so a job keeps its history across runs. If the job has a deliver target, the reply is sent there.

$ nocturn cron add --name brief --cron "0 8 * * 1-5" -m "plan my day" --deliver telegram:42
FieldRangeExamples
minute0 to 590, */15, 0,30
hour0 to 238, 9-17, */2
day of month1 to 31*, 1, 1-7
month1 to 12*, 6-8
weekday0 (Sunday) to 61-5, 0,6

Lists, ranges, and steps are supported; names like MON are not. The scheduler checks once a minute and only fires enabled jobs. nocturn cron run <id> fires one immediately, which is the easiest way to test a prompt.

HTTP API

The CLI and the dashboard use this API, and so can your own scripts. Base URL http://127.0.0.1:18790/api. Every call needs Authorization: Bearer <token> with the token from ~/.nocturn/token. Bodies and responses are JSON. Bodies are limited to 1 MB.

$ TOKEN=$(cat ~/.nocturn/token)
$ curl -s http://127.0.0.1:18790/api/state -H "Authorization: Bearer $TOKEN"
!

Requests are refused with 403 unless the Host header is 127.0.0.1, localhost, or [::1], and the Origin header is either absent or matches. A wrong token gets 401. Errors come back as { "error": "message" }.

State and events

RouteBodyReturns
GET /api/state—Redacted config, tool names, sessions, pending approvals, running sessions, channel status, pairing requests, jobs, skills, memory, and which credentials are present.
GET /api/events—A Server-Sent Events stream. Every event is a JSON object with a type. A comment ping is sent every 25 seconds.
PUT /api/configAny subset of the configNew state. Unknown keys are ignored, types must match, blank secrets keep the old value. Changing channels restarts the adapters.

Sessions and approvals

RouteBodyReturns
POST /api/sessions—201 with the new session { id, origin, title, messages, updated }.
GET /api/sessions/:id—The full session including message history, or 404.
DELETE /api/sessions/:id—Stops a running turn and deletes the file.
POST /api/sessions/:id/messages{ "text": "..." }202 at once. The run happens in the background; watch /api/events. A session that does not exist yet is created with this id, which is how chat sessions start.
POST /api/sessions/:id/stop—Aborts the running turn.
POST /api/approvals/:id{ "approved": true }Resolves a pending approval, or 404.

Channels, jobs, skills, memory

RouteBodyReturns
POST /api/pairing/:code{ "approve": true }Allows or drops the sender. New state.
POST /api/allow{ "channel", "sender" }Removes a sender from the allow list. New state.
POST /api/message{ "target", "text" }Sends through a connected channel. 400 if the channel is not connected.
POST /api/jobs{ "name", "cron", "prompt", "deliver" }201 with the new state. 400 on a bad cron.
POST /api/jobs/:id/run—202. Fires the job now.
PATCH /api/jobs/:id{ "enabled": false }Toggles the job.
DELETE /api/jobs/:id—Removes it.
POST /api/skills{ "name", "description", "instructions" }Writes skills/<name>/SKILL.md. 201 with the new state.
DELETE /api/skills/:name—Deletes the folder.
POST /api/memory{ "text" }201 with the new state. Up to 5,000 characters.
DELETE /api/memory/:id—Forgets it.

Wallet and partners

RouteBodyReturns
GET /api/wallet—{ address } if a wallet is linked, else {}.
POST /api/wallet{ "address", "message", "signature" }Verifies the personal_sign proof and stores it. 400 if the signature does not match.
DELETE /api/wallet—Unlinks.
GET /api/partners—The Trusted by list.
POST /api/partners{ "name", "logo" }Logo is a data URL: PNG, JPEG, or WebP, under 256 KB, checked by signature. Up to 40 entries.
DELETE /api/partners/:id—Removes one.

Event types

Everything on /api/events carries a sessionId where it applies.

TypeFieldsMeaning
turn_start / step_start—A turn began; each model call within it began.
texttextA streamed piece of the reply.
thinkingtextA streamed piece of the model's summarized thinking (Anthropic only).
tool_startid, name, inputThe model asked for a tool.
approvalid, tool, inputWaiting for you. Answer with POST /api/approvals/:id.
approval_resolvedid, approvedSomeone answered, or it timed out.
tool_resultid, name, content, isErrorWhat the tool returned.
turn_end—The reply is complete.
turn_errormessageThe turn failed or was stopped.
sessions_changed, channels_changed, jobs_changed—Refresh the matching part of /api/state.

Mining

nocturn mine hashes SHA-256 on your CPU and reports shares to a pool. Balances are in NOCT, a number kept by the pool server. NOCT is not a coin on a blockchain, cannot be withdrawn, and has no guaranteed value. Only mine on a machine you own or have permission to use.

Start mining

$ nocturn mine
$ nocturn mine --threads 4
$ nocturn mine balance
  1. Pick a name3 to 20 characters: letters, digits, dash, underscore. The pool returns a token that is saved in miner.json. The default pool comes from the package, or pass --pool https://..., or set NOCTURN_POOL.
  2. Answer the checkA small addition, asked once when mining starts. Three wrong answers end the session.
  3. HashBy default all cores but one. The screen shows hashrate, job and round progress, estimated share of the round reward, last payout, balance, hardware, temperature, and what auto-tune is doing.

Press Ctrl+C to stop. Mining only runs while that terminal is open; on a server use tmux so it survives disconnects. The check lasts as long as the miner keeps talking to the pool. If contact is lost for over 30 minutes, mining pauses and the check is asked again.

Auto-tune

Every 15 seconds the miner reads CPU temperature (Linux hwmon, or Windows ACPI thermal zones), GPU temperature through nvidia-smi when available, and free memory. At 85°C or above it idles one thread. Under 8% free memory it idles one thread. Once it is 75°C or cooler for a minute, it brings one back, up to the number you asked for. Virtual servers often expose no sensors, and then it simply keeps your thread count.

Hosting a pool

$ nocturn pool run --host 0.0.0.0 --port 18800 --trust-proxy

Put it behind an HTTPS reverse proxy, then set nocturn.pool in package.json to its address. --trust-proxy reads X-Forwarded-For so the limit of 5 sign-ups per address per hour works behind the proxy. The pool keeps accounts in pool.json, or the file you pass with --file.

Each round lasts 60 seconds and pays 100.00 NOCT, split by work: a share at difficulty d counts as 2d. Difficulty is per miner, starting at 20 bits, raised by one when shares arrive faster than every 2.5 seconds, lowered by one after 20 seconds without a share, between 8 and 44. Duplicate and stale shares are rejected, and a miner is limited to 20 shares per second.

Pool routePurpose
POST /register{ name } → { name, token }. The only route without a token.
POST /check, /check/answerGets a question, answers it. Errors: wrong_answer.
GET /jobSeed, difficulty, round timing, your work, balance, wallet. Error check_required until the check is passed.
POST /share{ seed, nonce } → { accepted, reason } plus a fresh job. Error slow_down over the rate limit.
GET /balance{ cents, wallet }.
POST /walletStores a verified wallet proof on the account.

Linking a wallet

On your own dashboard, Connect wallet asks MetaMask (or any wallet that injects window.ethereum) to switch to Robinhood Chain (chain id 4663), then to sign this message with personal_sign:

Nocturn wallet link
Wallet: 0xYourAddress
Issued: 2026-11-03T12:00:00.000Z

The gateway recovers the signer from the signature and refuses anything that does not match the address. No private key is ever sent. The proof is stored in wallet.json and sent to the pool the next time you run nocturn mine, so the pool can show the wallet on your account. On the public site the button only switches networks and signs nothing.

Configuration and servers

config.json

Read with nocturn config get, change with nocturn config set, the dashboard, or PUT /api/config. Unknown keys are dropped and types must match the defaults.

KeyDefaultMeaning
provideranthropicanthropic or openai (any OpenAI-compatible endpoint).
modelclaude-opus-5-5Anthropic model id. Nocturn enables server-side fallback for the Claude 5 family.
efforthighAnthropic effort level.
anthropicKeyemptyAPI key. ANTHROPIC_API_KEY in the environment also works.
openaiBaseUrlhttp://localhost:11434/v1Ollama by default. Any /chat/completions endpoint with streaming and tools.
openaiModel, openaiKeyemptyModel name and optional key for that endpoint.
persona“You are Nocturn, …”The first paragraph of the system prompt.
policies.<tool>see Toolsauto, ask, or deny per tool.
channels.<name>offenabled, tokens, and the allow list of sender ids.

Environment variables

VariableEffect
NOCTURN_PORTGateway port, default 18790. The CLI reads it too.
NOCTURN_HOMEState folder, default ~/.nocturn.
NOCTURN_BROWSERPath to a Chrome or Edge executable for the browser tool, if it is not in a standard location.
NOCTURN_POOLPool address for nocturn mine, overridden by --pool.
NOCTURN_TELEGRAM_APIAlternate Telegram API base, for a local Bot API server.
ANTHROPIC_API_KEY, ANTHROPIC_BASE_URLPicked up by the Anthropic SDK when the config has no key.
NO_COLORTurns off terminal colors.

On a server

$ nocturn onboard
$ nocturn gateway install
$ loginctl enable-linger $USER

On Linux this writes a systemd --user unit named nocturn-gateway with Restart=on-failure, and enable-linger keeps user services running after you log out. On Windows it creates a scheduled task that starts at login.

The gateway still listens on 127.0.0.1 only. To open the dashboard from your own computer, tunnel to it, then open the link from nocturn dashboard:

$ ssh -L 18790:127.0.0.1:18790 user@your-server

The same tunnel is what the mobile apps and the installable web app use: they talk to 127.0.0.1:18790 on the phone, which the tunnel forwards to the server.

Website deployment

The landing page in public/ is both the dashboard your gateway serves and the public site. nocturn site build copies it into a folder a static host can serve, writes partners.json with your Trusted by list, and adds a _headers file with the same Content-Security-Policy the gateway sends.

$ nocturn site build --out site
$ npx wrangler deploy

On Windows PowerShell use npx.cmd wrangler deploy, since PowerShell blocks npx.ps1 by default. wrangler.jsonc serves site/ as a Cloudflare Worker with static assets on nocturnh.com and www.nocturnh.com. Any other static host works: upload the folder and keep the headers.

The public site has no gateway, so the Connect wallet button only connects, the Trusted by section comes from the file written at build time, and the numbers in the “Remembers how you like things” tile stay at zero. The token contract and the official X account are published from the admin page at /admin, which needs the admin password set on the Worker.

FAQ and troubleshooting

Start with nocturn doctor. It checks Node, dependencies, the state folder, the gateway, the model key, and each enabled channel, and prints the fix for anything that fails.

“The gateway is not running.”

Run nocturn gateway start. If that fails, read nocturn gateway logs. A common cause is a missing model key: run nocturn onboard.

“Port 18790 is already in use.”

Another gateway, or another program, is on that port. Check with nocturn gateway status. To run on a different port, set NOCTURN_PORT for both the gateway and the CLI.

“npx : File npx.ps1 cannot be loaded because running scripts is disabled.”

That is the PowerShell execution policy, not Nocturn. Use npx.cmd, npm.cmd, and nocturn.cmd, or run Set-ExecutionPolicy -Scope CurrentUser RemoteSigned once.

“No model is set up yet.”

Run nocturn onboard, or set ANTHROPIC_API_KEY in the environment of the gateway process. For the OpenAI-compatible provider, openaiModel must be set.

“No Chrome or Edge found.”

The browser tool looks in the usual install locations. Point NOCTURN_BROWSER at the executable, or install Chrome. The profile is kept in ~/.nocturn/browser.

My bot does not answer on Telegram.

Check nocturn channels list: the status should be connected. Then check nocturn pairing list, because new senders are blocked until you approve their code. Only private chats are accepted on Telegram.

A tool was denied and the model gave up.

That is by design. The approval question waits 10 minutes; if nobody answers, it counts as denied and the model is told. Answer faster, or set that tool to auto if you trust it.

“Stopped after 40 steps without finishing.”

One turn may make at most 40 model calls. Break the task into smaller prompts, or add a skill with clearer instructions.

“The pool does not know this account.”

The pool was reset or you point at a different pool than the one that issued the token. Delete ~/.nocturn/miner.json and run nocturn mine to sign up again.

“nocturn mine needs a terminal.”

A person has to answer the check, so the miner refuses to run without an interactive terminal. On a server, run it inside tmux and detach.

Can I use a local model?

Yes. Pick the OpenAI-compatible provider in nocturn onboard, keep the Ollama base URL, and enter the model name. Prompts never leave the machine. The model needs tool-calling support to use tools.

Where are my keys?

In ~/.nocturn/config.json, in plain text, with file mode 600 where the OS supports it. The API never returns them.

How do I run the tests?

npm test in the repository. The tests use a fake model server, so they need no key and spend nothing.

© Nocturn · nocturnh.com · Needs Node 22 or newer · Your data stays in ~/.nocturn