Skip to content
| Marketplace
Sign in
Visual Studio Code>Other>Koh-VibeNew to Visual Studio Code? Get it now.
Koh-Vibe

Koh-Vibe

Thomas Jacquin

|
1 install
| (0) | Free
All your Claude Code sessions in a single view: live status, folders, usage and chimes.
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

Koh-Vibe

Version française

Every Claude Code session you have running, in one view: across projects, across windows, across editors — with its status, what it is doing right now, and your usage.

Koh means "island" in Thai. Inspired by open-vibe-island, which does the same thing in the Mac notch. No code is taken from it.

macOS only. Chimes go through afplay, the usage token is read from the system keychain, and the hook bridges are zsh scripts.

What it shows

  • Live sessions, sorted by what wants your attention: the ones waiting for you first, then the ones working, then the ones that just finished.
  • A status dot per session — one glyph, five colours — next to the project, the branch and the tool currently running. The row is named as the tab is: the title you gave it, else the one Claude generated, else the last prompt.
  • Ended conversations stay in the list, greyed out and in their folder, for as long as Persistent sessions is on in the settings (it is by default). Turn it off and closing a tab takes the row away instead. Recently closed, a view of its own, keeps the ten conversations that ended most recently either way.
  • Temporary sessions is where a conversation lands until you drag it into a folder. Left there for 24 hours without activity, it leaves the list — a setting turns that off.
  • Close a conversation with the trash icon that appears when you hover a live row. It closes its Claude Code tab and removes the row — the conversation goes to Recently closed — in one click, whatever Persistent sessions says: that setting is for the tabs you close yourself. A restored tab is closed in place, without being opened. When no tab is found — a conversation running in a terminal, in the Claude desktop app, or in a project no window has open — the row is simply removed from the list. On a greyed row, the icon removes it for good. A conversation that ends before its first message — Claude Code starts one for every panel it opens — leaves no row and no history: there is nothing to come back to.
  • Your usage over five hours and seven days — and per model, when your plan counts one apart — with the time until it resets.
  • One click opens or resumes a session's window, wherever it lives — a closed one included.

What's new in 1.2.0

Since 1.1.0:

  • Ended conversations stay in the list, greyed out, in their folder — and a setting, Persistent sessions, decides it. Reopening one brings back that very conversation, never a blank one: the editor tab when Claude Code will find it from this window, a terminal otherwise.
  • Temporary sessions replace Unfiled: left out of every folder for 24 hours, a conversation leaves the list. A second setting turns that off.
  • The trash closes in one click — the tab and the row at once. A tab the editor restored is closed in place.
  • Restored tabs are open sessions. After a window reload, every Claude tab still open is listed as idle — never greyed, never opened twice: a click brings it to the front.
  • New session from the dashboard: the + in the view title, or the one at the right of a folder row, which files the conversation there.
  • A spinner while a conversation comes back, on its row — and while Recently closed loads.
  • Rows are named as the tabs are — the title you gave, else Claude's, else the last prompt. A conversation that never got a message leaves no row and no history.
  • Nothing is forgotten for going quiet: a silent conversation stays; Refresh brings back the ones the list lost, in their folder; a conversation that vanished while its process still runs comes back on its own.
  • Usage per model, when your plan counts one apart.
  • Two default chimes travel in the package, so a fresh install is not silent.

Install

The extension is not published on the marketplace; it installs from a locally built package. From the integrated terminal of the editor you want it in:

pnpm install
sh install.sh

install.sh builds, packages under a throwaway version number and installs into the editor its terminal belongs to — VSCode, Cursor or Antigravity, whichever runs it. Then reload the window (Developer: Reload Window). The number comes from the clock so that every install lands in a fresh directory: the one in package.json only moves at release time, and reinstalling under the same number leaves the editor serving what it already had.

By hand, the same thing is pnpm package then code --install-extension koh-vibe-*.vsix --force — VSCode forks expose the command under their own binary name, usually installable from their palette via Install 'code' command in PATH. Installed that way, under the unchanged version number, quit the editor fully rather than reloading the window.

Install the hooks

Nothing appears until Claude Code starts dropping its events. Open the Koh-Vibe view and click Hooks not installed, or run Koh-Vibe: Install hooks from the palette.

The script adds eight hooks to ~/.claude/settings.json, backs the file up before touching it, and refuses to write if its fingerprint changed in the meantime. Hooks and a status line you already had are preserved: Koh-Vibe chains onto the end, it replaces nothing. Koh-Vibe: Uninstall hooks undoes exactly that.

Using it

Filing. Create folders, drag sessions into them, give them a colour. The order inside a folder is set by hand and stays put: a session opened later lands at the end without disturbing what you placed. The folders themselves are dragged the same way — drop one onto another to put it in front, or onto Temporary sessions to send it to the end.

New session. The + button in the view title opens a new Claude Code tab — a fresh conversation in the window's folder. Hover a folder: the same + appears at the right of its row (right-click offers it too, as New session here) and files the conversation in that folder as soon as it shows up, so it is not a temporary one.

Chimes. One when a session starts waiting for you, another when it finishes. Three levels, most specific first: a conversation's sound beats its folder's, which beats the global setting. "None" is a chosen silence rather than an absent choice, so it does not fall through to the level above.

The macOS sounds are the baseline. Koh-Vibe offers to add a library of a hundred short interface sounds (Kenney, CC0), downloaded once and kept in its own folder — never in ~/Library/Sounds, whose listing also feeds the system Sound panel. The Sound library row in the settings installs and removes it.

Two of its sounds travel inside the package, renamed after what they announce: Attente, when a session starts waiting for you, and Fin, when it finishes. A fresh install starts on those two, so the dashboard chimes from the first launch, library or no library. They are a default, not a policy: a sound already chosen — a chosen silence included — stays as it is, and an update never puts them back.

In the picker, the arrow keys play each sound; → replays the highlighted one.

Removing. Right-click a session → Remove from the list. Nothing is stopped: Claude Code runs in its own terminal, and a session still alive reappears on its next event.

Persistent sessions. The first row of the settings, a checkbox, decides what closing a tab does to its row. Checked — the default — the conversation stays in the list, greyed out, in its folder, with a muted dot and the time it closed; the fifty most recent are kept, and Remove from the list takes one away for good. Unchecked, closing the tab removes the row instead; the rows already greyed stay either way. Hover the row for the same explanation.

Temporary sessions. The second checkbox. A conversation filed in no folder is temporary: after 24 hours without activity it leaves the list — hidden, not forgotten, so any activity in it brings it back, and filing it in a folder keeps it for good. Unchecked, temporary conversations stay until you remove them.

Reopening. One click on an ended conversation — a greyed row, or an entry of Recently closed — brings it back: in the editor tab it ran in, or a fresh terminal on its folder, whichever it came from. The editor tab only when Claude Code will find the conversation from this window — its transcript under the window's own project, and not hidden from its session list; otherwise a terminal resumes it, which works from anywhere. A restored tab nobody has opened yet is simply brought to the front, never opened a second time. While it comes back, the row spins in place of its dot — a few seconds pass between the click and the conversation showing up, during which nothing else moves — and takes no second click, which would open a second tab. The spinner clears when the conversation is open again, or after thirty seconds without it.

Where the data lives

Everything sits under ~/.koh-vibe/:

bin/ the bridge and the status-line wrapper, copied when the hooks are installed
events/ the spool: one file per event, consumed then deleted
events/rejected/ what could not be read, kept rather than dropped
sessions/ the reduced state, one file per session
requests/ focus, reopen and close requests, from one window to another
backups/ copies of settings.json taken before each hook install
groups.json folders, their colours, the chosen order and the sounds
closed.json the ten most recently closed conversations
settings.json global sounds, volume, and the two list settings
usage.json the last usage reading, cached
status.json the last status-line snapshot
sounds/ the library, if you installed it

These files are shared across every window and every editor on the machine: a folder made on one side shows up on the other, and a sound chosen once applies everywhere. Uninstalling the extension does not erase them; deleting the directory is enough to start over.

How it works

Claude Code's hooks call a shell bridge that parses nothing: it copies what it receives into the spool, never writes to standard output, and always exits successfully. A bridge that parsed JSON could fail, and a failing hook disturbs the session it observes — the only acceptable behaviour is to break nothing, even at the cost of losing an event.

Each window watches the spool on its own, reduces the events into state, and displays it. No locks: shared files are merged three ways (the state read, ours, and the freshest one re-read just before writing), so two windows filing at the same time do not erase each other.

A conversation leaves the list when it ends, when you close it, or when you remove it — never because it went quiet: a tab you left open for a day is still a conversation. Refresh reads Claude Code's own registry of running processes (~/.claude/sessions/) and brings back every live conversation the list has lost, in the folder it was filed in. The same pass runs when the window opens, and a few seconds after a conversation vanishes while its process still runs — the same conversation open in two editors, one of them quitting — with a spinner in place of the button while it does. Tabs the editor restored but you have not opened since are listed like any idle session — the tab is open, that is what counts. The editor resolves only the active tab, so no Claude Code process runs behind the others until they are shown: a click brings the tab to the front, and Claude Code resumes it. « Remove from the list » hides a conversation until its next activity.

Usage comes from Anthropic's API, called at most once every five minutes and cached in a shared file — otherwise every window would fetch exactly the same thing. The OAuth token is read from the system keychain, never logged and never written to disk.

Contributing

Outside contributions are welcome — see CONTRIBUTING.md.

Development

pnpm install
pnpm build       # compiles to out/, and stamps the build from the latest tag
pnpm test        # builds, then runs the whole suite without an extension host
pnpm test:watch  # the same tests, without rebuilding on every run
pnpm typecheck   # types across src AND test
pnpm package     # produces the .vsix

pnpm test builds first because the end-to-end test runs scripts/install-hooks.cjs, which loads the compiled installer. That dependency used to be invisible: it held on a machine that had built once, and failed on a fresh clone.

Tests do not start VSCode: vscode resolves to a stub (test/stubs/vscode.ts), which makes the tree, the commands and the bridge testable in milliseconds. The type checker, however, works against the real API — a stub that drifted from its signatures would prove nothing.

scripts/make-icons.cjs regenerates both icons from the point table it contains: that table is the source of the drawing.

Versioning is described in CLAUDE.md — one pull request merged into main is one version, and the delivery workflow posts it on its own.

Licence

MIT.

  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
© 2026 Microsoft