Claude Code deletes history after 30 days: how to save it
MarkdownWhere Claude Code sessions are stored, how to configure cleanupPeriodDays, and how to organize an external archive using rsync, launchd, or cron.
Read full article
For help using the service, see the Ailoot documentation.
Does Claude Code really erase your session history?
Key takeaways
Yes. Every time Claude Code starts, it deletes session files older than 30 days. The cleanupPeriodDays setting in ~/.claude/settings.json is responsible for this; its default value is 30. Deletion happens without warning, without asking for consent, and with no way to recover the files.
You open Claude Code to return to a session from two months ago—and it’s gone. The file has been completely erased from disk. This is not a glitch or a rare bug: it’s how the default cleanup mechanism works.
One setting controls cleanup: cleanupPeriodDays. Its default value is 30. Every time Claude Code starts, it scans the history folder and deletes everything older than that period. I didn’t have this setting in my ~/.claude/settings.json at all, which meant the default value was in effect, and some of my older sessions were already gone.
Several bug reports about this are open in Anthropic’s repository, and none have been fixed.
Where does Claude Code store session history?
Key takeaways
Each session’s history is stored in ~/.claude/projects/<project-path>/<session-id>.jsonl. The folder name is the absolute path of the working directory where you ran Claude Code, with slashes replaced by hyphens. The .jsonl file contains the entire conversation, one line at a time: your prompts, model responses, tool calls, and file edits. This is the very memory that cleanup deletes.
Finding your history is easy. Open a terminal and look at the contents of the folder:
ls ~/.claude/projects/
Each subfolder is a separate project. Its name encodes the path: for example, a project in /Users/you/dev/shop becomes the folder -Users-you-dev-shop. Inside are session files:
ls -lt ~/.claude/projects/-Users-you-dev-shop/
# 3f8a1c2e-....jsonl ← one session = one file
# a91b7d40-....jsonl
Each .jsonl is a line-by-line log: one line equals one session event. It contains more than the conversation text. It holds the logic behind your decisions: why you chose a particular database structure, which options you rejected, where Claude made a mistake, and how you corrected it.
In essence, it’s a project development journal. That’s why losing it hurts: you lose not a “chat,” but context you’ve built up over weeks. I covered how this context is structured in the guide “Claude Memory vs. CLAUDE.md”.
Why does Anthropic delete transcripts after 30 days?
Key takeaways
Anthropic’s position is privacy and security. Session files are stored on disk in plain text and may contain source code, passwords, and API keys. Keeping them forever is a risk: if a laptop is stolen or someone gains access to the disk, they get all that sensitive data. The 30-day period is their balance between “resuming recent work” and “not keeping secrets on disk longer than necessary.”
There is a rationale for deletion, and it’s worth understanding before turning it all off. A transcript is plain text. If Claude read a .env file during a session, inserted a key into a command, or you pasted a password into a prompt, all of it ended up in the .jsonl as plain text. The longer such a file remains on disk, the greater the chance that it will leak one day.
Anthropic puts it plainly: transcripts may contain source code, credentials, and other sensitive material, and keeping them on disk longer than necessary creates a real privacy risk. The 30-day period was chosen as a compromise.
The community’s objections concern three things: deletion is silent (there is no warning during setup or at startup), there is no consent (you aren’t asked), and there is no recovery (the Trash isn’t used, and there is no rollback). In issue #59248, developers are asking for one thing: make cleanup fair—provide a warning, a recovery period, and a less aggressive default period.
Why can a backup script itself trigger deletion?
Key takeaways
Cleanup decides what to delete based on file modification time (mtime). It does not check the actual last activity in a session. Any process that touches a .jsonl file—cloud sync, rsync, an editor, a script—can shift its mtime so that a fresh session appears outdated. At the next Claude Code startup, it will consider the session old and delete it. The paradox: a naive attempt to back up history inside the managed folder accelerates its loss.
This is the trickiest part, and it trips up people trying to protect their data themselves. Cleanup looks at mtime, the file’s last-modified timestamp. It assumes mtime reflects when you last worked in the session. In practice, anything can change mtime: a Dropbox or iCloud sync client, rsync, antivirus software, an indexer, or your own backup script.
Here’s the trap. You decide to save your history and set up cloud sync for ~/.claude/projects/. At some point, the sync service rewrites a file and sets its mtime to an earlier date (this can happen when restoring from a cloud copy). Claude Code sees an “old” file at startup and deletes it. You wanted to save it, but you sped up its deletion.
There’s only one conclusion: the backup must live outside ~/.claude/projects/. Cleanup acts only inside this folder. A copy stored outside it is beyond cleanup’s reach. I’ll build the solution around this principle.
How can you stop history deletion right now?
Key takeaways
One setting. Open ~/.claude/settings.json and set cleanupPeriodDays to a large number—for example, 3650 (ten years). In practice, this disables automatic deletion: nothing will be older than the limit. Important: this setting protects only what has not yet been deleted. History already erased by cleanup cannot be restored. So the first step is to act before you lose another session.
Stop deletion in three steps:
- Open the settings file:
~/.claude/settings.json(if the file doesn’t exist, create it). - Add the
cleanupPeriodDayssetting with a large value:
{
"cleanupPeriodDays": 3650
}
- Save the file. The setting will take effect the next time Claude Code starts.
The value 3650 means ten years: in practice, deletion will no longer take place. If you want to keep cleanup but allow more time, set it to 365 (one year); then only sessions older than a year will disappear. You can check that the setting has been picked up with this command:
grep cleanupPeriodDays ~/.claude/settings.json
One caveat that’s easy to miss: extending the period does NOT restore what has already been deleted. Cleanup runs at startup, and anything erased in previous runs is gone for good. That’s why you should set this first—it prevents future losses but does not bring back what has already been erased. If you want to avoid losing your Claude Code history, as well as your project to an accidental command, see the guide “How to Configure Claude Code So It Won’t Break Your Project”.
Your session history is part of your project’s second brain: it contains decision logic you haven’t recorded anywhere else. cleanupPeriodDays saves the files, but it doesn’t turn them into a system that lets you retrieve what you need six months from now.
How can you archive history automatically outside the cleanup folder?
Key takeaways
Copy sessions into an archive OUTSIDE ~/.claude/projects/, where cleanup does not apply. A simple rsync -a to a separate directory once a day does the job: new files are added, and old ones stay. Because the archive is outside, neither cleanupPeriodDays nor the mtime bug affects it. Automate the run with launchd (macOS) or cron (Linux), and your history will accumulate on its own.
The idea is simple: let Claude Code do what it wants with its folder, while you keep a separate archive outside it. The archive is protected from that cleanup mechanism, but it can still be lost to disk failure, accidental deletion, or a failed copy. Set it up like this:
- Create an archive folder outside the managed directory:
mkdir -p ~/claude-history-archive
- Copy your current history there. The
-aflag preserves the structure and timestamps;--ignore-existingleaves files already copied untouched:
rsync -a ~/.claude/projects/ ~/claude-history-archive/
- Automate the run once a day. On macOS, use launchd. Create the file
~/Library/LaunchAgents/com.example.claudearchive.plist:
<?xml version="1.0" encoding="UTF-8"?>
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.example.claudearchive</string>
<key>ProgramArguments</key>
<array>
<string>/usr/bin/rsync</string>
<string>-a</string>
<string>/Users/YOUR_NAME/.claude/projects/</string>
<string>/Users/YOUR_NAME/claude-history-archive/</string>
</array>
<key>StartInterval</key>
<integer>86400</integer>
</dict>
</plist>
- Load the agent so it runs in the background:
launchctl load ~/Library/LaunchAgents/com.example.claudearchive.plist
On Linux, the same thing is done with one line in crontab (crontab -e):
0 3 * * * rsync -a ~/.claude/projects/ ~/claude-history-archive/
Why does this work where sync from the previous section fails? The archive is OUTSIDE ~/.claude/projects/, so cleanup cannot see it at all. Copying happens in one direction (from the live folder to the archive), and we do not touch the mtime of live files—so the mtime bug does not occur. Even if Claude Code deletes a session from its own folder tomorrow, its copy will remain in the archive.
How can you turn your session archive into a searchable second brain?
Key takeaways
Put the archive under git, and you’ll get a versioned, fully searchable database of all your sessions. Run git init in the archive folder, then daily git add -A && git commit to get a change history and protection against accidental overwrites. You can search past sessions with ordinary grep and extract structured content with jq, since .jsonl is line-delimited JSON. This turns the archive into a practical tool.
Simply accumulating files isn’t enough—you need access to them. Two steps turn the archive into a working tool.
First, version it with git. Initialize a repository in the archive folder:
cd ~/claude-history-archive
git init
git add -A && git commit -m "First snapshot of Claude Code history"
Add git add -A && git commit to the same daily run as rsync. Now you have a version history: you can see what appeared and when, and undo an accidental overwrite with one command.
Second, search. .jsonl files are line-delimited JSON, so you can use familiar tools on them. Find which session discussed a particular topic:
grep -rl "database migration" ~/claude-history-archive/
Extract only the text of your prompts from a session (using jq, since it’s JSON):
jq -r 'select(.type=="user") | .message.content' session.jsonl
At this point, your session history starts working as a project’s second brain: a database where you can retrieve “how we decided this in March” in seconds. For a separate breakdown of where context goes in a session and how to manage it, see “Where the Tokens Go in Claude Code”.
Can you recover sessions that have already been deleted?
Key takeaways
There is no built-in method. Claude Code does not put deleted files in the Trash or keep a rollback; the file is erased for good. The only chance is external copies made BEFORE deletion: a Time Machine snapshot on macOS, OneDrive or Dropbox version history, or a manual backup. If none of these exist, the session is lost. That’s why protection must be set up in advance—before there’s anything to lose.
The honest answer: probably not. Claude Code has no recovery feature, no Trash, and no undo log for deleted transcripts. The file simply disappears from disk.
There is one option: system backups, if they were enabled in advance:
- macOS Time Machine—if a snapshot captured
~/.claude/projects/before deletion, you can retrieve the file from the backup for the required date. - OneDrive / Dropbox version history—if the folder was synced with versioning enabled, look for the file in the cloud’s version history (but remember the mtime trap: sync may also have triggered deletion).
- Manual copies—any
rsync/cpyou ran manually to somewhere outside the managed folder.
If none of these existed, the session is gone. And this is not rare: one author of a bug in Anthropic’s repository had 26 of 38 records corrupted, representing months of work. The only reliable protection is the one in place BEFORE the loss. Set cleanupPeriodDays and automatic archiving today, while there is still something to save.
What value should you choose for cleanupPeriodDays?
Key takeaways
For most people, use 3650 (ten years, which effectively disables deletion) plus an external automatic archive. Keep the default value 30 only if you don’t need history and it matters more not to keep secrets on disk. The value 365 is a reasonable middle ground, with yearly cleanup. Another option is not to write history at all: use the CLAUDE_CODE_SKIP_PROMPT_HISTORY environment variable or the --no-session-persistence flag, but that serves the opposite purpose.
There’s one setting, but it can mean several things. Compare the options and choose one for your use case:
| Value | What it does | Who it suits |
|---|---|---|
30 (default) | Deletes sessions older than 30 days at startup | You don’t need history; avoiding the storage of sensitive data on disk matters more |
365 | Keeps a year of history, then cleans it once a year | You need recent history but not an indefinite archive |
3650 | Effectively disables deletion | You want to keep everything + an external archive (recommended) |
CLAUDE_CODE_SKIP_PROMPT_HISTORY | Does not write history to disk at all | Maximum privacy; you don’t need history at all |
An important security caveat: if you set 3650 and keep everything, you agree to store transcripts that may contain keys and code on disk. It’s a deliberate trade-off: archive convenience versus risk. Minimize the risk: keep the archive on an encrypted disk (FileVault on macOS), don’t put it in a public cloud, and don’t commit it to a public git repository. I’ve put together a separate guide on what data may leak through Claude Code: “Data Security in Claude Code”.
What to do today: checklist
Key takeaways
These steps reduce history loss: extend retention with cleanupPeriodDays: 3650, copy sessions outside ~/.claude/projects/, and version the archive. Only successfully copied files are protected from Claude Code’s cleanup. A daily schedule leaves up to a day of recent changes unarchived when runs succeed; failed or missed runs make that gap longer. A copy on the same disk is not protection against disk failure.
Set up protection step by step:
- Set
cleanupPeriodDays: 3650in~/.claude/settings.json—you’ve stopped deletion. - Create
~/claude-history-archiveoutside the managed folder and run the firstrsync -a. - Schedule a daily run using launchd (macOS) or cron (Linux).
- Initialize git in the archive and add
git add -A && git committo the same run. - Check that the archive is on an encrypted disk and is not synced to a public cloud.
- Check each scheduled run for a successful copy, then inspect a recent archived session and periodically restore a sample into a separate temporary folder to verify that it is readable.
- If losing the device or disk is in scope, keep an independently stored backup with appropriate access controls and test its restoration too. Git history on the same disk is not an independent backup.
Session history is just one layer of context that makes Claude reliable.
Get to know Ailoot.
More details
Questions about Claude Code deletes history after 30 days: how to save it
Does a daily archive guarantee that no session can be lost?
No. It protects successfully copied files from cleanup in the managed folder. With successful daily runs, up to a day of recent changes may still be missing; failed runs widen that gap, and a copy on the same disk can fail with the original.
How do I check that the archive is usable?
Confirm that scheduled copies succeed, inspect a recent archived session, and periodically restore a sample into a separate temporary folder. For protection from device or disk loss, also test a backup stored independently of the original.