# Files

> Every file and folder Nodecode keeps: the home, the cache, and the folder it leaves in each project.

Source: https://nodecode.ai/docs/files
Updated: 2026-10-08

Nodecode keeps a home for each profile, a cache every profile shares, and an undo folder in each project it edits.

## The home

The home is `~/.nodecode/`. This one has had an afternoon: four turns, one key, one `/backup` and one profile. In it are the store and its lock, the layer of kept definitions, the knowledge cell of memories and skills, a generation per keep, and two files that are keys.

```text
~$ tree -a -L 2 --dirsfirst --noreport -I .git ~/.nodecode
/home/you/.nodecode
├── backups
│   ├── nodecode-default-2026-10-08-211925.json
│   └── nodecode-default-2026-10-08-211925.tar.gz
├── cells
│   ├── .locks
│   ├── you
│   └── you-memory
├── generations
│   ├── 1.json
│   ├── 2.json
│   └── 3.json
├── profiles
│   └── work
├── auth.json
├── cells-named
├── composer-catalogs.sexp
├── composer-history
├── config.jsonc
├── history.db
├── history.db-shm
├── history.db-wal
├── history.db.lock
├── history.db.owner
├── history.db.stdio.log
├── operator-token
└── usage.jsonl
```

A profile has a home of its own under `~/.nodecode/profiles/<name>/`, laid out the same way.

## Settings

Files you or the agent write on purpose. A profile and an export carry them.

| Entry | Holds |
| --- | --- |
| `config.jsonc` | The settings. See [Config](https://nodecode.ai/docs/config). |
| `AGENTS.md` | Your rules for every session. See [Instruction files](https://nodecode.ai/docs/instructions). |
| `SOUL.md` | The persona channel bots speak in. |
| `themes.json` | Your own themes. |
| `auth.json` | Provider keys, at `api_keys.<id>.key`. `/connect` writes it. |
| `secrets/` | Secrets pasted into setup, one file each. |
| `cells/` | Cell folders. See [Cells](https://nodecode.ai/docs/cells). |
| `cells/<you>/` | The layer: the definitions the agent kept, one file each. A git repository. |
| `cells/<you>-memory/` | The knowledge cell: memories and skills, kept as definitions. Read by the index, never loaded. |
| `profile.jsonc` | The profile's manifest: what this profile is. |

`<you>` is git's `user.name` in lowercase, each run of other characters one hyphen: `Mike Smith` is `mike-smith`. Without one it is `USER`, then `you`.

Mistakes to avoid:

- Writing a key into `config.jsonc` as `api_key`. An export and a new profile carry `config.jsonc`, key and all, and no mode is forced on it. Instead: `/connect`. The key goes in `auth.json`, 0600, which an export leaves out.
- Keeping `~/.nodecode` in a dotfiles repository. It carries `auth.json`, `operator-token` and the store. Instead: `nodecode profile export NAME PATH`: the settings and the cells, no store, no keys.

**Mistake:**

```text
~$ tar xzOf ~/share.tar.gz .nodecode/config.jsonc | grep api_key
   "api_key": "sk-demo",
```

The plain export, the one meant for sharing, has the key in it.

**Instead:**

```text
~$ nodecode profile export default ~/share2.tar.gz && tar xzf ~/share2.tar.gz -O | grep -c sk-new
exported default to /home/you/share2.tar.gz
0
```

The key `/connect` saved is nowhere in it.

## State

Files Nodecode makes for itself. A new profile starts without them, and an export leaves them out.

| Entry | Holds |
| --- | --- |
| `history.db` | The store: every session and every event. SQLite, with `-wal` and `-shm` beside it. |
| `history.db.lock` | Held by the process that owns the store, for as long as it runs. |
| `history.db.owner` | That process's pid and gateway port, as JSON. |
| `history.db.stdio.log` | The organism's boot log and stray output. |
| `operator-token` | The gateway token. See [Safety and trust](https://nodecode.ai/docs/security). |
| `usage.jsonl` | Each keep, view and call of a memory or skill. The index ranks by it. |
| `generations/` | A manifest per sealed generation, and a restore's markers. |
| `release-pin` | The release a rollback pinned. `nodecode update` lifts it. |
| `keybinds.json` | Key overrides. See [The shell](https://nodecode.ai/docs/shell). |
| `theme-selection` | The theme picked with `/themes`. |
| `composer-history` | Prompts you typed. |
| `composer-catalogs.sexp` | The lists `@` and `/` complete from, as last read. |
| `cells-named` | Shipped cells already named as not installed. |
| `distribution.json` | Where this home was installed from. |
| `gateway-off` | The background gateway's off switch. |
| `import/` | The import's marker and its reports. |
| `hub/` | The cell index, as last read. |
| `cells/.locks/` | Write locks of the knowledge cells. |
| `mcp/` | MCP servers' error logs, `mcp/<name>.stderr.log`. |
| `link/state.json` | This machine's name at its relay, and the browsers let in. |
| `backups/` | `/backup`'s archives, each with a `.json` note. |
| `team/`, `chrome-extension/`, `chrome-screenshots/` | Written by the team and chrome cells. |

## The store

While Nodecode runs, `history.db` is a header and the sessions are in `-wal`. The lock names who owns them: a pid and a port. Every shell you open attaches to that one.

```text
~$ ls -lh ~/.nodecode/history.db*
-rw-r--r-- 1 you you 4.0K Oct  8 21:18 /home/you/.nodecode/history.db
-rw-r--r-- 1 you you  32K Oct  8 21:18 /home/you/.nodecode/history.db-shm
-rw-r--r-- 1 you you 3.6M Oct  8 21:19 /home/you/.nodecode/history.db-wal
-rw------- 1 you you    0 Oct  8 21:18 /home/you/.nodecode/history.db.lock
-rw------- 1 you you   38 Oct  8 21:18 /home/you/.nodecode/history.db.owner
-rw-r--r-- 1 you you  217 Oct  8 21:18 /home/you/.nodecode/history.db.stdio.log
```

```text
~$ cat ~/.nodecode/history.db.owner
{
  "pid": 2212192,
  "port": 37213
}
```

Mistakes to avoid:

- Copying `history.db` while Nodecode runs. You get the header and none of the sessions: `no such table: events`. Instead: `nodecode profile export NAME PATH --whole`, or `/backup`. Both take a whole copy of the store while it runs.
- Deleting `history.db.lock`. A second organism takes the same store on another port. When it stops it deletes `history.db.owner`, and the shells lose the first. Instead: Nothing to clear. The lock goes with the process that holds it, crash or not. `nodecode profile list` shows who holds it.

**Mistake:**

```text
~$ cp ~/.nodecode/history.db ~/copy.db && sqlite3 -list ~/copy.db 'select count(*) from events'
Parse error in 3rd command line argument: no such table: events
```

```text
~$ rm ~/.nodecode/history.db.lock && timeout 6 nodecode serve; echo "exit $?"; cat ~/.nodecode/history.db.owner
cell you: layer, 2 definitions, generation 3
cell you-memory: knowledge, 1 definition
[CP-ISSUE-20260912-001] gateway ready
serving store /home/you/.nodecode/history.db on port 36563 (session "s-U1LGSL8W")
[CP-ISSUE-20260912-002] gateway heartbeat
exit 124
cat: /home/you/.nodecode/history.db.owner: No such file or directory
```

The copy has no tables. The second organism served on its own port, then took the owner file with it.

**Instead:**

```text
~$ nodecode profile export default ~/home.tar.gz --whole && mkdir -p ~/check && tar xzf ~/home.tar.gz -C ~/check && sqlite3 -list ~/check/.nodecode/history.db 'select count(*) from events'
exported default to /home/you/home.tar.gz, its store and keys with it: keep it where you keep passwords
78
```

```text
~$ nodecode profile list
* default  /home/you/.nodecode  serving pid 2212192 port 37213  boots by default
      also carrying cells-named, composer-catalogs.sexp
  work  /home/you/.nodecode/profiles/work
      shares auth.json, cells/you-memory with default
```

The archive's store answers 78 events. The list names the process that holds the lock.

## The layer

Each definition the agent keeps is a file in `cells/<you>/` and a commit, and each keep seals a generation. To go back, roll back to one.

```text
~$ git -C ~/.nodecode/cells/you log --oneline
b453153 (HEAD -> master) word-count — session s-8ZRLUFP8
12d29ea count-lines — session s-8ZRLUFP8
```

```text
~$ nodecode generations
generation 3  current  2026-10-09T04:19:20.188Z  nodecode 0.0.1+370099410
  you layer own b453153  +1 keep since 2
generation 2  2026-10-09T04:18:49.964Z  nodecode 0.0.1+370099410
  you layer own 12d29ea
  added since 1: you
generation 1  2026-10-09T04:18:44.853Z  nodecode 0.0.1+370099410
```

Mistakes to avoid:

- Deleting a kept file to take a definition back. The folder now has an edit nothing versions, and a rollback refuses until it is gone. Instead: `nodecode rollback N` to the generation before it. The layer takes one commit forward, and its history stays.

**Mistake:**

```text
~$ rm ~/.nodecode/cells/you/word-count.lisp && nodecode rollback 2
nodecode: generation 2 cannot be restored: you has uncommitted edits; keep or discard them first
```

**Instead:**

```text
~$ nodecode rollback 2
generation 2 restored: you at 12d29ea; the next launch runs it
```

```text
~$ git -C ~/.nodecode/cells/you log --oneline && ls ~/.nodecode/cells/you
854f3fa (HEAD -> master) restored generation 2 -- session s-GATEWAY
b453153 word-count — session s-8ZRLUFP8
12d29ea count-lines — session s-8ZRLUFP8
count-lines.lisp  you.asd
```

## Profiles

A new profile copies the settings and links what is yours: `auth.json`, `secrets/` and every knowledge cell. It gets a fresh store and a fresh layer. `--clone-all` copies the keys and clones the layer instead. See [Profiles](https://nodecode.ai/docs/profiles).

```text
~$ ls -l ~/.nodecode/profiles/work ~/.nodecode/profiles/work/cells
/home/you/.nodecode/profiles/work:
total 8
lrwxrwxrwx 1 you you  29 Oct  8 21:19 auth.json -> /home/you/.nodecode/auth.json
drwxr-xr-x 2 you you  60 Oct  8 21:19 cells
-rw-r--r-- 1 you you 548 Oct  8 21:19 config.jsonc
-rw-r--r-- 1 you you 193 Oct  8 21:19 profile.jsonc

/home/you/.nodecode/profiles/work/cells:
total 0
lrwxrwxrwx 1 you you 37 Oct  8 21:19 you-memory -> /home/you/.nodecode/cells/you-memory/
```

| Only in the default home | Holds |
| --- | --- |
| `profiles/<name>/` | The home of each named profile. |
| `active-profile` | The profile a bare `nodecode` boots. `nodecode profile use` writes it. |

Mistakes to avoid:

- `/connect` inside a profile to change the shared key. The save puts a file where the link was. That profile keeps the new key, every other one keeps the old, and `profile list` still says it shares. Instead: `/connect` in the default home. Every profile that links `auth.json` reads the new key.

**Mistake:**

```text
~$ ls -l ~/.nodecode/profiles/work/auth.json; grep -h "\"key\"" ~/.nodecode/auth.json ~/.nodecode/profiles/work/auth.json
-rw------- 1 you you 111 Oct  8 21:20 /home/you/.nodecode/profiles/work/auth.json
      "key": "sk-demo-4f1c9a2e7b"
      "key": "sk-work-90b3e1d55a"
```

```text
~$ nodecode profile list
* default  /home/you/.nodecode  serving pid 2212192 port 37213  boots by default
      also carrying cells-named, composer-catalogs.sexp
  work  /home/you/.nodecode/profiles/work  serving pid 2225020 port 46507
      shares auth.json, cells/you-memory with default
      also carrying composer-catalogs.sexp
```

After `/connect` in `work`: a plain file, two keys, and the list unchanged.

**Instead:**

```text
~$ ls -l ~/.nodecode/profiles/work/auth.json; grep -h "\"key\"" ~/.nodecode/auth.json ~/.nodecode/profiles/work/auth.json
lrwxrwxrwx 1 you you 29 Oct  8 21:23 /home/you/.nodecode/profiles/work/auth.json -> /home/you/.nodecode/auth.json
      "key": "sk-new-77d0c4e1aa"
      "key": "sk-new-77d0c4e1aa"
```

After `/connect` in the default home: still a link, one key.

## Outside the home

| Path | Holds |
| --- | --- |
| `<project>/.nodecode/workspace_snapshots` | Snapshots for undo, in each folder a session edits. Never in your home folder or `/`. See [Sessions and undo](https://nodecode.ai/docs/sessions). |
| `~/.local/share/nodecode/` | The installed releases. On Windows, `%LOCALAPPDATA%\Programs\nodecode`. See [Install](https://nodecode.ai/docs/install). |
| `~/.local/bin/<profile>` | The command `profile create` writes for a profile. |
| `nodecode-gateway.service` | The background gateway, in `~/.config/systemd/user/`. On macOS, a plist in `~/Library/LaunchAgents/`. |
| `nodecode-ephemeral-<pid>.db` | The store of an `--ephemeral` run, in the temp folder. |

Nodecode does not add `.nodecode/` to your project's ignore list. Until you do, git sees it.

```text
~/project$ git status --short && du -sh .nodecode
 M src/main.rs
?? .nodecode/
128K	.nodecode
```

Mistakes to avoid:

- `git add -A` in a project Nodecode has edited. The snapshot repository goes into your commit: 30 files after one edit. Instead: Add `.nodecode/` to `.gitignore`, or to `.git/info/exclude` to keep it to yourself.

**Mistake:**

```text
~/project$ git add -A && git status --short | head -6 && git status --short | wc -l
A  .nodecode/workspace_snapshots/HEAD
A  .nodecode/workspace_snapshots/capture-count
A  .nodecode/workspace_snapshots/config
A  .nodecode/workspace_snapshots/description
A  .nodecode/workspace_snapshots/hooks/applypatch-msg.sample
A  .nodecode/workspace_snapshots/hooks/commit-msg.sample
31
```

**Instead:**

```text
~/project$ echo .nodecode/ >> .git/info/exclude && git status --short
 M src/main.rs
```

## Cache

What Nodecode can fetch or build again. Every profile shares it. Most of it is the launch images; the home itself is a few megabytes.

```text
~$ du -sh ~/.cache/nodecode/* ~/.nodecode
16K	/home/you/.cache/nodecode/layers
7.5M	/home/you/.cache/nodecode/models.dev
158M	/home/you/.cache/nodecode/warm
4.0M	/home/you/.nodecode
```

| Platform | Cache root |
| --- | --- |
| Linux, macOS | `$XDG_CACHE_HOME/nodecode/`, else `~/.cache/nodecode/` |
| Windows | `%LOCALAPPDATA%\nodecode\`, unless `XDG_CACHE_HOME` is set |

| Entry | Holds |
| --- | --- |
| `models.dev/api.json` | The models.dev catalog. |
| `provider-models.json` | Model lists fetched from providers. |
| `layers/`, `peripherals/` | The compiled layer and cells, per build. |
| `warm/` | Launch images. Linux and macOS. |
| `previews/` | Images converted for the prompt. |
| `profile-import/`, `profile-install/` | Where a profile is unpacked before it moves in. |
| `leases/` | One lock per bot token, so two organisms never run one bot. |
| `channel-files/`, `channel-images/` | Channel attachments and images. |
| `card-pictures/` | Pictures for Discord cards. Gone after a day. |
| `libdave/`, `speaker/`, `transcriber/` | Discord's voice encryption, and the local voice and speech engines. |
| `prs/` | Scratch clones for the prs cell. |
| `open-url.log` | Output of the last link opener. |

Mistakes to avoid:

- Deleting `~/.nodecode` to free space. That is the agent: its store, its layer, its keys. Here it is 4 MB. Instead: Clear the cache. `rm -rf ~/.cache/nodecode/warm` is always safe; the next launch builds it again.

## Permissions

The home is yours alone, and so is every file that is a key. `config.jsonc` keeps its mode.

```text
~$ stat -c "%A  %n" ~/.nodecode ~/.nodecode/auth.json ~/.nodecode/operator-token ~/.nodecode/history.db.owner ~/.nodecode/backups ~/.nodecode/backups/* ~/.nodecode/config.jsonc
drwx------  /home/you/.nodecode
-rw-------  /home/you/.nodecode/auth.json
-rw-------  /home/you/.nodecode/operator-token
-rw-------  /home/you/.nodecode/history.db.owner
drwx------  /home/you/.nodecode/backups
-rw-------  /home/you/.nodecode/backups/nodecode-default-2026-10-08-211925.json
-rw-------  /home/you/.nodecode/backups/nodecode-default-2026-10-08-211925.tar.gz
-rw-r--r--  /home/you/.nodecode/config.jsonc
```

| Path | Mode |
| --- | --- |
| `~/.nodecode/` | 0700. Set when the store opens, and again at every write of a key. |
| `auth.json`, `operator-token` | 0600, at every write. |
| Files in `secrets/` | 0600, in a 0700 folder. |
| `history.db.owner`, `history.db.lock` | 0600 |
| `link/state.json` | 0600, in a 0700 folder. |
| `backups/` | 0700. Each archive and note: 0600. |
| An `export --whole` archive | 0600 |
| `config.jsonc` | No mode is forced. A write keeps the file's mode. |

## Backups and exports

Three ways to take a home with you, and only one is for sharing.

The shell after /backup:

```text
     README.md has 2 words. word-count is kept too.

   • nodecode/nodecode-axolotl-cyber (max) · 3.1s completed · ↑276 c94.5% ↓97

    ■ backed up to /home/you/.nodecode/backups/nodecode-default-2026-10-08-211925.tar.gz (48.9 KB); it holds this
      home's keys, so keep it where you keep passwords

    Ready

   nodecode nodecode-axolotl-cyber (max) · ? help · ← sessions                    Gateway 127.0.0.1:37213 • connected
```

| Entry | New profile | `--clone-all` | Export | `--whole` | `/backup` |
| --- | --- | --- | --- | --- | --- |
| `config.jsonc`, `AGENTS.md`, `SOUL.md`, `themes.json` | Copied | Copied | Copied | Copied | Copied |
| `auth.json`, `secrets/` | Linked | Copied | No | Copied | Copied |
| `cells/<you>/`, the layer | New | Cloned | Copied | Copied | Copied |
| `cells/<you>-memory/` | Linked | Cloned | Copied | Copied | Copied |
| `history.db`, the store | New | New | No | Copied | Copied |
| `operator-token` and the rest of State | No | No | No | No | No |

Linked is one file for both homes. `nodecode profile import PATH` brings either export back as a profile.

Mistakes to avoid:

- Sending someone a backup to share your setup. It holds `auth.json` and every session you had. Instead: `nodecode profile export NAME PATH`, without `--whole`.

**Mistake:**

```text
~$ tar tzf ~/.nodecode/backups/*.tar.gz | grep -v /.git/
.nodecode/history.db
.nodecode/config.jsonc
.nodecode/cells/
.nodecode/cells/you-memory/
.nodecode/cells/you-memory/you-memory.asd
.nodecode/cells/you-memory/one-change-per-commit.lisp
.nodecode/cells/.locks/
.nodecode/cells/.locks/you-memory.lock
.nodecode/cells/you/
.nodecode/cells/you/you.asd
.nodecode/cells/you/word-count.lisp
.nodecode/cells/you/count-lines.lisp
.nodecode/auth.json
```

**Instead:**

```text
~$ nodecode profile export default ~/share.tar.gz && tar tzf ~/share.tar.gz | grep -v /.git/
exported default to /home/you/share.tar.gz
.nodecode/config.jsonc
.nodecode/cells/
.nodecode/cells/you-memory/
.nodecode/cells/you-memory/you-memory.asd
.nodecode/cells/you-memory/one-change-per-commit.lisp
.nodecode/cells/.locks/
.nodecode/cells/.locks/you-memory.lock
.nodecode/cells/you/
.nodecode/cells/you/you.asd
.nodecode/cells/you/word-count.lisp
.nodecode/cells/you/count-lines.lisp
```
