Backing up ~/.claude and ~/.codex without archiving your AI logins

·6 mins

If you back up the whole ~/.claude or ~/.codex folder, the restore works, and the backup now holds everything an infostealer wants. The same folder holds your settings, every session transcript in plaintext, and, on Linux, the login itself:

~/.claude/.credentials.json     # Claude Code login, mode 0600
~/.codex/auth.json              # Codex login when file storage is in use
~/.claude/projects/*/*.jsonl    # transcripts: prompts, tool output, file contents

Split the folder into two lists. Back up what you wrote: settings, instructions, skills, hooks, and memory. Keep transcripts as optional encrypted data. Leave login files out of routine backups and log in again after a restore.

Where AI client state lives on macOS and Linux

I checked these paths against Claude Code 2.1.316, Claude Desktop for Linux 4.4212.0, ChatGPT for macOS 1.2026.183, the Codex desktop app for macOS 26.1027.30824, and Codex source at commit 67f0994. “Documented” means the vendor docs name the path. “Observed” means I found it by inspecting the official build so that it can change in any release.

ClientState rootLogin materialEvidence
Claude Code~/.claude/ and ~/.claude.json, both under CLAUDE_CONFIG_DIR if setKeychain on macOS, or ~/.claude/.credentials.json when the Keychain rejects the write (locked in an SSH session, for example). On Linux, always that fileDocumented
Claude DesktopmacOS: ~/Library/Application Support/Claude/. Linux (beta): ${XDG_CONFIG_HOME:-~/.config}/Claude/Electron cookies and Local Storage, extension secrets encrypted with safeStorageMCP config documented, rest observed
ChatGPT desktop, macOS only~/Library/Application Support/com.openai.chat/, ~/Library/Group Containers/2DC432GLL2.group.com.openai.chat/, ~/Library/Preferences/com.openai.chat.plistKeychain items in OpenAI’s access groupObserved
Codex desktop, macOS only~/Library/Application Support/Codex/, plus ~/.codexShared with Codex CLIObserved
Codex CLI${CODEX_HOME:-~/.codex}. CODEX_SQLITE_HOME, sqlite_home and log_dir can move parts of itauth.json in file mode or as the auto fallback; .credentials.json for MCP OAuth without a keyringDocumented and source

Desktop sessions that run Claude Code write to ~/.claude/, not to the Electron folder, so include both.

What to back up and what to leave out

TreatmentClaude CodeCodex
Back up, versionedsettings.json, CLAUDE.md, rules/, skills/, commands/, agents/, workflows/, output-styles/, keybindings.json, projects/*/memory/, agent-memory/, plugins/installed_plugins.json as a manifestconfig.toml, *.config.toml, hooks.json, rules/, skills/, agent-role files
Back up after a secret check~/.claude.json (personal MCP servers, trust decisions)MCP env blocks in config.toml
Optional, encrypted, short retentionprojects/*/*.jsonl, subagents/, tool-results/, history.jsonlsessions/YYYY/MM/DD/rollout-*.jsonl, archived_sessions/, history.jsonl
Exclude.credentials.json, file-history/, paste-cache/, debug/, shell-snapshots/, session-env/, backups/auth.json, .credentials.json, log/, logs_2.sqlite, shell_snapshots/, packages/, caches

For Claude Desktop, keep claude_desktop_config.json after checking its MCP env blocks, plus a list of installed extensions and where each came from. Reinstall extensions instead of restoring their executable caches. The ChatGPT app’s local databases are caches of a server-side account; use the account’s data export for conversations you want to keep.

Why copying the whole folder is the wrong default

Transcripts are plaintext. Anthropic’s docs say that anything passing through a tool is written to the session .jsonl, so a .env file a tool reads or a token a command prints is in there. Codex rollouts record tool activity the same way.

Your backup also keeps transcripts after the client has deleted them. Claude Code deletes transcripts after cleanupPeriodDays (default 30), but keeps sessions started, or last continued in Claude Desktop or Cowork at any age unless you set desktopSessionCleanupPeriodDays. A backup with a year of history still holds a transcript eleven months after the client deleted it.

A restore can also run code. Hooks, MCP server commands, skills, plugins, desktop extensions, and shell snapshots all execute something. If malware edited them, a full restore puts it back on the clean machine.

The Keychain protects less than it seems to. It stops someone who copies the disk offline, but malware running as your user can still request the item. The Linux desktop build can also fall back to Chromium’s basic password store when no wallet is running.

Dead ends worth skipping

  • Guessing Linux paths from macOS ones. Replacing Library/Application Support with .config works for Claude Desktop, which has a Linux beta. OpenAI ships no Linux desktop app for ChatGPT or Codex. The Codex source has Linux branches, but there is no supported Linux build. On Linux, your ChatGPT state lives in the browser profile.
  • Copying only the .sqlite files. Codex keeps state in state_5.sqlite, thread_history_1.sqlite, memories_1.sqlite and others . A live copy without the -wal and -shm sidecars can be incomplete or corrupt. Stop the client and copy all three.
  • Treating the desktop database as the archive. The Codex desktop app can rebuild its index from the rollout JSONL files, but metadata that lives only in the database is lost, back up the JSONL files.
  • Assuming claude purge cleaned everything. It doesn’t touch shell-snapshots/, backups/ (older copies of ~/.claude.json) or files written by /heapdump. According to Anthropic, a heap snapshot contains the full conversation and any credentials the process held.

Restore into a staging profile

  1. Reinstall the signed apps, plugins, and extensions from their sources.
  2. Restore your config, then read every hook, MCP command, and executable path before the first launch.
  3. Restore transcripts or memory only if you need them.
  4. Log in again. Don’t restore auth.json, .credentials.json, cookies, or Keychain exports.
  5. Resume one session and confirm that it uses the right account and repository.

Verify the backup set

To list what exists and how large it is, without printing any contents, run this on the machine you back up:

for p in "${CLAUDE_CONFIG_DIR:-$HOME/.claude}" "$HOME/.claude.json" \
  "${CODEX_HOME:-$HOME/.codex}" \
  "${XDG_CONFIG_HOME:-$HOME/.config}/Claude" \
  "$HOME/Library/Application Support/Claude" \
  "$HOME/Library/Application Support/Codex" \
  "$HOME/Library/Application Support/com.openai.chat" \
  "$HOME/Library/Group Containers/2DC432GLL2.group.com.openai.chat"; do
  [ -e "$p" ] && du -sh "$p"
done

Then check that no login file ended up in the backup:

find /path/to/mounted/backup \( -name .credentials.json -o -name auth.json \) -print

It should print nothing. If it prints anything, that backup is a credential store: encrypt it, shorten its retention, or rotate the logins.

If malware may already have run

Don’t treat a restore as the cleanup. From a clean device, revoke your Claude and ChatGPT sessions, then rotate API keys, MCP and connector credentials, and any secret that appeared in a transcript or in tool output. Any backup the malware could reach counts as exposed. Rebuild the user profile, restore only config you have reviewed, and log in again.

Caveats

Paths and retention rules change between releases. The ChatGPT and desktop paths come from build inspection, not from a published schema, so check them against your installed versions before you write a backup job. Sources: the .claude directory reference , Claude Code credential management , Codex config and state locations , Codex credential storage , Claude Desktop MCP config paths , and Electron’s app.getPath() .

Back up the config you wrote, and leave out the files the app uses for login. Run the find check above against your latest backup tonight.