npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

lazy-claude-tui

v1.3.0

Published

🦞 A LazyGit-style terminal UI for managing Claude Code sessions and project history.

Downloads

70

Readme

Lazy Claude

A terminal UI for finding, resuming and maintaining Claude Code sessions.

npm node license

Claude Code stores every conversation as a UUID-named file, and its own picker only lists the directory you happen to be standing in. After a few weeks that is hundreds of sessions spread across dozens of projects, with no way to search them and no way to move a project without orphaning its history.

Lazy Claude reads the same files Claude Code writes. Every session shows its real title, ctrl+k searches all of them at once, and one key hands the terminal over to claude --resume in the right directory. It also fixes the things Claude Code has no answer for: moving a project without losing its sessions, repairing references after a manual mv, archiving what you no longer need, and backing up the history index before every change.

Lazy Claude command palette

Contents

Why it exists

Two problems, both caused by how Claude Code stores sessions on disk.

Finding an old conversation is hard. Sessions are named by UUID, the resume picker is scoped to the current directory, and there is no search across projects. If you remember the work but not where you did it, you are out of luck.

Moving a project breaks its history. Claude Code derives each storage path from the project's absolute path, so a plain mv orphans every session that belonged to it. Renaming a repository does the same thing.

Lazy Claude solves both without touching Claude Code itself. It reads the same metadata, understands the same encoding, and hands control back to claude when you want to continue a conversation.

Features

  • Sessions listed by their real title, with branch, size and age beside them
  • Global command palette (ctrl+k) that searches every project and session at once, and runs workspace commands
  • Sortable and filterable lists: order by date, size or name, or narrow to the projects that need attention
  • Fuzzy search (/) inside each panel, fzf-style, with matched characters highlighted
  • Session inspector with four tabs: overview statistics, conversation preview, activity timeline and file list
  • Resume in Claude Code from anywhere, with or without permission prompts, and land back in Lazy Claude when it exits
  • Move a project and migrate every session reference, including nested sub-projects and worktrees
  • Repair references after a manual mv or rename
  • Archive, restore and delete individual sessions
  • Pack a project and its sessions into a portable .claudepack archive
  • Timestamped history.jsonl backups before every mutation, with a manager to restore them
  • Health check, diagnostics and pruning for orphaned session folders
  • Workspace statistics: storage, counts, and the largest projects and sessions
  • Integrity check that validates every record in a session file
  • Dry-run mode on every destructive operation
  • Overlay dialogs that stack on top of the interface instead of replacing it
  • A CLI that exposes every operation for scripts
  • Native TypeScript, no shell-outs, three runtime dependencies

Installation

The package is published as lazy-claude-tui. It installs four commands, all running the same binary: lazyclaude (the main one), plus lazy-claude, lazy-claude-tui and lzc.

Requires Node.js 18 or newer.

Global install:

npm install -g lazy-claude-tui
pnpm add -g lazy-claude-tui
yarn global add lazy-claude-tui
bun add -g lazy-claude-tui

Run it once without installing:

npx lazy-claude-tui
pnpm dlx lazy-claude-tui
yarn dlx lazy-claude-tui
bunx lazy-claude-tui

From source:

git clone https://github.com/brunos3d/lazy-claude.git
cd lazy-claude
npm install       # builds via the prepare script
npm link          # exposes lazyclaude and its aliases globally

Quick start

npm install -g lazy-claude-tui
lazyclaude

That is it. The TUI opens on every project it finds.

lazyclaude .              # open on the current workspace
lazyclaude ~/code/app     # open on a specific project

Inside the TUI:

  1. Press ctrl+k and type a few characters to find any session.
  2. Press enter to jump to it.
  3. Press e to resume it in Claude Code.

Press ? for help and q to quit.

Interface overview

The screen is three panels and a footer.

| Panel | Contents | | ------------ | ------------------------------------------------------------------------------------- | | Projects | Every project, plus an "All sessions" row that widens the session list to the machine | | Sessions | Sessions belonging to the highlighted project, live or archived | | Inspector | The project summary, or the session details once Sessions or Details has focus |

Projects panel with a missing project selected

The left column is a hierarchy. Projects sit on top and their sessions below, and both stay on screen, so the workspace you are in never disappears while you browse its sessions. Sessions always belong to the highlighted project, whichever panel has focus.

Focus moves with tab through Projects, Sessions and Details. enter steps down the hierarchy, esc steps back up. The focused panel has a green border and paints its selection as a solid bar; the others keep a ▶ marker so the current project and session stay identifiable.

Project rows carry their status. A green dot means the directory exists, red means it is missing, and a folder with no resolvable path is listed as an orphan. Selecting one shows what is wrong in the inspector, which is where a repair usually starts.

Dialogs are overlays, not screens. Confirmations, pickers, reports and the action menu draw on top of the interface while the panels stay visible and keep their selection, so closing a dialog returns you exactly where you were. Only the top dialog receives keys. Dialogs stack, so a confirmation raised from a picker layers over it.

Command palette

ctrl+k opens a global search over every project and session on the machine, live and archived, and a list of workspace commands. It exists because the per-panel / search only filters the list in front of you, which is no help when you cannot remember which project the work was in, and because remembering that M refreshes metadata is not a reasonable thing to ask.

Command palette searching projects and sessions

Type to search. Results are grouped into categories with a tab bar under the input, and each tab owns the whole result area, so nothing is truncated and long result sets stay reachable. A category with no hits has no tab, so you can never land on an empty one. Each tab keeps its own cursor and scroll position.

| Key | Action | | --------------- | ------------------------------- | | ctrl+k | open the palette | | tab / shift+tab | switch category | | ↑ / ↓ | move through results | | pgup / pgdn | page through results | | enter | jump to the result, or run the action | | ctrl+u | clear the query | | esc | close |

Jumping selects the result's project, loads its sessions, highlights the session and focuses the right panel. Jumping to an archived session flips the list to the archived view first.

Open the palette with an empty input and the tabs show your recent searches and every action, so commands can be found by browsing rather than by knowing the name. The Actions tab groups them into Sorting, Filters, Workspace and Statistics:

| Group | What is in it | | ---------- | -------------------------------------------------------------------- | | Sorting | order the sessions or projects list by date, size or name | | Filters | show archived sessions, or only projects that are missing, orphaned or empty | | Workspace | rescan, refresh metadata, repair references, health check, diagnostics, backups, unpack, prune | | Statistics | storage, counts, and the largest projects and sessions |

Searching finds them by description as well as by name: largest reaches both size sorts and the statistics report, repair reaches the repair command, the health check and the missing-projects filter.

The split between the two surfaces is deliberate. The action menu (x) acts on whatever is highlighted; the palette acts on the workspace as a whole or on how it is displayed. Nothing appears in both, apart from repair, which behaves differently from each.

Sorting and filtering

Both lists keep an order and the projects list keeps a filter, and both hold until you change them. The active sort sits on the right of each panel's search row so the order is never a mystery.

Press s to sort the focused list, or pick a sort from the command palette.

| List | Orders | | -------- | ------------------------------------------------------------------------- | | Sessions | most recent, oldest, largest, smallest, title A to Z, title Z to A | | Projects | recently active, least recently active, most sessions, largest, name A to Z |

Filters come from the palette and narrow the projects list to what needs attention: missing on disk, orphaned, or empty. An active filter names itself in the panel title, and esc clears it.

"Least recently active" is the one worth knowing about. It surfaces the projects you have not touched in months, which is usually the list you want before deciding what to delete.

Session inspector

Step into the Sessions panel and the inspector reads the highlighted session in a single pass, filling four tabs. Press 1 to 4 to switch between them, or tab while the Details panel has focus.

| Tab | Contents | | ---------------- | ------------------------------------------------------------------------------------ | | 1 Overview | Id, project, branch, size, timestamps, message and tool-call counts, tokens, duration, model, top tools | | 2 Conversation | A readable preview of the exchange | | 3 Timeline | Activity over the life of the session | | 4 Files | Files the session touched and created |

J and K scroll the inspector from any panel, so you can read a preview without leaving the session list.

Titles come from the ai-title record Claude Code writes, the same one its resume picker shows. When a session has no AI title, the label falls back in order to the opening prompt, the first user message, the slash command that started it, and finally (empty session). Inferred titles are dimmed so a guess never looks like a real title.

Actions

Press x for the action menu. It holds the operations that act on the highlighted project or session, grouped into Session, Project and Dangerous, with the destructive group last and marked in red. Unavailable actions stay listed with the reason, so the menu doubles as documentation. Operations on the whole workspace are in the command palette instead.

Project actions menu

The menu adapts to the focused panel. From Projects only the project operations appear: the sessions panel always highlights a row, but you have not chosen it yet, so session actions wait until Sessions or Details has focus.

Session actions menu

Inside the menu, enter runs the selection and typing a shortcut key runs it directly.

| Key | Action | Group | | --- | ------------------- | ----------- | | e | Resume session | Session | | E | Resume session (yolo) | Session | | a | Archive session | Session | | r | Restore session | Session | | n | New session | Project | | N | New session (yolo) | Project | | m | Move project | Project | | F | Repair references | Project | | p | Pack project | Project | | i | Project information | Project | | c | Check integrity | Session | | d | Delete session | Dangerous | | D | Delete project | Dangerous |

Destructive actions confirm first and show the exact planned steps.

Managing projects and sessions

Resuming

e resumes the highlighted session, E resumes it with --dangerously-skip-permissions after a confirmation that shows the exact command.

Resuming is a round trip. Lazy Claude unmounts and hands the real terminal to Claude Code, then comes back up when Claude Code exits, selecting the session you were just working in. Nothing runs underneath in the meantime: Claude Code gets the terminal to itself, and a non-zero exit is reported in the status line on the way back. Set LAZY_CLAUDE_NO_RETURN to exit on handover instead, which is what you want if you use lazyclaude <path> as a one-shot launcher.

Neither wraps Claude Code. Lazy Claude unmounts, leaves the alternate screen, prints the shell equivalent, then executes Claude Code in the project's own directory with stdio inherited. What you get is the same as typing:

cd <project-directory>
claude --resume <session-id>

Everything is validated before the interface exits, so a missing claude binary, a project directory that has moved, a deleted session file, or an archived session (invisible to Claude Code until restored) each produce a dialog you can act on instead of a broken terminal.

Starting a new session

n starts a fresh Claude Code session in the highlighted project, from any panel. N does the same with --dangerously-skip-permissions after a confirmation. It is the same round trip as a resume, minus the --resume flag: browse to a project, press n, work, exit, and you are back in Lazy Claude with the new session at the top of the project's list.

Since there is no session yet, the return lands on the project rather than a session, and both keys are disabled while the project directory is missing on disk.

Moving a project

lazyclaude move operates on a project rather than a session. It moves the directory, renames the session folder for every session bound to it, migrates the folders of nested sub-projects and worktrees, updates history.jsonl, and keeps archived sessions in sync. Nothing has to be resumed.

lazyclaude move ~/code/old-name ~/code/new-name
lazyclaude move --here ~/code/some-project     # move it into the current directory
lazyclaude move ~/a ~/b -n                     # print the plan, change nothing

If the directory already moved, lazyclaude repair performs the same relocation after the fact. It auto-detects broken entries, searches likely new locations, and relinks explicitly or interactively.

lazyclaude repair                          # scan and relink what it can find
lazyclaude repair ~/code/new-location      # relink a known project by its new path
lazyclaude repair --from ~/old --to ~/new  # relink explicitly

Both run as journaled operations: every step records its inverse, and a failure undoes the completed steps in reverse order.

How this differs from /cd and /add-dir

Claude Code has two built-ins that touch this area, and they solve a different problem.

/cd changes the working directory of the session you have open and, since v2.1.169, relocates that session's storage too. Its scope is exactly one session: moving N sessions means resuming each and running /cd N times. /add-dir grants the open session access to an extra directory and relocates nothing.

| | Scope | Session must be open | Moves storage | N sessions at once | | ---------------------- | --------------------------------------- | -------------------- | ------------------------- | ------------------ | | /cd | the one open session | Yes | Yes, from v2.1.169 | No | | /add-dir | the one open session | Yes | No | No | | lazyclaude move | a project and every session bound to it | No | Yes, project and folders | Yes | | lazyclaude repair | same, when the directory already moved | No | Yes, session folders | Yes | | lazyclaude pack | one project, archived and restored | No | Yes | Yes |

Use /cd for a single live session you are working in right now. Use Lazy Claude when relocating a repository together with its full history, or repairing one that already moved.

Archiving

Archiving moves a session file to ~/.claude/lazy-claude/archive/, outside the projects directory, so Claude Code stops listing it until you restore it. Nothing is deleted. Press t to toggle between live and archived sessions, a to archive, r to restore.

Packing

lazyclaude pack writes a project and all its sessions into a portable .claudepack archive. unpack restores it to a new location and rewrites the paths for the new machine, which makes it the closest thing to a full snapshot before a large change.

lazyclaude pack ~/code/app                 # writes ./app.claudepack
lazyclaude pack ~/code/app ~/backups/app   # or name the archive yourself
lazyclaude unpack ./app.claudepack ~/code/app-restored

The destination must not already exist, so an unpack never merges into a live project by accident. Pass -f if you mean to overwrite.

Backups and health

move, repair, remove and unpack back up history.jsonl before touching anything, unless you pass --no-backup. The backup manager (B) creates, restores and deletes those snapshots.

[!NOTE] The automatic backup covers history.jsonl, not the transcripts themselves. For a full snapshot before a large change, run lazyclaude pack.

lazyclaude verify reports missing project directories and orphaned session folders and exits non-zero when it finds either. lazyclaude doctor prints where everything lives and how much of it there is. lazyclaude prune deletes session folders whose project no longer exists.

Keyboard shortcuts

Navigation

| Key | Action | | ------------------ | --------------------------------------------- | | ↑ / k, ↓ / j | move within the focused panel | | tab | cycle Projects, Sessions, Details | | shift+tab | cycle backwards | | enter, → / l | step down the hierarchy | | esc, ← / h | step back up |

Search

| Key | Action | | ------------------ | --------------------------------------------- | | / | search the focused list | | ↑ / ↓ | move through matches while typing | | enter | keep the filter, hand the keyboard back | | ctrl+u | clear the query without leaving search | | esc | clear the query and leave search | | ctrl+k | command palette: search everything, run commands | | s | sort the focused list |

Inspector

| Key | Action | | ----------- | ---------------------------------------------------- | | 1 .. 4 | overview, conversation, timeline, files | | tab | next tab, while the Details panel has focus | | J / K | scroll the inspector from any panel |

Actions

| Key | Action | | --- | --------------------------------------------------- | | x | open the action menu | | e | resume the session in Claude Code | | E | resume with --dangerously-skip-permissions | | n | start a new session in the highlighted project | | N | new session with --dangerously-skip-permissions | | a | archive the session | | r | restore an archived session | | d | delete the session permanently | | c | check session file integrity |

The action menu holds the operations that act on the highlighted project or session. Its shortcut keys are listed in Actions and work while the menu is open. Operations on the whole workspace live in the command palette instead.

General

| Key | Action | | --- | ------------------------------------- | | t | toggle live and archived sessions | | R | rescan projects and sessions | | ? | help | | q | quit |

CLI

Every TUI operation is also a command. Both front ends call the same services, so behavior is identical.

lazyclaude list [--json]            # all projects with status
lazyclaude sessions [archived]      # all sessions, titled
lazyclaude show <session-id>        # stats, preview and timeline
lazyclaude search <query>           # match titles, ids, paths, branches
lazyclaude info [path] [--json]     # project details (defaults to cwd)
lazyclaude stats [--json]           # storage, counts, largest projects
lazyclaude doctor                   # environment summary
lazyclaude verify                   # health check (exit 1 when issues found)

lazyclaude move <src> <dest>        # move project + migrate references
lazyclaude move --here <src>        # move project into the current dir
lazyclaude repair                   # scan and relink broken references
lazyclaude repair <new-path>        # relink a moved project by new path
lazyclaude repair --from A --to B   # relink explicitly
lazyclaude prune                    # remove orphaned session folders
lazyclaude remove <path>            # delete project + all session data

lazyclaude pack <path> [archive]    # create .claudepack
lazyclaude unpack <archive> <dest>  # restore .claudepack

lazyclaude backup                   # list history backups
lazyclaude backup create
lazyclaude backup restore <name>
lazyclaude backup delete <name>

lazyclaude session archive <id>     # ids accept unique prefixes
lazyclaude session restore <id>
lazyclaude session delete <id>
lazyclaude session check <id>       # integrity scan

| Flag | Meaning | | ----------------- | -------------------------------------------- | | -n, --dry-run | print the plan, change nothing | | -f, --force | skip confirmation prompts | | -p, --parents | create missing parent directories | | --no-backup | skip the automatic history.jsonl backup | | --json | JSON output for list, sessions, info and stats |

Session ids accept unique prefixes, so lazyclaude show 155552ca is enough.

The TUI needs a TTY and exits with an error otherwise. Use the CLI to inspect things from a script or a pipe.

Configuration

| Variable | Purpose | | ------------------------- | -------------------------------------------------------------------- | | LAZY_CLAUDE_CLAUDE_DIR | Override the Claude data directory. Useful for testing against a copy | | CLAUDE_CONFIG_DIR | Respected when set, the same variable Claude Code uses | | LAZY_CLAUDE_CLAUDE_BIN | Path to the claude executable, when it is not on PATH | | LAZY_CLAUDE_NO_RETURN | Exit when handing over to Claude Code instead of coming back |

The data directory resolves in that order and falls back to ~/.claude.

[!WARNING] Lazy Claude reads and mutates real Claude Code data. Point LAZY_CLAUDE_CLAUDE_DIR at a throwaway directory before trying anything destructive.

Demo

A walkthrough of finding a session, inspecting it, and resuming it:

https://github.com/user-attachments/assets/1a9a7ca4-f129-4eeb-96b2-6297c67345ed

Supported platforms

| Platform | Status | | -------- | ------------------------------------------------------------------ | | Linux | primary target, developed and tested here | | macOS | expected to work, including case-insensitive path canonicalization | | Windows | designed for, not yet tested |

All filesystem work uses Node.js APIs, path handling is separator-aware, the encoding treats \ and : the way Claude Code does on Windows, and cross-device moves fall back to copy-and-delete. The only runtime dependencies are ink, react and tar.

Documentation

One caveat worth stating plainly: this depends on an on-disk layout that is internal to Claude Code and changes between versions.

Contributing

git clone https://github.com/brunos3d/lazy-claude.git
cd lazy-claude
npm install
npm run dev       # tsc --watch
npm test          # tsc, then node --test over the compiled output
npm link          # try your build as lazyclaude

Running the tests needs Node 21 or newer, while the published CLI supports Node 18. There is no linter or formatter; tsc under strict is the type check.

Read docs/architecture.md first. It explains the layer separation, the journaled mutations, and why the on-disk encoding is never decoded. Issues and pull requests are welcome.

Credits

Inspired by LazyGit for the interface model, and by Clamp, whose behavior served as the reference for the session-migration semantics.

License

MIT