Skip to content
| Marketplace
Sign in
Visual Studio Code>Other>Project BadgeNew to Visual Studio Code? Get it now.
Project Badge

Project Badge

constyn

|
1 install
| (0) | Free
Colored, icon-tagged project badge in the status bar, plus a Projects sidebar that lists your recent folders ordered like the desktops on your Mac, and your open GitHub pull requests with their checks, reviews and conflicts. Nothing is written to your settings unless you opt in.
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

Project Badge

Shows the project you have open as a tag in the status bar, with an icon and color derived from its name, so you can tell VS Code windows apart at a glance. Both are computed at runtime — nothing is written to your settings or your repo.

It also adds a Projects view in the activity bar: every folder you have opened recently, wearing its badge color and icon, with the windows that are open right now on top — ordered left to right like the desktops on your Mac — and everything else greyed out below. Click the status bar tag to open a panel where you pick the project's icon and color.

Projects view

  • Open group: projects that have a window open right now, in the order of your macOS desktops (Spaces) from left to right. Click one to jump to it (VS Code switches to that window); the inline button opens a fresh window instead.
  • Not open group, greyed out: everything you opened before. Click to open it in a new window (projectBadge.projects.clickOpens can make it reuse this window instead); right-click for Open in This Window.
  • Drag an open project up or down to move its desktop to that place in Mission Control (macOS); see Reordering desktops.
  • Project Badge: Switch Project… is the same list as a quick pick, for the keyboard. Bind it to a key if you like.
  • Sort by desktop position (macOS default), last opened, or name from the view's … menu. Add Current Folder, Import from VS Code History, Remove Missing Projects and Clear Project List live there too.
  • Right-click a project for Open in This Window, Open in New Window, Customize Badge…, Reveal in Finder, Copy Path, Remove from List.
  • Multi-root workspaces show up as one project (the .code-workspace file). Missing folders keep a warning icon so a renamed or unmounted project is not silently lost.

How it knows where your windows are

macOS does not let an app read other windows' titles without Screen Recording permission, so the extension never tries. Instead, every VS Code window runs this extension; when a window gains focus, its copy asks a tiny bundled helper (bin/spaces-helper, ~20 lines of Swift around two window-server calls) which window is frontmost and on which desktop, and writes "that window is project X" into a file shared by all windows. The answer is only trusted once two readings a moment apart agree and no desktop switch is in progress, because a switch focuses the new window while the old desktop is still in front; a window that was just reloaded, and may still report focus after you have moved on, only fills in a window nobody else has. Ordering then only needs the helper's list of desktops. Nothing is sent anywhere and no permission prompt appears (dragging to reorder desktops is the one exception, below).

Every window also registers itself when it starts, so it counts as Open right away; its desktop is known once you click into it, or immediately when it is the only window left unidentified. Windows still running an older version of the extension (not reloaded since the update) cannot register and show as Not open until reloaded. The list refreshes every few seconds while the view is visible. On Windows and Linux there is no desktop tracking: the list is flat, sorted by last opened.

Reordering desktops by dragging

With the list sorted by desktop position, grab an open project and drag it up or down: it lifts and follows the pointer, the projects it passes slide out of the way, and a dashed drop zone shows where it will land. Let go and its desktop moves to that place in Mission Control, everything in between shifts over by one, and the row pulses until the move is done (it slides back if the move did not happen). Escape cancels a drag; with the keyboard, Alt+↑ / Alt+↓ moves the focused project one place. It works for fullscreen windows (each its own space) as well as for ordinary desktops, which move with every window on them.

The Projects list is drawn by the extension (a webview) rather than as a native tree, because a tree can only highlight the row under the cursor, not move rows aside. It looks and behaves like one: theme colors, hover cards, the right-click menu, inline buttons, collapsible groups, arrow keys and Enter.

macOS has no API for reordering desktops, so a second helper (bin/spaces-reorder) does what you would do by hand: it opens Mission Control, drags the desktop's thumbnail along the Spaces bar, and closes it again, which takes about two seconds. Driving another app's interface needs Accessibility permission, which macOS grants to VS Code (the app that starts the helper). The first drag explains this and opens System Settings → Privacy & Security → Accessibility; turn VS Code on and drag again. Mission Control would tile two fullscreen apps into Split View if one were let go over the other, so the helper waits for the bar to make room and releases the thumbnail on its own slot; if the bar never makes room, it calls the drag off and nothing moves. Desktops on different displays cannot be swapped this way.

How the list is built

The extension records the folder (or workspace file) of every window it activates in, with a timestamp. Removing a project hides it until you open that folder again. On first start it also imports VS Code's own File → Open Recent history from the user-data folder next to its storage (state.vscdb via the sqlite3 CLI when available, and storage.json), so the list is not empty. Imported projects have no timestamp and sort after the ones it has seen you open.

Setting Default What it does
projectBadge.projects.groupOpen true Split into Open and Not open (macOS)
projectBadge.projects.trackDesktops true Ask the window server where windows are (macOS)
projectBadge.projects.showDesktopNumber false Show "desktop 3 of 8" next to open projects (the tooltip always has it)
projectBadge.projects.clickOpens newWindow What a click does for a project with no window: a new window, or this one
projectBadge.projects.maxProjects 50 How many projects to keep
projectBadge.projects.showMissing true Keep showing projects whose folder is gone
projectBadge.projects.importFromEditor true Merge VS Code's Open Recent history on startup
projectBadge.projects.showPath / pathStyle true / parent Show the parent folder, or the full ~ path
projectBadge.projects.excludePatterns node_modules, .git Globs for paths that should never be listed

Claude Code status

If you run Claude Code, each project row also says what its agents are up to: ● working, ◐ needs you (a permission prompt or a question is waiting), or ✓ done. The row is tinted to match, and the Projects icon in the activity bar carries a count of sessions waiting for you. Nested folders are fine: a session started in app/packages/web is attributed to the most specific project that contains it. A session that stopped to wait for shell commands it started in the background still counts as working until they finish.

"Done" is for what just finished, and for what you have not looked at yet: it holds for projectBadge.projects.doneMinutes (10 by default) after the agent's last write, or until you focus that project's window, whichever is later. After that the row falls back to the folder's git state instead, so a glance tells you what is left to ship: ○ uncommitted changes, ↑ unpushed commits (or a branch with no upstream), ⇡ pushed but not yet merged into the default branch, or plain idle when everything is merged and pushed. Hover for the branch name and counts. Git state is shown for open projects only and refreshes every 20 seconds while the view is visible; projectBadge.projects.gitStatus turns it off.

Notifications. When an agent in another window finishes, the window you are in shows a toast with an Open button that jumps to that project (a finish in the window you are looking at stays quiet). When an agent starts waiting for you — a question or a permission prompt — you get the toast wherever you are, and “project needs you” stays pinned in the status bar of every window until it is answered; click it to jump there. If no VS Code window is focused, a single macOS system notification is posted instead, from a small bundled notifier app: it shows the project's colored icon, and clicking it brings up that project's window (and its desktop). macOS asks once to allow notifications for "Project Badge". Each finish is logged with how long the agent worked, and the tooltip shows it: "finished 5 minutes ago after 12 min". Right-click a project → Mute Notifications to put it in stealth mode: its sessions still show in the tree, but never notify or pin. Settings: projectBadge.projects.notifyDone, notifyWaiting, systemNotifications.

This reads Claude Code's own session registry (~/.claude/sessions/*.json, or under $CLAUDE_CONFIG_DIR) for what is running or waiting, and the per-folder conversation transcripts (~/.claude/projects/<folder>/*.jsonl) for when something last finished — a window reload restarts the Claude process, so the transcript is the only thing that remembers. Claude Code keeps both up to date itself, so there is nothing to configure and no hooks are installed. Sessions whose process has exited are ignored. Turn it off with projectBadge.projects.claudeStatus.

After updating the extension, each open window keeps running the version it loaded until it is reloaded, so for a while old and new behavior coexist. Windows that lag behind offer a Reload Window prompt once the Claude sessions in them are idle.

Codex status

Codex sessions appear in the same project rows and Switch Project picker, labeled Codex working, Codex needs you, or Codex done. When Claude and Codex share a project, both are listed; waiting takes priority over working, and working over done. Completion notifications, notification muting, the waiting badge and status bar, and doneMinutes apply to both agents. Reload and branch-checkout checks also account for Codex.

Activity is read locally from ~/.codex/sessions (or $CODEX_HOME/sessions) every five seconds. Codex's task_started, task_complete, and turn_aborted rollout events identify turns. On macOS and Linux, lsof confirms that a Codex process holds the rollout or its thread-writer lock open, so a stale transcript cannot keep a project marked working. Completed turns remain visible after Codex exits. Sub-agent transcripts are excluded to avoid counting one conversation more than once. Nothing is written to Codex's files and no hooks are installed.

Needs you is detected for synchronous request_user_input calls recorded in the rollout. Permission prompts or questions that Codex does not persist remain working until the turn ends. Live detection requires lsof; Windows and systems without it show completed activity only. Disable this feature independently with projectBadge.projects.codexStatus.

Pull Requests view

Below Projects, Pull Requests lists every open pull request you opened on GitHub, in any repository, grouped by repository. The repository this window's project is a clone of comes first, highlighted like this window's row in Projects; the rest follow by most recent update. So each window shows its own work first. When this window has a pull request's branch checked out, that pull request goes to the very top and takes the highlight instead. Only that repository starts unfolded; every other one is folded to a single line that sums it up, one icon and count per state, colored like the rows: ✓ 2 ready to merge (green), ✗ failing checks (red), ⚠ conflicts, ! changes requested and ↓ behind (orange), ⟳ checks running (blue), and ◉ waiting for review, ⊘ blocked and drafts in grey. Hover a count to see what it means. Fold or unfold any repository yourself and that window remembers it. Each pull request takes two lines: the badge icon of its project and the title, then three status icons under the title, always in the same order:

Other people's pull requests are listed too: the open ones in every repository you have pull requests in or a local clone of, as long as you can push there (an open-source project you once cloned is left out), plus any pull request anywhere that requests your review, directly or through a team, or is assigned to you. They sit in each repository under a folded Others line that sums them up (want your review, from bots, passing CI, the rest). Unfolded, they come in that order of priority: what asks for you first (with an orange Your review and a stripe), then bots, then those passing CI, then the rest, newest first within each. Their rows start with who opened them; conflicts or being behind show in grey, since that is theirs to fix, and Fix with Claude is only for your own and those opened by bots (like Renovate or Dependabot). The folded repository line counts them too, in orange when some want your review. Someone else's pull request you have checked out in this window joins yours at the top.

  • Checks: ✓ Passing, ✗ 2 failing, ⟳ Running, or No checks.
  • Review: Approved, Changes requested, Needs review (the repository requires one), Commented, or No reviews. Comments from bots such as CI summaries do not count.
  • Rebase: ⚠ Conflicts with the base branch, or ↓ 12 behind in orange when the repository requires branches to be up to date before merging. A branch that merges cleanly shows Up to date, or a grey ↓ 26 behind when a rebase is possible but optional. Ready to merge replaces it once everything is green, and Blocked when it is approved but GitHub still holds the merge.

Problems are colored (orange for conflicts and requested changes, red for failing checks) and get a stripe at the left edge, as does a pull request that is ready to merge (green). Rows waiting on someone else stay grey. Drafts are faded. The number sits at the end of the status line and is left out when the sidebar is narrow.

The icon is the badge of the project the pull request belongs to, in its color, exactly as in Projects. That is the clone that has the pull request's branch checked out, or, when none has, the repository's clone: an open one before a closed one, most recently opened first. So frontend, frontend2 and frontend3 share an icon, and the color tells you which clone holds the branch. Any remote counts, and a clone made before its repository was renamed is still recognized. Repositories you have no clone of get a plain icon.

Hover a row for the full title, the names of failing checks, who reviewed, how many commits it is behind its base, and where it is checked out. Click a row to open it on GitHub. Hover a pull request of this window's repository for Check Out Branch in This Window (the branch icon): it fetches the branch from the remote that points at GitHub and switches to it, creating a local branch that tracks it, or fast-forwarding yours when it is only behind (one with commits of its own is left as it is). If the folder has uncommitted changes, or a Claude Code session is working in it, you are asked first. Hover a repository for Open Project (jumps to the clone's window) and Open on GitHub. Right-click for those plus Copy Link and Copy Branch Name. Like Projects, the view is drawn by the extension (a webview), which is what makes room for the second line; arrow keys, Enter and Left/Right to fold a repository work as in a tree.

Fix with Claude

A pull request that is out of date (conflicts, or behind its base while it waits for review), has failing checks, or has review feedback waiting gets a Fix with Claude button (the sparkle) when you hover it, and the same in its right-click menu. It needs a local clone of the repository among your projects and the Claude Code CLI (claude).

After you confirm what it will do, Project Badge makes a git worktree at the tip of the pull request's branch, <clone>/.claude/worktrees/fix-pr-<number>, so nothing in your checkouts changes, and starts a Claude Code background session in it (claude --bg). The session:

  • rebases onto the base branch and resolves conflicts, fixes the failing checks (reading their logs with gh), and makes the code changes reviewers asked for;
  • runs the relevant tests, then pushes to the pull request's branch, force-pushing after a rebase with --force-with-lease on the tip it started from, so nothing anyone pushed meanwhile is overwritten;
  • waits for CI and, if it fails, fixes and pushes again, up to 3 rounds;
  • never merges, never edits the pull request or posts on GitHub, and asks you when something needs a decision.

Claude Code runs background sessions only in folders you have trusted, and a clone you only ever used Claude in through VS Code may never have been asked. The first fix in such a clone says so and opens claude there in a terminal; accept its trust prompt and the fix starts by itself, the terminal closing on its own. Each clone needs this once. Project Badge only reads Claude's trust record, it never writes it. It runs with your own Claude Code settings and permission mode. While it works, the row says ✦ Fixing… in purple (the folded repository line counts it too), and Needs you when it waits for an answer, which also brings up the usual Claude Code notification. Watch opens the session in a terminal (claude attach), where you can follow it, answer, or take over; Stop ends it. Fix sessions stay out of the Projects list: the clone's row does not count them, and when one needs you, you get a single notification with Watch.

When the session is done, Project Badge removes it and deletes the worktree, and tells you how it went in Claude's own words (Show Summary opens the whole closing message). If anything in the worktree is not on GitHub (uncommitted changes, or commits that were not pushed), the worktree is kept and you are told where. If the repository does not already ignore .claude/worktrees/, it is added to the clone's local .git/info/exclude, so the worktree does not show up as a change. Every window shows the runs, and if the window that started one closes, another window finishes following it.

is logged in (gh auth login), its token is used with no prompt. Otherwise the view offers Sign in to GitHub, which uses VS Code's own GitHub account. Project Badge stores no token. The list refreshes every 2 minutes in every window that shows it, focused or not, so a window on another screen stays current too; coming back to a window or opening the view refreshes it when it is more than 30 seconds old, and the refresh button always does. Windows share each fetch through a small file in the extension's storage, so a dozen open windows still ask GitHub about once every couple of minutes. A line under the list says when it was last updated, and its icon spins while a refresh runs. GitHub works out whether a pull request has conflicts only when someone asks, so a fresh one can take a few seconds to show it.

projectBadge.pullRequests.query changes the search: is:open is:pr involves:@me also lists pull requests you review, and org:<name> keeps to one organization.

Customize panel

Click the tag in the status bar (or right-click a project → Customize Badge…, or run Project Badge: Customize Badge…) to open a panel with a live preview, the palette as swatches plus a custom color picker, and all icons in sections. Search them by plain words (phone, money, chat), hover one to try it on the preview, and use the arrow keys and Enter to pick without the mouse. A dot marks an icon another project already shows. Picks are written to projectBadge.overrides and projectBadge.iconOverrides in your user settings and apply to every window of that project immediately; Auto (from name) removes the override again.

Icons

  • The glyph before the name is a codicon picked by hashing the project name with digits removed: frontend, frontend1 and frontend-2 all share the same icon, while their colors still differ. Related windows look like a family; the color tells them apart.
  • 117 icons to choose from. If another project stem on this machine already holds the preferred icon, the next free one is used, and the assignment is remembered (same mechanism as colors). The tooltip shows which one was picked.
  • Don't like the draw? Project Badge: Shuffle Icons sets a random projectBadge.iconSeed, which reshuffles every project's icon at once while keeping the digit-sharing rule; Set Icon Seed… lets you type any text. Or pin one in the Customize panel (click the tag) or with Project Badge: Pick Icon for This Project (stored in projectBadge.iconOverrides, keyed by the digit-stripped name).
  • projectBadge.statusBar.style switches to a plain swatch (square, dot, block, tag) or none.

Accents (no settings writes)

Everything here is applied at runtime through the decoration and status bar APIs, so nothing is written anywhere.

Setting Default What it colors
projectBadge.accents.editorRail true Thin line in the project color down the left edge of the text in every editor
projectBadge.accents.scrollbar true Strip in the project color in every editor's scrollbar
projectBadge.accents.statusBarBookend true With a one-sided tag, a matching swatch at the opposite end

Theme tints (opt-in, write to workspace settings)

VS Code has no runtime API for backgrounds or theme accent colors; the only way to color those is workbench.colorCustomizations. These are therefore off by default and, when enabled, write to the workspace's .vscode/settings.json.

Setting Default What it colors
projectBadge.tint.tabs false Active editor tab top border, active terminal tab, active panel title
projectBadge.tint.activityBarAccents false Active activity bar indicator and its badge
projectBadge.tint.badges false Badges (unread/result counts)
projectBadge.tint.focusBorder false Focus outlines, sash hover, progress bars
projectBadge.tint.windowBorder false Thin border around the window
projectBadge.tint.cursor false Editor and terminal cursors
projectBadge.tint.links false Text links
projectBadge.tint.commandCenter false Command center (title bar search box) text and border

All of these are written to the workspace's workbench.colorCustomizations alongside the tag color; Project Badge: Remove Workspace Tint removes exactly the keys this extension owns and nothing else.

Colors

  • 14 curated dark-theme colors: Red, Orange, Yellow, Lime, Green, Teal, Mint, Sky, Blue, Violet, Magenta, Pink, Tan, Silver. Every pair is at least 16 CIEDE2000 units apart and every color has at least 4.5:1 contrast on a dark status bar, so no two are easy to confuse.
  • A hash of the project name picks its preferred color; if another project on this machine already holds it, the next free color is used. Assignments are remembered, so colors stay stable and distinct until you have more than 14 projects.
  • Tag text is the same hue, darkened.
  • Project Badge: Pick Color for This Project opens a Quick Pick over the palette (plus Auto / custom hex). Overrides are stored in projectBadge.overrides.
  • projectBadge.palette replaces the built-in list with your own hex colors.

Filled background (opt-in)

projectBadge.statusBar.filled gives the tag a solid background. VS Code only lets a status bar item use the warning background slot, so this remaps statusBarItem.warningBackground / warningForeground in the workspace's workbench.colorCustomizations — which is why it is off by default.

Settings

Setting Default Description
projectBadge.statusBar.enabled true Show the tag
projectBadge.statusBar.alignment both both ends of the status bar, or right / left only
projectBadge.statusBar.style icon Glyph before the name: icon (from the name, digits ignored), square, dot, block, tag, none
projectBadge.statusBar.filled false Filled background vs. colored text only
projectBadge.palette [] Your own hex colors; empty = built-in palette
projectBadge.overrides {} { "name": "#hex" } per-project overrides
projectBadge.iconSeed "" Text mixed into the icon hash; change to reshuffle all icons
projectBadge.iconOverrides {} { "frontend": "rocket" } icon pins, keyed by digit-stripped name
projectBadge.tint.sideBarHeader / titleBar / statusBar / activityBar false Opt-in: tint larger UI areas with the project color

Commands

  • Project Badge: Pick Color for This Project
  • Project Badge: Reset to Auto Color
  • Project Badge: Pick Icon for This Project
  • Project Badge: Shuffle Icons (random seed) / Set Icon Seed…
  • Project Badge: Forget Remembered Color and Icon Assignments
  • Project Badge: Copy Project Path (also: click the tag)
  • Project Badge: Apply Workspace Tint / Remove Workspace Tint
  • Project Badge: Refresh
  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
  • Your Privacy Choices
  • Consumer Health Privacy
© 2026 Microsoft