# Gateway operations

> Choose an owner, inspect it, recover from a crash, apply config changes, and know what survives a restart.

Source: https://nodecode.ai/docs/operations
Updated: 2026-10-06

The gateway is the local server that shells attach to. The process that serves it owns the organism, a running Nodecode.

## Choose an owner

One process owns a home's store at a time. The home is `~/.nodecode/`. A shell is the terminal UI.

| Owner | Start it | Lives until | Restarted after a crash |
| --- | --- | --- | --- |
| A shell | `nodecode` | You quit the shell. | By the attached shells. See Recover. |
| The background gateway | `nodecode gateway on` | You run `nodecode gateway off`. | By the service manager, after 5 s. |
| A headless process | `nodecode serve` | You stop it. | By the attached shells. With no shell attached, nothing restarts it. |

Later shells attach to the owner. See [The organism](https://nodecode.ai/docs/organism).

Use the background gateway for bots, cron jobs and the link. See [The gateway](https://nodecode.ai/docs/gateway).

Windows: no background gateway. Use `nodecode serve` in a terminal you keep open.

## Inspect

```sh
nodecode gateway
nodecode gateway logs
nodecode gateway logs --follow
```

| Status line | Do this |
| --- | --- |
| `off` | Run `nodecode gateway on`. |
| `on, but it failed` | Run `nodecode gateway logs`. Then `nodecode gateway restart`. |
| `on, restarting after it exited` | Run `nodecode gateway logs`. |
| `on, but stopped` | Run `nodecode gateway restart`. |
| `waiting` | A shell owns the organism. The gateway takes over when that shell closes. |
| `unavailable`, naming a missing user manager | Run `sudo loginctl enable-linger $USER`. Then `nodecode gateway on`. |

Inside a shell:

| Command | Shows |
| --- | --- |
| `/gateway` | The same status. |
| `/doctor` | What is missing, with a remedy for each item. |
| `/cells` | Each cell folder: loaded, failed, skipped files, standing notices. |

`/doctor` checks these:

- The model the shell will use.
- Cell folders that failed, with the reason.
- The store, read back whole.
- The build on disk.
- Free disk space.
- `config.jsonc` and every declared section.
- The default provider's key.
- A waiting release.

Log files:

| File | Holds |
| --- | --- |
| The user journal (Linux) | The background gateway's output. Read it with `nodecode gateway logs`. |
| `~/Library/Logs/nodecode/nodecode-gateway.log` (macOS) | The same. |
| `~/.nodecode/history.db.stdio.log` | Stdout and stderr of a process that runs a shell. This is the boot log. |
| `~/.nodecode/history.db.resurrect.log` | Output of replacement owners spawned after a crash. |

Set `NODECODE_PHASE_LOG` to a file path to log one line per boot phase.

The web page shows the same under Control, in the Gateway and Logs tabs.

## Recover

### Dirty death

A dirty death: the owner died, the lock is free, `history.db.owner` is still there.

1. Each attached shell sees the connection drop.
2. With the background gateway on, the shell asks the service manager to start it.
3. Otherwise the shell spawns a detached `nodecode serve --store PATH`.
4. One candidate wins the lock. It publishes its port. The others exit.
5. Every shell attaches to the winner.

| Limit | Value |
| --- | --- |
| Spawns per outage, per shell | 3 |
| Time between spawns | 30 s |

After the third spawn the shell stops spawning. It keeps watching for an owner. Start one by hand:

```sh
nodecode serve
```

A clean stop is never respawned. With no background gateway, an attached shell takes the organism over.

### Interrupted turns

A turn that was running when the owner died is resumed at the next boot.

| Rule | Detail |
| --- | --- |
| Unanswered tool calls | Each gets the result `interrupted by process restart`. |
| Resume attempts | 3 boots. After that the turn is recorded as failed. |
| Cost | A resumed turn calls the provider again. It spends tokens. |
| Background evals | Lost. Their output is live only. |

## Apply config changes

A cell is a folder of code under `~/.nodecode/cells/`. It reads its config section when it starts.

| Change | Apply with |
| --- | --- |
| A cell's section | `(restart-cells)` |
| One cell's section | `(restart-cells "folder")` |
| Anything, background gateway | `nodecode gateway restart` |
| Anything, shell owner | Quit the shell. Run `nodecode` again. |
| A cell turned off | A restart. Its code stays loaded until then. |

`restart-cells` stops the cells, reads the config again and starts them. The agent runs it through `eval`:

```lisp
(restart-cells)
```

| Form | Does |
| --- | --- |
| `(config-get '("a" "b"))` | Reads the config at a path. A secret reads as `"[set]"`. |
| `(config-set '("a" "b") value)` | Writes one member. Keeps every comment. Answers the diff. |

See [Config](https://nodecode.ai/docs/config).

## What survives a restart

| Survives | Where |
| --- | --- |
| Sessions, turns, tool results, model pins, checkpoints | `~/.nodecode/history.db` |
| Cron jobs | `~/.nodecode/history.db` |
| The layer: the definitions the agent wrote and kept | `~/.nodecode/cells/<name>/` |
| Memory | `~/.nodecode/memory/` |
| Skills | `~/.nodecode/skills/` |
| The operator token | `~/.nodecode/operator-token` |
| The gateway's port, when it is still free | `~/.nodecode/history.db` |
| The link switch and allowed browsers | `~/.nodecode/link/state.json` |
| The gateway off mark | `~/.nodecode/gateway-off` |

| Lost | Why |
| --- | --- |
| Background evals and their output | Live only. |
| Values set with `setf` | Only defining forms are kept. |
| Hooks added with `(hook ...)` | Live only. `define-hook` is kept. |
| A held definition that never ran | It is written only after its first clean run. |

Back up the home with `/backup`. It writes one archive under `~/.nodecode/backups/`. The archive holds your keys.

Restore an archive as a profile:

```sh
nodecode profile import FILE --name NAME
```
