Coding AgentsMemoryBenchmarksLinux

How much memory does each AI coding agent use?

October 17, 2026 · Oyren AI Team (AI-written)

How much memory does each AI coding agent use?

A coding agent's terminal process and the work it starts need separate memory budgets. In four snapshots of 33 live sessions, median harness PSS ranged from 198 MiB for Codex with GPT-6.1 Sol at the recorded max setting to 492 MiB for one long Claude Code session with Opus 5.5. One test tree used 5,370 MiB in tool children alone.

The useful rule is simple: the harness is small; the tools it runs are big. The observed harnesses were smaller than the largest tool trees, though startup configuration also mattered. An OpenCode startup state used 804 MiB without a successful model response.

These are measurements from 17 October 2026, on one 8 vCPU, 32 GB Linux x86_64 machine with no swap. They describe local process memory, not model-serving RAM or GPU memory. The numeric samples and measurement script accompany this post.

What the measurement includes

The harness is the CLI and its wrappers. MCP is the group of child processes whose command names matched an MCP or server pattern. Tools are the remaining descendants: shells, test workers, compilers and similar processes. The MCP label is a heuristic. A browser-associated process can land in that bucket, so a large MCP total does not establish the cost of one standalone MCP server.

RSS counts the resident pages mapped into a process. Shared pages appear in the RSS of every process that maps them. PSS divides each shared page among the processes sharing it. Adding PSS across a process tree therefore avoids repeatedly charging the full size of shared pages. That makes PSS the fairer comparison on a machine running many agents. The Linux kernel documentation defines both measures. All tables below use MiB, calculated as KiB divided by 1,024.

The collector follows parent PIDs and reads /proc/<pid>/smaps_rollup. Detached services, kernel allocations and filesystem cache are outside those process trees. Reads are not atomic, and exited or unreadable children can be missed. Host memory pressure still needs a separate MemAvailable check.

Fresh sessions after 60 seconds

Each installed harness started in a new empty temporary directory, in a dedicated tmux window. The prompt asked for exactly ok, without tools, file reads or delegation. Collection began after 60 seconds, then the session was closed. Reading the process table added roughly one to four seconds.

Existing user configuration and available authentication stayed in place. Codex used --no-daemon to keep its tree self-contained, with read-only permissions; Claude Code and agy used plan mode. Node old-space was capped at 1,024 MiB for these short launches. The Codex CLI reference documents the model and daemon flags. This is one launch per harness, with different configurations, rather than a factory-default benchmark.

Harness and versionModel or startup stateHarness PSSMCP PSSOutcome
Codex CLI 0.160.1GPT-6.1 Sol, max227.10.0Completed ok; idle
Claude Code 2.1.301Sonnet 5.5284.184.0Completed ok; idle
agy 1.3.0Gemini 4 Argon, high264.385.8Completed ok; idle
OpenCode 1.17.18DeepSeek V4 Pro shown in UI803.885.5Provider returned insufficient balance
Cursor Agent 2026.09.10-fd3934aLogin screen175.50.0No authenticated response
Gemini CLI 0.50.0Authentication selection124.40.0No model response

The last three rows are startup measurements, not successful post-response idle results. OpenCode also displayed an update offer. Gemini displayed an automatic-update notice and had another 241.1 MiB in tool children. Its 124.4 MiB harness figure therefore excludes a substantial startup child. These states cannot support an idle-memory ranking across all six tools.

The fresh Claude Code and agy MCP children used about 84-86 MiB each. In the ongoing-session samples below, their MCP groups were around 60 MiB. That difference is another reason to measure the configured installation instead of treating an MCP process as a fixed-size allowance.

Ongoing sessions with different models

The supplied workload has four snapshots, 15 seconds apart, of the same 33 live sessions. The cover chart shows the pooled median harness PSS for each labeled cohort. MCP and tool children are excluded.

Harness and modelMedian PSSObserved rangeSessionsObservations
Codex 0.160.1, GPT-6.1 Sol, max198139-2821560
Codex 0.160.1, GPT-6.1 Sol, ultra232194-4541040
agy 1.3.0, Gemini 4 Argon high214196-362312
Claude Code 2.1.301, Sonnet 5.5277170-348312
Claude Code 2.1.301, Opus 5.5492492-49414

One additional Claude session had no model label in the numeric records. Its median was 405.5 MiB; it is omitted from the model-labeled chart.

Observations are repeated readings of existing sessions, not independent trials. Tasks, conversation lengths and configurations differ. The collection notes identify the larger Codex sessions and the Opus session as long-running conversations. Session history is a plausible contributor, but this experiment does not isolate its effect. It also cannot attribute the difference between the max and ultra cohorts to reasoning effort. Those are recorded launch settings; the server's applied effort was not independently inspected.

The harness/model pair matters for describing the sample. It does not make this a measurement of the model's weights.

The busy session is mostly children

One browser-associated Codex tree contained 238 MiB of harness memory, 2,592 MiB in MCP-classified children and 616 MiB in other tool children. Total PSS was 3,446 MiB, or 3.37 GiB.

One busy Codex session: 238 MiB harness, 2,592 MiB MCP-classified children and 616 MiB other tools, total 3,446 MiB

A separate Codex session running tests had 274 MiB in its harness and 4,307 MiB in tools in the first snapshot. Its tool totals across the four samples were 4,307, 4,847, 5,370 and 3,516 MiB. The largest observed tool total was 5.24 GiB. Independently rounded buckets can differ from the recorded total by one or two MiB.

A machine can hold many waiting conversations and still run out of room when several start tests or browsers together. The count of open agent sessions is therefore a poor substitute for the count and size of concurrent heavy jobs.

Memory budgets for 8, 16 and 32 GB machines

The following are planning examples, not measured device capacities. A 1 GiB session allowance rounds above the largest fresh harness-plus-MCP total here, OpenCode at 889.3 MiB. It is a starting allowance, not an upper bound for a long conversation or an unmeasured configuration.

Each example also reserves 3 GiB for the operating system, editor and other services. A 6 GiB heavy-job allowance rounds above the largest observed test-tool tree. The 2 GiB job allowance on an 8 GB machine describes smaller, capped work; it would not accommodate that test tree. Actual usable RAM and MemAvailable determine admission.

RAMSessionsToolsTotal
8 GB21 × 2 GiB7 GiB
16 GB51 × 6 GiB14 GiB
32 GB122 × 6 GiB27 GiB

These examples leave additional headroom on the nominal capacities. A mix dominated by the measured 200-300 MiB harnesses can hold more waiting sessions, as the 33-session source workload demonstrates. That does not establish capacity for 33 simultaneous builds.

An older 8 GB laptop needs the smaller-job distinction. A 16 GB laptop has more room for the measured test workload, provided its other processes leave the assumed budget available. The Raspberry Pi 5 has a 16 GB variant, but this x86_64 experiment did not test a Pi, ARM installation compatibility or task speed. The 16 GB row is memory arithmetic only.

Limits on concurrent heavy jobs

A shared heavy-job slot prevents every agent from starting a suite at once. Our local runner admits a job only after acquiring a slot and checking that MemAvailable exceeds the requested memory allowance plus a 3,072 MiB reserve. The slot controls concurrency. A separate limit controls how large the admitted job can grow.

For Node-based tests, a bounded command can look like this:

NODE_OPTIONS=--max-old-space-size=1536 pnpm exec jest --maxWorkers=2

The Node CLI documentation defines that setting as a V8 old-space limit. It is not a cap on all native allocations or the sum of multiple workers. Two workers can each have their own heap allowance.

On a Linux system with a user systemd manager and delegated memory controller, a cgroup limit can contain the whole command tree:

systemd-run --user --scope -p MemoryHigh=5G -p MemoryMax=6G \
  env NODE_OPTIONS=--max-old-space-size=1536 \
  pnpm exec jest --maxWorkers=2

The upstream systemd resource-control manual describes MemoryHigh as a throttling control and MemoryMax as the hard limit, with an out-of-memory kill inside the unit if usage cannot be contained. The systemd-run manual documents the scope and property options. The limits above are example policies derived from this workload, not requirements for every project.

The measurement script

The script takes the harness PID, or the PID of its dedicated shell. It sums RSS and PSS for the descendant tree and emits category totals without command lines. The MCP and harness-name patterns need checking for unfamiliar wrappers. An absent or unreadable root produces an error; children that disappear or cannot be read are skipped.

"""Linux process-tree memory snapshot. Usage: python3 measure.py ROOT_PID

Pass the harness PID, or its dedicated shell PID. No command lines are emitted.
MCP classification uses a name heuristic; audit the tree for unfamiliar tools.
"""

import collections
import json
import re
import sys
from pathlib import Path


def snapshot(root):
    processes = {}
    children = collections.defaultdict(list)
    for directory in Path("/proc").iterdir():
        if not directory.name.isdecimal():
            continue
        try:
            stat = (directory / "stat").read_text().rsplit(")", 1)[1].split()
            argv = (directory / "cmdline").read_bytes().split(b"\0")
            command = " ".join(arg.decode(errors="replace") for arg in argv[:2])
            fields = dict(re.findall(r"^(Rss|Pss):\s+(\d+)",
                                    (directory / "smaps_rollup").read_text(), re.M))
            pid, parent = int(directory.name), int(stat[1])
            processes[pid] = (command, int(fields["Rss"]), int(fields["Pss"]))
            children[parent].append(pid)
        except (OSError, ValueError, KeyError, IndexError):
            continue

    if root not in processes:
        raise SystemExit("Root process is absent or its memory is unreadable")
    buckets = {name: [0, 0, 0] for name in ("harness", "mcp", "tools")}
    stack = [root]
    harness = re.compile(r"(?:^|[/@ ])(?:codex|claude|agy|opencode|cursor-agent|gemini)(?:[/. -]|$)")
    while stack:
        pid = stack.pop()
        stack.extend(children[pid])
        if pid not in processes:
            continue
        command, rss, pss = processes[pid]
        if harness.search(command):
            group = "harness"
        elif re.search(r"mcp|context7|server", command, re.I):
            group = "mcp"
        elif pid == root and command.split() and Path(command.split()[0]).name in ("bash", "sh", "zsh"):
            continue
        else:
            group = "tools"
        buckets[group][0] += rss
        buckets[group][1] += pss
        buckets[group][2] += 1
    return {
        group: {"rss_mib": round(rss / 1024, 1),
                "pss_mib": round(pss / 1024, 1), "processes": count}
        for group, (rss, pss, count) in buckets.items()
    }


if __name__ == "__main__":
    print(json.dumps(snapshot(int(sys.argv[1])), indent=2))

The downloadable script is the same code. The anonymized dataset includes all four readings per session, the fresh startup states, versions and units. The small harness footprint explains how many conversations can coexist. The tool-child measurements explain why test and browser concurrency still needs a limit.

The Oyren Codespaces page describes a hosted Linux computer with an editor, terminal and browser. The same process-tree measurement and heavy-job budgets apply to that execution host.