Metadata-Version: 2.4
Name: session-ls
Version: 0.1.0
Summary: List and search session history across coding agents (pi, codex, claude, cursor)
License: MIT License
        
        Copyright (c) 2026 4ier
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
        
Project-URL: Repository, https://github.com/4ier/session-ls
Project-URL: Issues, https://github.com/4ier/session-ls/issues
Keywords: agent,sessions,search,pi,codex,claude,cursor
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: MacOS
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Utilities
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: license-file

# session-ls

List and search session history across all coding agents on your machine:
pi, codex, claude, cursor.

```
$ session-ls -n 3
AGENT   STARTED              LAST                  CWD                            TITLE
codex   2026-07-29T00:03:17  2026-07-29T00:21:15   /home/alice/projects/website   fix the login redirect loop
pi      2026-07-17T14:42:45  2026-07-18T08:45:13   /home/alice/projects/backend   tune the postgres connection pool
claude  2026-06-15T03:08:57  2026-06-15T03:31:55   /home/alice/dotfiles           migrate to starship prompt
```

Sessions are read directly from each agent's local store, newest first. The
title of a session is its first real user message (injected context such as
codex `<recommended_plugins>` or `AGENTS.md` instructions is skipped).

## Design

- **Fast.** Metadata is cached in `~/.cache/session_ls_cache.json`, keyed by
  file size + mtime; unchanged files are never re-read. Listing ~1000
  sessions takes milliseconds. Full-text search uses `ripgrep` when
  available (fallback: `grep`).
- **Plain search, no semantics.** No index, no embeddings, no network.
  Matching is literal substring comparison. Decide what's relevant
  yourself - or hand the file paths to an LLM.
- **Lightweight, zero dependencies.** Pure stdlib, one module.
- **Extensible.** Adding another agent is one `REGISTRY` entry plus two
  small functions (see below).

## Install

```bash
pip install .            # from a checkout
pipx install .           # recommended: isolated environment
```

Requires Python >= 3.9. A man page (`session-ls(1)`) is installed alongside;
on macOS venvs, point `MANPATH` at the venv's `share/man` to see it.

## Usage

```
session-ls [KEYWORD] [OPTIONS]
```

| Option | Meaning |
| --- | --- |
| `KEYWORD` | search titles (first user message), case-insensitive substring |
| `-f, --full` | search full session content instead of titles (slow, uses rg/grep) |
| `-a, --agent` | only this agent: `pi`, `codex`, `claude`, `cursor` |
| `-c, --cwd` | only sessions under a cwd substring |
| `--since DATE` | started on/after (YYYY-MM-DD) |
| `--until DATE` | last active on/before (YYYY-MM-DD) |
| `-n, --limit N` | show only the N newest |
| `-l, --list` | print file paths only (for piping) |
| `--json` | JSON Lines output (keys: agent, cwd, started, last, title, file) |

### Examples

```bash
session-ls -n 10                              # ten most recent sessions
session-ls websocket                              # title search
session-ls "immich 2283" -f                  # full-content search
session-ls -a pi -c nemo --since 2026-08-01   # filters combine
session-ls websocket -l | xargs head -1          # inspect raw matches
session-ls websocket --json | jq -r .file        # feed paths to other tools
```

## Supported agents

| Agent | Store | Timestamps |
| --- | --- | --- |
| pi | `~/.pi/agent/sessions/<encoded-cwd>/*.jsonl` | in file |
| codex | `~/.codex/sessions/YYYY/MM/DD/rollout-*.jsonl` (+ `archived_sessions/`) | in file |
| claude | `~/.claude/projects/<encoded-cwd>/*.jsonl` | in file |
| cursor | `~/.cursor/projects/*/agent-transcripts/<id>/<id>.jsonl` | file mtime (none in file) |

## Adding an agent

Append an entry to `REGISTRY` in `src/session_ls/__init__.py`:

1. a glob of session files
2. `meta_parser(f, head) -> (cwd, started_iso) | None`
3. `user_text(line) -> first real user text | ''` (drives the early-exit read)

```python
REGISTRY = [
    # (name, glob, meta-parser, user-text-extractor)
    ("myagent", os.path.join(HOME, ".myagent/sessions/*.jsonl"),
     _myagent_meta, _myagent_user),
]
```

## Development

```bash
python -m pytest tests/        # plain asserts, also runnable via pytest
python -m session_ls ...       # run from a checkout
```

## License

MIT
