stardance has been extended another month! the new deadline is october 31 :)

You are browsing as a guest. Sign up (or log in) to start making projects!

Tab Rot VS Code

  • 12 Devlogs
  • 15 Total hours

I’m making Tab Rot, a VS Code extension where your tabs literally decay if you ignore them. They get faded and cracked over time, and clickng them heals them. It’s basically a sick guilt trip for tab hoarder s.

Ship #1 Pending review

I built Tab Rot, a VS Code extension that makes your files visually decay if you ignore them. The most annoying part was mocking the VS Code API to write unit tests, plus fixing a random Node js crash when I tried to publish. Im super proud of the actual visual rot effect and that the state save even if you restart VS Code. If you wanna test it, just drop the decay timer in the setting to like 1 minute, otherwise you’ll be waiting an hour to see it work.

  • 12 devlogs
  • 15h
Try project → See source code →
Open comments for this post

2h 5m 56s logged

I built a proper settings webview panel for Tab Rot because asking users to edit raw JSON for threhold values felt hostile. Made a settingsPanel.ts that opens a dedicated webview tab with a clean form — three number inputs for the decay thresholds (stage 1, 2, 3 in minute), three toggle switches for decorations, status bar, and notifications. The whole thing uses VS Code’s CSS variables so it automatically matches the user’s theme — dark mode, light mode, high contrast, whatever. It looks native.The panel is a singleton — if you already have it open, running the command again just focuses the existing panel instead of spawning duplicates. The HTML is inline because it’s small enough that a separate file feels like overkill, but it’s structured with proper labels, hints explaining what each value means, and a little visual preview of the three decay stages as colored badges. The toggles are custom CSS switches that feels nicer than raw checkboxes.

0
0
21
Open comments for this post

1h 41m 57s logged

Testing

today I finally sat down to write unit tests for tabTracker.ts. I’ve been putting this off becaus, honestly, testing feels like homework when you just want to see the thing work. But I knew if I didn’t write tests now, Id never catch the bug s hiding in the decay logic.

0
0
52
Open comments for this post

2h 15m 43s logged

built the sidebar tree view for Tab Rot. Made a decayView.ts with a DecayTreeProvider that implements VS Code s TreeDataProvider interface. It pulls all decayed tabs from the tracker, sorts them by stage with the worst rot first, and renders each one as a DecayItem with the filename as the label, a stage emoji + name as the description (like “🍂 Faded” or “💀 Cracked”), and a tooltip showing how long it’s been since the file was last visited. Each item gets a stage-specific SVG icon and clicking it’s opens the file in the editor.I also created four littl SVG leaf icons in resources/icons/ — a green one for fresh tabs, orange-yellow for faded, brown with dots for grainy, and a dark cracked one for stage 3. They’re just simple leaf shapes but the color coding makes the sidebar immediately scannable.Wired the tree provider into extension.ts and registered it under the view ID tabRot.decayedTabs in package.json. The view lives in the Explorer sidebar and only shows up when there are actually decayed tabs, thanks to a context key tabRot.hasDecayedTabs that I set on every refresh. So if all your tabs are fresh, the sidebar section disappears completely instead of sitting there empty and sad.Added a tabRot.openDecayedTab command that the tree items use to open files when clicked. Since opening the file triggers onDidChangeActiveTextEditor, the tab gets touched and restored automatically, complete with the green flash animation from Phase 5. So the flow is: see rotting tab in sidebar → click it → file opens → green flash → tab is fresh again. Very satisfying.I also updated all the refresh calls so the sidebar stays in sync — it refreshes after every tab touch, close, restore command, and interval tick. And the showDecayedTabs command from Phase 4 now actually works because the view is registered, so that unhandled rejection error is gone.

0
0
59
Open comments for this post

37m 57s logged

I builts the restoration flash animation today because instantly snapping from cracked stage-3 to pristine stage-0 felt robotic. I wanted a little “healing” moment — like the file is literally coming back to life. Added a flashRestore() method to tabDecorator.ts that chains two temporary decoration flashes: a bright green pulse at 0ms, a softer second pulse at 300ms, then clear at 600ms. The tab breathes green for a second and then settles into its clean state. I also added a “✨ Tab restored!” info message because I’m a sucker for positive feedback.I wired the flash into two places: when you actively switch to a decayed tab (it detects the old stage was > 0, touches it, then flashes), and when you run the restoreTab comand manually. So whether you click into a rotting file or hit the command palette, you get the dopamine hit.I also added an optional decay notification system. Every 60 seconds during the interval tick, it checks if any tab crossed into a higher decay stage. If tabRot.showNotifications is enabled, it pops a toast like “📉 utils.ts reached stage 2 (unvisited for 1440 minutes)”. I defaulted it to false because getting spammed every minute that your tabs are dying would make people uninstall immediatey. But for accountability masochists, its there.

0
0
30
Open comments for this post

1h 29m 54s logged

I built the status bar and command layer for Tab Rot. Made a statusBar.ts that creates a StatusBarItem shoved over to the right side of the bar at priority 100. It shows a little 🍂 leaf emoji followed by how many tabs are rotting — like “🍂 3 rotting” — but only when there’s actually something decaying. When the count hits zero it hides itself completely so it’s not sitting there being useless and cluttering the bar. Clicking it is supposed to focus the sidebar view later, but since I haven’t built the sidebar yet, it’s basically a button that promises something it can’t deliver. I also gated it behind the tabRot.enableStatusBar config so people can kill it if they want.Registered three commands in package.json — tabRot.restoreTab to freshen up whatever file I’m currently staring at, tabRot.restoreAllTabs to reset every tracked tab back to stage 0, and tabRot.showDecayedTabs which is supposed to focus the sidebar. I wired all the handlers in extension.ts. restoreTab grabs the active editor URI, calls tracker.restoreTab(), then immediately refreshes the decorations and status bar so the rot vanishes right away. restoreAllTabs does the same thing but for everything and pops up a little info message saying “✨ All tabs restored!” because I wanted it to feel satisfying. showDecayedTabs tries to execute tabRot.decayedTabs.focus which is a VS Code auto-generated command for tree views.I also added a context menu to contributes.menus.editor/title/context so when you right-click in the editor area you get “Restore Tab” and “Restore All Tabs” right there without having to open the Command Palette. I grouped them under 9_tabRot so they sit in their own little section instead of getting drowned in the giant VS Code right-click menu.

0
0
82
Open comments for this post

1h 20m 43s logged

Implimented Visual Decay Decorations

I built the entire visual decay layer for Tab Rot over the past two days. Created tabDecorator.ts with three TextEditorDecorationTyp instances one for each decay stage. Stage 1 is a slight washout with opacity: 0.75 and a warm background tint. Stage 2 gets heavier with opacity: 0.55, a dashed brown border, and a darker background. Stage 3 is the nasty one — opacity: 0.4, solid border, wavy strikethrough, and a dark background that makes the code genuinely look abandoned.
The updateDecorations() method loops through all visibleTextEditors, grabs the decay stage from the tracker, clears any previous decorations (super important so they dont stack), and applies a full-document Range if the stage is above zero. I register all decoration types in context.subscriptions so VS Code cleans them up on deactivate.
I also registered custom theme colors in package.json under contributes.colors — background tints and overview ruler colors for all three stages, with separate defaults for dark, light, and high-contrast themes. Then I swapped out all the hardcoded rgba() values in the decorator for new vscode.ThemeColor(…) so user can customize the palette in their settings.json if they want.
Wired everything into extension.ts — updateDecorations() gets called after activation, after every onDidChangeActiveTextEditor (so visiting a tab instantly removes the rot), after onDidCloseTextDocument (cleanup), inside the 60-second interval (so decay progresses live), and on onDidChangeVisibleTextEditors (for split views).

0
0
30
Open comments for this post

50m 57s logged

Wiring the Engine + Config Schema

I wired up the TabTracker into the actual extension entry point today. Made an extension.ts that instantiates the trackr when VS Code activates the extension, then immediately scans all already-open text documents and registers them with touchTab() so nothing gets lost if the user already has files open. I hooked into onDidChangeActiveTextEditr to call touchTab() every time the user switches tabs, and onDidCloseTextDocument to remove tabs when files close. I also set up a setInterval that fires every 60 second to call updateAllStages() so the decay actually progresses in real time without waiting for someone to interact.I also completely redid the configuration schem in package.json. Instead of the array-based thresholds I had before, I switched to individual keys : tabRot.stage1Threshold, stage2Threshold, and stage3Threshold with defaults of 60, 1440, and 10080 minutes respectively. That maps to 1 hour, 1 day, and 1 week which feels way more intuitive than the old array. I also added two boolean flags — enableDecorations and enableStatusBar — so users can toggle the UI features later without digging through code.I updated tabTracker.ts to read from the individual config key instead of the array, and kept the hot-reload listener so if someone edits their settings the thresholds update live. I peppered console.log everywhere for debugging — activation messages, tab touch events, removals, and a periodic log of how many decayed tabs exist.

0
0
15
Open comments for this post

1h 26m 18s logged

Core State Engine — tabTracker.ts

I finally started the actual VS Code extension part of Tab Rot after planning everything out. Today’s goal was just the core state engine — basically tracking when each file was last visited and making sure it survives if you close and reopen VS Code. I made a tabTracker.ts file that has a TabState interface and a TabTracker class. The interface is super strict with the decay stages locked to 0 | 1 | 2 | 3 which felt like good TypeScript practice but also kind of a pain later.The tracker uses a Map to hold everything in memory, but it loads from and saves to context.workspaceState so the data persists across restarts. I added all the main methods — touchTab() to mark something as visited right now, removeTab() when a file closes, getDecayStage() to figure out how rotten a tab is based on the time thresholds, and getDecayedTabs() to spit out everything that’s stage 1 or higher sorted by how dead it is. I also threw in restoreTab() and restoreAllTabs() for when you want to pretend you never abandoned that file.I set it up to read the decay thresholds from VS Code settings (tabRot.decayThresholds) and even made it hot-reload when you change the config without restarting the whole editor. Oh and I added a debounced save because I realized it would be stupid to write to disk every single time you switch tab

0
0
6
Open comments for this post

30m 33s logged

Planned the Tab Root Project

Today, I planned the development roadmap for my Tab Root VS Code extension. After finishing the initial project setup, I broke the project into smaller tasks and subtasks so I can develop the extenssion step by step.I created a task list covering the main parts of the project, including tab tracking, the decay system, tab activity detection, visual tab changes, restore functionality, user configuration, testing, documentation, and the final release.Breaking the project into small tasks should make it easier to track my progress and understand what I need to work on next. I also organized the tasks into diffarent phase so I can focus on building the core functionality before moving on to the UI and release.

0
0
18
Open comments for this post

43m 54s logged

Implemented Project Structure

What I worked on:Today, I started working on my first VS Code extension, called Tab Root. I initialized the project and set up Git for version control. I also created the basic file and folder structure for the extension and configured the project to use TypeScript.After setting everything up, I created my first working VS Code extension. I added a basic VS Code command and tested it successfully inside VS Code. This was my first time creating and running an extension, so getting the basic setup working was an important first step for the project.

0
0
46

Delete project?

Are you sure you want to permanently delete this project? This action cannot be undone.

All devlogs, followers, and associated data will be removed.

Followers

Loading…