---
ai_assisted: true
title: "Sharing Claude Code Sessions via Symlinked .jsonl"
description: "Resume the same Claude Code session across accounts by pointing every projects directory at one shared physical path"
pubDate: 2026-05-20T20:30:37+09:00
category: "AI"
subcategory: "Agent"
tags: ["Claude Code", "Multi-account", "Session Sharing", "Symlink", ".jsonl", "Configuration", "Developer Workflow"]
heroImage: ""
series: "claude-multi-account"
seriesOrder: 2
seriesTitle: "Multi-Account Claude Code Operations"
serial: 15
draft: false
published: true
---

Multi-account setup introduces a new problem: sessions created in account A don't appear in account B. Each account's resume list is built from its own `projects` directory. Switching accounts means losing the conversation context you were just in — which undermines half the value of running multiple accounts seamlessly.

The fix is to point every account's `projects` directory at the same physical path.

Claude Code builds its resumable-session list by scanning `.jsonl` files in the projects directory directly. To share that list across multiple accounts on the same machine, point each account's projects directory at the same physical directory via symlink.

---

## How it works

When `claude --resume` opens the resume dialog, it scans the projects directory for every `.jsonl` file and builds the session list in memory. The physical location of the files is what matters — a symlink is transparent to the scan.

```
~/.claude-shared/projects/              <- physical directory (all .jsonl files live here)
├── -Users-jaesolshin/
│   └── *.jsonl
├── -private-tmp/
│   └── *.jsonl
└── ...

~/.claude/projects        -> symlink -> ~/.claude-shared/projects/
~/.claude-2/projects      -> symlink -> ~/.claude-shared/projects/
~/.claude-3/projects      -> symlink -> ~/.claude-shared/projects/
~/.claude-4/projects      -> symlink -> ~/.claude-shared/projects/
```

All accounts point at the same physical directory. A session created in one account is visible from any other — no sync step, no polling.

---

## Directory layout and symlinks

The shared physical directory lives at `~/.claude-shared/projects/`. Each account's projects path is replaced with a symlink pointing there:

```
~/.claude/
├── settings.json
├── history.jsonl
└── projects/    -> ~/.claude-shared/projects/

~/.claude-2/
├── settings.json
├── history.jsonl
└── projects/    -> ~/.claude-shared/projects/

~/.claude-shared/projects/
├── -Users-jaesolshin/
│   └── session-abc123.jsonl
└── -private-tmp/
    └── session-ghi789.jsonl
```

---

## Migration

Run the initialization script once:

```bash
bash ~/.claude/scripts/sessions-shared-init.sh
```

The script runs three phases. Phase 1 rsyncs each account's existing sessions into `~/.claude-shared/projects/` with `--ignore-existing` to deduplicate:

```bash
for ACCT in ~/.claude ~/.claude-2 ~/.claude-3; do
    if [ -d "$ACCT/projects" ] && [ ! -L "$ACCT/projects" ]; then
        rsync -a --ignore-existing "$ACCT/projects/" ~/.claude-shared/projects/
    fi
done
```

Phase 2 backs up each original projects directory with a timestamp:

```bash
for ACCT in ~/.claude ~/.claude-[0-9]*; do
    BACKUP="$ACCT/projects.bak.$(date +%s)"
    mv "$ACCT/projects" "$BACKUP"
done
```

Phase 3 creates the symlinks:

```bash
for ACCT in ~/.claude ~/.claude-[0-9]*; do
    ln -sf ~/.claude-shared/projects "$ACCT/projects"
done
```

To roll back to independent per-account directories:

```bash
for ACCT in ~/.claude ~/.claude-[0-9]*; do
    [ -L "$ACCT/projects" ] || continue
    rm "$ACCT/projects"
    BACKUP=$(ls -td "$ACCT"/projects.bak.* 2>/dev/null | head -1)
    [ -d "$BACKUP" ] && mv "$BACKUP" "$ACCT/projects"
    echo "Restored $ACCT/projects"
done
```

To carry sessions created after the symlink into the restored directory:

```bash
rsync -a --update ~/.claude-shared/projects/ "$ACCT/projects/"
```

---

## Session resume behavior

Because every account's projects path resolves to the same physical directory, the `.jsonl` scan returns an identical list regardless of which account is active. A session started under account 1 (`claude -1`) appears in the resume list when account 2 (`claude -2`) is launched.

```bash
# Start a session under account 1
claude -1
# ... do some work, then exit

# Switch to account 2 — the session from account 1 appears in the Resume list
claude -2
```

Session IDs are stable across accounts. A known ID can be resumed directly from any account:

```bash
claude --resume <session-id>
```

---

## Operational notes

**Ownership.** On a single-user Mac, `~/.claude-shared/` is owned by the running user automatically. No ownership changes are needed.

**Concurrent writes.** Each session gets a unique `.jsonl` filename, so two processes writing simultaneously do not collide. External tools that maintain `sessions-index.json` can race, but `--resume` reads `.jsonl` directly and is unaffected.

**Settings stay isolated.** The shared directory contains only session conversation files. `settings.json`, `CLAUDE.md`, `history.jsonl`, `commands/`, `hooks/`, and `memory/` all remain per-account — the symlink touches nothing outside `projects/`.

**Memory sharing (optional).** To extend the same pattern to `memory/`:

```bash
mkdir -p ~/.claude-shared/memory
rsync -a --ignore-existing ~/.claude/memory/ ~/.claude-shared/memory/

for ACCT in ~/.claude ~/.claude-[0-9]*; do
    rm -rf "$ACCT/memory"
    ln -sf ~/.claude-shared/memory "$ACCT/memory"
done
```

Without this step, memory remains per-account.

---

## Series position

Ep1 covered `CLAUDE_CONFIG_DIR` account isolation. Ep3 covers settings synchronization with `sync-claude.sh` — distributing `settings.json`, `CLAUDE.md`, commands, and hooks across accounts while keeping per-account overrides intact.
