Skip to main content

ai-sessions

ai-sessions is a searchable terminal browser for local Codex CLI and Claude Code conversations. It indexes each provider's existing on-disk history. Browsing is read-only; an explicit rename appends the provider's supported title record so the name also appears in that provider.

It runs as sessions on Linux and native Windows PowerShell.

Features

  • One navigable list for Codex and Claude sessions
  • Search and filters for provider, directory, origin, open state, and visibility
  • Human, cross-provider, and subagent/automation origin labels
  • Started and updated timestamps plus user-message counts across compactions
  • Rename that carries through to Claude Code and Codex, plus utility-local hiding
  • Nickname and parent labels that tell sibling subagent threads apart
  • Detection of currently open sessions on Linux and Windows
  • tmux pane and desktop-terminal focus on Linux when the environment exposes it
  • Cross-harness resume: continue any session in Codex or Claude regardless of where it was created
  • Safe, dangerous, and custom launch profiles
  • Native paths and argument handling on both operating systems

Windows Terminal does not expose a stable session-ID-to-tab interface. On Windows, open sessions are identified, but exact tab focusing is intentionally not attempted.

Requirements

  • Python 3.11 or newer
  • Codex CLI, Claude Code, or both
  • Linux or native Windows PowerShell

The Windows-only windows-curses dependency is installed automatically. psutil is used for portable process inspection.

Install

From a checkout:

python -m pip install .
sessions

With pipx:

pipx install .
sessions

From PyPI:

pipx install ai-sessions

On Windows, py -m pip can be used in place of python -m pip.

Everyday use

Run sessions, navigate with the arrow keys or j/k, and press Enter to resume the selected conversation.

Key Action
Ctrl-F or / Start search mode
Tab Cycle provider filter
o Cycle Human, Cross, Agent, and All origins
v Cycle visible, hidden, and all sessions
d Choose a directory
s Cycle sort order
x Cycle launch harness for selected session (bridges a copy when needed)
p Cycle Safe, Dangerous, and Custom launch modes
r Rename in the utility and provider
h Hide or restore locally
Ctrl-R Refresh
? Show complete help

Useful noninteractive forms include:

sessions --list --tool codex
sessions --list --query "is:open dir:my-project"
sessions --list --visibility hidden
sessions --resume SESSION_ID
sessions --resume SESSION_ID --launch-tool claude
sessions --resume SESSION_ID --launch-tool codex
sessions --resume SESSION_ID --dry-run

What is written, and when

Resuming a session in the harness that recorded it is a pure read: sessions runs codex resume ID or claude --resume ID against the original id and touches nothing. Sessions at rest are never rewritten, and no transcript is ever edited in place.

Only two actions write to provider storage, and both are additive:

  • Rename (r) appends a title entry — a custom-title line to a Claude transcript, or a thread_name line to ~/.codex/session_index.jsonl.
  • Bridging creates a new session file next to the existing ones and appends its title. The source transcript is opened read-only and left byte for byte unchanged.

Everything else — hiding, sort order, per-session harness preference — stays in this utility's own state.json.

Cross-harness resume

Codex and Claude Code store transcripts in different formats, and neither recognises the other's session id, so a conversation cannot simply be handed across by reference. Press x (or pass --launch-tool) and ai-sessions bridges it instead: it reads the source transcript, converts the conversation into the target harness's own on-disk format, and writes it there as a new native session. That copy is an ordinary session — the target CLI resumes it, appends to it, and lists it like any other.

sessions --resume CODEX_SESSION_ID --launch-tool claude
sessions --resume CLAUDE_SESSION_ID --launch-tool codex

The user/assistant conversation crosses over as messages. Tool calls cross over summarised, folded into the turn that made them:

⟦Bash⟧ python -m unittest discover -s tests
   → Ran 75 tests in 0.066s
     OK

They are deliberately not replayed as live tool calls: a tool_use block would name tools the target harness does not have, and would need a matching result to stay a valid conversation. Summarising keeps what was run and what it returned — usually the part worth having — without inventing structure the target cannot honour. Arguments and output are clipped, Codex's fixed result preamble is stripped, and a Codex exec snippet is reduced to the shell command it actually ran. Reasoning and attachments are dropped entirely.

Because a summary is a record and not a result, the copy opens with a note saying where it came from and warning that the filesystem state is unverified. The source transcript is never modified, and the copy is named <title> (from Codex) or <title> (from Claude) so the two are never confused in the list.

Long conversations are trimmed to a character budget before they are replayed, since the copy lands in the target's context window in full. The opening request and the most recent exchanges are kept and the middle gives way; the note says how many messages were dropped. Set max_chars in config.toml to change the budget, or tool_calls = false for a conversation-only copy.

Bridged copies are remembered, so launching the same pairing again continues that copy rather than making a new one. Once the source session picks up new messages, the next launch bridges again from the current state.

Adding a harness

Conversions run through a harness-neutral conversation rather than pairwise, so support for another CLI costs one reader and one writer rather than a converter per existing harness. Register it in HARNESSES in bridge.py with four things: a name, a display label, a reader that turns a transcript file into Turn objects, a writer that turns Turn objects into a resumable session file, and a check for whether a session id still exists on disk. Bridging in both directions then works for free.

This seam covers bridging only. Listing, message counts, and open-session detection are still provider-specific in app.py, because each CLI records them differently — Codex in a SQLite state database and lock files, Claude Code in a PID registry and per-project transcript directories. That side is the larger job and is deliberately left concrete until a third harness makes the right abstraction obvious.

A Codex writer has one non-obvious obligation. Codex records the model's context (response_item) separately from what its TUI redraws (user_message and agent_message events), and groups both into turns delimited by task_started/task_complete. A rollout carrying only the first kind resumes with the full conversation in context but a blank screen, which looks exactly like a failed bridge. Writers for other harnesses should expect a similar split and check the resumed session visually, not just by asking the model what it remembers.

One more wrinkle: Codex enumerates its sessions from a local state database rather than from the rollout files, so a copy bridged into Codex is resumable immediately but only appears in the sessions list after Codex itself has opened it once. Copies bridged into Claude Code are listed straight away.

Launch safety

The package defaults to safe. This leaves approval and sandbox behavior to each provider's normal configuration:

claude --resume SESSION_ID
codex resume SESSION_ID

Dangerous mode adds the providers' explicit bypass flags:

claude --dangerously-skip-permissions --resume SESSION_ID
codex --dangerously-bypass-approvals-and-sandbox resume SESSION_ID

These options disable important protections. Use them only where you have consciously accepted that risk.

Set a persistent mode from the command line:

sessions --set-launch-mode safe
sessions --set-launch-mode dangerous

Use --launch-mode for a one-time override. The active mode is always displayed in the interface header.

Configuration

Configuration is stored in:

  • Linux: ~/.config/ai-sessions/config.toml
  • Windows: %APPDATA%\ai-sessions\config.toml

The optional custom profile uses structured argument arrays, avoiding shell interpolation:

[launch]
mode = "custom"
claude_command = ["claude"]
codex_command = ["codex"]

[launch.custom]
claude_args = ["--permission-mode", "acceptEdits"]
codex_args = ["--sandbox", "workspace-write", "--ask-for-approval", "on-request"]

[bridge]
max_chars = 950000
tool_calls = true

Rename/hide state is kept alongside the configuration as state.json. Per-session launch-harness preferences are stored there too, with unset sessions defaulting to the harness where the session was started, along with the bridged copy made for each cross-harness pairing. Caches use ~/.cache/ai-sessions on Linux and %LOCALAPPDATA%\ai-sessions on Windows. Environment overrides are available through AI_SESSIONS_CONFIG_FILE, AI_SESSIONS_STATE_FILE, CODEX_HOME, and CLAUDE_CONFIG_DIR.

How open-session detection works

  • Claude Code publishes a live PID/session registry.
  • Codex on Linux holds per-thread writer locks.
  • Codex on Windows records thread IDs alongside process IDs in its local log database.
  • Linux focus support follows the process into tmux and then uses wmctrl/xdotool when available.

Detection is best-effort and read-only. See What is written, and when for the complete list of operations that touch provider storage.

Privacy

No transcripts, caches, credentials, local names, or hidden-session state belong in this repository. The defensive .gitignore excludes common provider and local data paths.

Development

python -m unittest discover -s tests -v
python -m build

CI exercises Python 3.11–3.13 on Ubuntu and Windows.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ai_sessions-3.1.0.tar.gz (53.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ai_sessions-3.1.0-py3-none-any.whl (48.1 kB view details)

Uploaded Python 3

File details

Details for the file ai_sessions-3.1.0.tar.gz.

File metadata

  • Download URL: ai_sessions-3.1.0.tar.gz
  • Upload date:
  • Size: 53.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for ai_sessions-3.1.0.tar.gz
Algorithm Hash digest
SHA256 103d984d9579922776fc209afc4837b285c9687627c76929ee50eea7a814bb12
MD5 5a417b7f9b065b8b1dadbebc8926b2ac
BLAKE2b-256 baf908557a459e20b32f0824e7d7908b3959cfbe0e32f7ccfc1df7d614e0ebdc

See more details on using hashes here.

Provenance

The following attestation bundles were made for ai_sessions-3.1.0.tar.gz:

Publisher: publish-to-pypi.yml on vandyand/ai-sessions

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ai_sessions-3.1.0-py3-none-any.whl.

File metadata

  • Download URL: ai_sessions-3.1.0-py3-none-any.whl
  • Upload date:
  • Size: 48.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for ai_sessions-3.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 fbb77160988b6cdc0deb3959acfa73112e0f8b808c4b125726a1b12308e30d0c
MD5 f8fec92381fdf9f9117a99010c7c3562
BLAKE2b-256 a0f99536128fa9a88a3b323c6cf3af721cd3f6527d7cc4b5c555612b620f8000

See more details on using hashes here.

Provenance

The following attestation bundles were made for ai_sessions-3.1.0-py3-none-any.whl:

Publisher: publish-to-pypi.yml on vandyand/ai-sessions

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

3.1.5

2 files

3.1.4

2 files

3.1.3

2 files

3.1.2

2 files

3.1.1

2 files

This release

3.1.0 This release

2 files

3.0.3

2 files

3.0.2

2 files

3.0.1

2 files

3.0.0

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page