‹ All articles
Agentic Coding
Agentic codingXcode

What AI coding agents write to your Mac while you code

I got curious about what AI agents write to our Macs while we code in Xcode. Here’s what I found when I went looking through the files.

Carolane Lefebvre7 min
What AI coding agents write to your Mac while you code

I knew coding agents kept a record of our sessions somewhere. I didn't expect them to keep this much. I found out while building Perch, a small macOS app that shows what Xcode's built-in agent is doing, right in the MacBook notch. There's no API to tell you which tool is running, which model is answering or how many tokens are going out.

You have to read what the agent writes to disk. So I opened those files.

Then I took stock of everything the agents had left on my Mac. Nothing alarming, and nothing hidden either: some of it is documented. But if you code with an agent every day, it's worth knowing what stays on your machine once the session is over.


Where the agents write

Since Xcode started shipping Claude and Codex, everything lives in one folder:

~/Library/Developer/Xcode/CodingAssistant/
├── Agents/                     # the agent binaries, one folder per version
├── ClaudeAgentConfig/
│   └── projects/<project>/     # Claude: one .jsonl per session
│       ├── <session>.jsonl
│       ├── <session>/subagents/
│       ├── <session>/tool-results/
│       └── memory/
└── codex/
    ├── sessions/YYYY/MM/DD/    # Codex: one rollout-*.jsonl per session
    ├── shell_snapshots/
    └── *.sqlite

The two agents organize things differently. Claude files by project, and the folder name encodes the project's absolute path, username included. Codex files by date and keeps several SQLite databases alongside (thread state, history, logs).

ClaudeAgentConfig/ has the same layout as ~/.claude/ when you run Claude Code in a terminal, and it appears to follow the same rules: a .last-cleanup file records the last automatic cleanup. Apple doesn't document this folder, so what follows is based on what I observed and on Claude Code's documentation.

On my Mac, the folder weighs more than 2 GB. A good third of that is agent binaries: Xcode keeps several versions of Codex side by side. The rest is our sessions.

Outside Xcode, every tool has its own folder in your home directory: ~/.claude, ~/.codex, ~/.cursor… I also found folders for agents I've never launched, like ~/.gemini, ~/.kiro and ~/.qwen. They're empty apart from a symlink to a skill stored in ~/.agents/skills/. The agents didn't create those folders. A skill installer did, dropping a link into the folder of every agent it knows about.


What's in a line

A transcript is JSON Lines: one JSON object per line, appended as the session goes. A line on the Claude side looks like this (simplified, made-up values):

{
  "type": "assistant",
  "timestamp": "2026-10-30T09:12:44.512Z",
  "cwd": "/Users/me/Developer/MyApp",
  "gitBranch": "feature/onboarding",
  "message": {
    "model": "<model>",
    "usage": { "input_tokens": 3, "output_tokens": 412, "cache_read_input_tokens": 48210 },
    "content": [
      { "type": "tool_use", "id": "toolu_01", "name": "Read", "input": { "file_path": "…" } }
    ]
  }
}

There are two kinds of information in there.

  • Metadata: project folder, git branch, timestamp, model, token counts, the name of every tool called. That's all Perch needs.

  • Content: your prompts, the replies, the model's reasoning when it's recorded, and above all the result of every tool call. Claude Code's documentation is explicit: the transcript holds "every message, tool call, and tool result". In practice, when the agent reads a file, the file's contents end up in the transcript. When it runs a build, the build output does too.

That's what surprised me. In my Claude sessions, tool results account for more than half the volume. What I actually typed is under 1% of the file. My prompts are a few lines long. What the agent read, ran and fetched to answer them adds up to tens of megabytes.

Codex works the same way in a different format: function_call and function_call_output events, plus a snapshot of the rate limits rate_limits) on every turn. Sessions are also copied into a SQLite database.

Two more things caught my attention:

  • Claude writes Markdown notes to itself in memory/ about the project: decisions made, how the code is organized, things to pick up later. Automatic cleanup doesn't touch these notes (we all know that it’s the memory part right?).

  • To run commands in the same environment as you, agents capture your shell: aliases, functions, exported environment variables. Claude Code deletes its snapshot when the session exits cleanly. On my Mac, Codex had kept one.


How long it stays

This is where the two agents really differ.

Claude deletes transcripts after 30 days by default, based on their last modification date. The setting is called cleanupPeriodDays. The August sessions I opened while building Perch are gone; only the last month is left.

Codex hadn't deleted any rollouts. My sessions go back to the first time I used it in Xcode, more than two months ago, for over a gigabyte in total. I couldn't find any documented automatic cleanup.

Either way, the files are plain text. Claude Code's documentation says so directly: they're not encrypted at rest, and file system permissions are the only protection. It also gives the example that makes you stop and think: if the agent reads a .env file or a command prints a credential, that value ends up in the transcript.


Reading these traces without touching them

These files are also a genuinely useful data source. That's what Perch does: it reads them live to show what the agent is up to. Two rules guided me.

Decode metadata only. JSONDecoder ignores any key you don't declare, so you only model what you want to display:

struct TranscriptLine: Decodable {
    let type: String?
    let cwd: String?
    let gitBranch: String?
    let timestamp: String?
    let message: Message?

    struct Message: Decodable {
        let model: String?
        let usage: Usage?
    }

    struct Usage: Decodable {
        let inputTokens: Int?
        let outputTokens: Int?

        enum CodingKeys: String, CodingKey {
            case inputTokens = "input_tokens"
            case outputTokens = "output_tokens"
        }
    }
}

Message text, tool arguments and tool results never become Swift values. They're not kept in memory, displayed or logged.

Watch without being able to write. You don't need to poll the file to know when the agent appends a line. A DispatchSource gets a kernel notification on every write:

import Foundation

final class TranscriptObserver {
    private let source: any DispatchSourceFileSystemObject

    init?(url: URL, onChange: @escaping @Sendable () -> Void) {
        let descriptor = open(url.path, O_EVTONLY)
        guard descriptor >= 0 else { return nil }

        source = DispatchSource.makeFileSystemObjectSource(
            fileDescriptor: descriptor,
            eventMask: [.write, .extend],
            queue: .global(qos: .utility)
        )
        source.setEventHandler(handler: onChange)
        source.setCancelHandler { close(descriptor) }
        source.resume()
    }

    deinit {
        source.cancel()
    }
}

The descriptor is opened without write access, so the system itself rejects any write. It's enforced, not just promised in the code. O_EVTONLY also signals that the descriptor exists only to receive events. On each notification, Perch resumes reading where it left off using an offset, and holds on to the last line if the agent was still writing it.

Perch is open source btw: github.com/CarolaneLFBV/Perch


Check your own Mac

Two commands are enough to see what's on yours:

du -sh ~/Library/Developer/Xcode/CodingAssistant/* ~/.claude ~/.codex 2>/dev/null
find ~/Library/Developer/Xcode/CodingAssistant -name '*.jsonl' | wc -l

Then, depending on what you want to keep:

  • Shorten retention on the Claude side: cleanupPeriodDays in Claude Code's settings (30 days by default, minimum 1).

  • Block reads of sensitive files: a permission rule that denies reading .env and credential files. This is the most useful one, because what never gets read never gets written.

  • Clean up a project: claude purge <path> deletes that project's transcripts, memory and prompt history for Claude Code. Run it with --dry-run first to see what would go.

  • On the Codex side: since nothing is cleaned up automatically, check the size of codex/sessions/ now and then and delete old sessions by hand.


Agents are only going to write more: memory, skills, longer sessions, subagents that each keep their own transcript. That's not a problem in itself. It just means the CodingAssistant folder deserves the same attention you already give your .env files: knowing what's in it, how long it stays, and what you let the agent read in the first place. In the meantime, have fun coding!