Tab Haunting Chrome Extension — Complete User Guide
How every ghost appears, what triggers it, and how the formulas behind it actually work.
Chrome Extension · Manifest V3 · FreeWhat Is Tab Haunting and What Does It Calculate?
Tab Haunting is a humor-first browser productivity extension for Google Chrome. Every time you close a browser tab, the extension quietly records how long you spent on it, what kind of page it was, and how important it appeared. A short time later — anywhere from 30 seconds to several hours, depending on your settings — a semi-transparent ghost overlay floats onto your current active tab, delivering a personality-matched guilt message on behalf of the tab you abandoned.
Unlike a basic tab history tool, Tab Haunting calculates four separate outputs in real time: the ghost's priority tier, the scheduled haunting time, the personality selection probability, and your running Guilt Score. Each of these is derived from a defined formula explained in detail below.
Where This Extension Gets Used
- Remote workers who open dozens of research tabs during a session and frequently regret closing them mid-read.
- Developers who close Stack Overflow tabs before implementing the fix they found.
- Online shoppers who dismiss product pages only to want them back hours later.
- Students and researchers who open academic links, skim the abstract, and close before reading the conclusion.
- Productivity enthusiasts who want a light-hearted audit of their own browsing habits.
Key User Pain Points and How Tab Haunting Solves Them
⚠ Problem
You close a tab and immediately regret it. Chrome's native Ctrl+Shift+T requires you to remember you had it.
✓ Solution
Tab Haunting pushes the memory to you. The ghost appears unprompted, recovering your attention without any manual action.
⚠ Problem
You spent 12 minutes reading a tutorial, closed it, and can no longer find it in your history because you opened 40 more tabs since.
✓ Solution
The Ghost Graveyard stores every closed tab with its URL, title, and time-on-tab. Searchable and exportable to CSV.
⚠ Problem
Generic "tab manager" tools are boring and add friction. You never actually use them.
✓ Solution
Tab Haunting uses humor and personality to make the experience memorable. The guilt message system means you engage with it rather than ignoring it.
⚠ Problem
You have no visibility into your own tab-closing behavior — how many tabs you close, how quickly, and which domains you abandon most.
✓ Solution
The Guilt Score dashboard quantifies your tab habits with a live score, weekly summary, and most-haunted domain leaderboard.
Ghost Creation Flow — How the Extension Works Step by Step
The diagram below shows the complete lifecycle of a single ghost, from the moment you close a tab to the moment the overlay appears on your screen. Each box maps to a formula or decision point explained in the sections that follow.
Formula 1 — Time on Tab Calculation
Every time Chrome creates a new tab, the extension records the exact timestamp in milliseconds. When the tab closes, it calculates the session duration using the following formula:
Where: closedAt = timestamp when tab was removed [ms] openedAt = timestamp when tab finished loading [ms] Result = duration in whole seconds [s]
Units: Input timestamps are in milliseconds (ms) from Date.now(). The result is expressed in seconds (s) after integer division by 1,000. Math.floor() ensures no partial seconds are counted — a tab open for 59.9 seconds counts as 59, not 60.
⚠ Common Mistake: Ghost Never Appears for Tabs You Open Briefly
If you open a tab and close it in under 10 seconds (the default minTimeOnTab threshold), the extension intentionally skips haunting. This prevents ghost spam from accidental opens or redirects. If a ghost isn't appearing, check Settings → Timing and lower the "Minimum time on tab" value.
Formula 2 — Ghost Priority Tier Classification
Once the time on tab is known, the extension classifies each ghost into one of three priority tiers. The tier controls which message pool is drawn from and how urgently the ghost behaves. Title keywords also influence the tier — tabs with words like "tutorial," "guide," or "how to" are automatically elevated to High priority regardless of time.
Regret keywords: tutorial, how to, best, guide, review, vs
| Priority Tier | Trigger Condition | Time on Tab | Message Pool Used |
|---|---|---|---|
| Petty 😤 | Tab closed in under 5 seconds | 0–4 s | Short, snarky messages ("Opened for 3 seconds. Classic.") |
| Normal 😑 | Standard close, no keyword match | 5–300 s | Standard personality message pool |
| High 🕯️ | 5+ minutes on tab, or title contains regret keyword | > 300 s | Priority messages with stronger guilt language |
💡 Microcopy — Why Keywords Matter
Titles containing "tutorial," "how to," "guide," "best," "review," or " vs " are treated as high-priority regardless of how long you spent on them. This is intentional — a tutorial you glanced at for 20 seconds is exactly the kind of tab you'll regret. The extension flags it before you forget it existed.
Formula 3 — Weighted Random Personality Selection
The extension ships with 10 ghost personalities, each assigned a configurable weight in Settings → Personalities. Rather than pure random selection, it uses weighted random sampling — personalities with higher weights appear proportionally more often.
FOR each personality (id, weight) in order: r = r − weight IF r ≤ 0 → return this personality
Fallback: return first personality in list
Worked Example: Personality Probability with Default Weights
With default settings the total weight sum is 100. The probability of each personality appearing is its weight as a direct percentage:
| Personality | Emoji | Default Weight | Probability | Sample Message |
|---|---|---|---|---|
| Guilt Tripper | 🕯️ | 25 | 25% | "You spent 4m 12s on me and then just... left." |
| Passive Aggressive | 😑 | 20 | 20% | "No no, go ahead. Do whatever you were doing." |
| Scholar | 📚 | 15 | 15% | "The answer was in my third paragraph." |
| Dramatic | 😭 | 10 | 10% | "I HAD THE ANSWER. You will NEVER know." |
| Zen | 🧘 | 10 | 10% | "I was a tab. Now I am free. Are you?" |
| Shopper | 🛍️ | 5 | 5% | "That sale ended at midnight. I hope it was worth it." |
| Nerd | 🤓 | 5 | 5% | "Error 404: Your attention not found." |
| Whiner | 👶 | 5 | 5% | "You didn't even scroll down to the good part." |
| Karen | 😤 | 3 | 3% | "I would like to speak to your bookmarks manager." |
| Melancholic | 🌙 | 2 | 2% | "I remember when you opened me with such hope." |
Weights do not need to sum to 100. The algorithm works with any total — a weight of 5 is always twice as likely as a weight of 2.5, regardless of what all other weights sum to.
Formula 4 — Ghost Schedule Time (Randomised Delay)
To avoid predictability — and to heighten the dramatic effect of the ghost appearing when you've least expected it — the haunting time is randomised within your configured delay window.
| Setting | Default Value | Unit | Valid Range | Effect |
|---|---|---|---|---|
minDelay |
30 | seconds | 0 – 86,400 | Earliest a ghost can appear after tab close |
maxDelay |
1,800 (30 min) | seconds | 0 – 604,800 (7 days) | Latest a ghost can appear after tab close |
maxPerHour |
3 | count / hr | 1 – 20 | Hard cap on ghost appearances per clock-hour |
minTimeOnTab |
10 | seconds | 0 – 600 | Tabs open for less than this are not haunted |
⚠ Common Mistake: Setting maxDelay Too High
If you set maxDelay to 7 days and close hundreds of tabs, you will accumulate a large ghost queue that fires unpredictably days later. Keep maxDelay under 2 hours for a satisfying experience where ghosts feel timely and relevant.
Formula 5 — Quiet Hours Boundary Detection
When an alarm fires during quiet hours, the ghost is not shown — it is rescheduled 30 minutes later automatically. The quiet hours check handles midnight crossover correctly:
IF startMinutes < endMinutes: // same day (e.g. 09:00 – 17:00) return nowMinutes ≥ startMinutes AND nowMinutes < endMinutes ELSE: // crosses midnight (e.g. 23:00 – 07:00) return nowMinutes ≥ startMinutes OR nowMinutes < endMinutes
Example with default settings (23:00 – 07:00): At 02:30 AM, nowMinutes = 150, startMinutes = 1380, endMinutes = 420. Since startMinutes > endMinutes (crosses midnight), the second branch applies: 150 ≥ 1380 is false, but 150 < 420 is true → quiet hours are active, ghost is rescheduled.
Formula 6 — The Guilt Score Calculation
The Guilt Score is a running metric displayed in the extension popup. It reflects both the volume of tabs you close and how ruthlessly you exorcise ghosts (treating exorcisms as a more "cold-blooded" act worth double the score contribution).
Guilt Tier mapping: score 0–25 → "Low Guilt" score 26–50 → "Mild Regret" score 51–75 → "Haunted Soul" score 76–100 → "Tab Murderer 💀"
Guilt Score Tier Visualisation
Closing 200 tabs with 0 exorcisms = score of 10 (Low Guilt). Closing 200 tabs and exorcising 40 ghosts = score of 90 (Tab Murderer).
Worked Example: Calculating Your Guilt Score
Scenario: End of a Heavy Research Session
rawScore = (340 × 0.05) + (18 × 2) = 17 + 36 = 53score = Math.min(100, Math.round(53)) = 53Formula 7 — Dynamic Message Variable Substitution
Ghost messages use live metadata variables that are substituted at render time. This is what makes messages feel eerily personal rather than generic.
Domain override (takes priority over personality pool): reddit.com → fixed message stackoverflow.com → fixed message youtube.com → fixed message amazon.com → fixed message github.com → fixed message
Example substitution: A tab open for 267 seconds on the Scholar personality would produce: "I contained the tutorial you needed 4m 27s ago."
Full End-to-End Worked Example
This walkthrough applies every formula to a single real-world scenario so you can see exactly what the extension calculates from start to finish.
Scenario: A developer closes a Stack Overflow tab
openedAt = 1700000530000 ms). Page is a Stack Overflow answer titled "Best way to debounce in JavaScript."
closedAt = 1700000873000 ms).
Math.floor((1700000873000 − 1700000530000) ÷ 1000) = Math.floor(343000 ÷ 1000) = 343 seconds (5 min 43 sec)
343 > 300 → "high". Also confirmed by title containing "best" — doubly elevated.
stackoverflow.com → fixed message: "The accepted answer was right there. Right. There." (overrides personality pool)
minDelay = 30s, maxDelay = 1800s, Math.random() = 0.44:delay = 30000 + 0.44 × (1800000 − 30000) = 30000 + 778800 = 808800 ms ≈ 13.5 minutes
Common Mistakes When Using Tab Haunting
| Mistake | Why It Happens | How to Fix It |
|---|---|---|
| No ghosts ever appear | All closed tabs are below the minTimeOnTab threshold, or haunting is toggled off |
Open the popup → confirm the toggle is ON. Settings → Timing → reduce "Minimum time on tab" to 5 seconds. |
| Ghosts appear on every tab instantly | minDelay was set to 0 and maxPerHour is high |
Settings → Timing → set minDelay to at least 30 seconds for a natural feel. |
| Ghost appears on banking or medical sites | The domain wasn't added to the whitelist | Settings → Filters → add the domain to the Whitelist field (one domain per line, no www.). |
| Sound plays at 2 AM even with quiet hours set | Quiet hours start/end times not saved after editing | Always click Save Settings at the bottom of the Settings page after making any change. |
| Exorcised a tab by mistake and want it back | Exorcism is permanent for that URL | Open the Graveyard (🪦 from popup), search for the URL, and click Resurrect to reopen it. The exorcism block only prevents future haunting, not manual access. |
| Ghost appears on a PDF or Chrome Web Store page | This should not happen — these pages are blocked by URL check | If this occurs, report it via the Chrome Web Store support page. The extension skips any URL that doesn't begin with http:// or https://. |
| Ghost appears but no sound plays | Browser blocked audio autoplay (common on first run) | Click anywhere on the page once before the ghost is expected to appear. Chrome allows audio after a user gesture on the page. |
Accuracy and Reliability Notes
Time on Tab accuracy: The extension records open time when the tab's status changes to "complete" (page fully loaded), not when the browser tab is first created. This means actual reading time is measured, not the loading time. If a page takes 8 seconds to load and you close it after 15 seconds of reading, timeOnTab will be approximately 15 seconds — accurate to within ±1 second due to Math.floor() rounding.
Schedule accuracy: Ghost delays use chrome.alarms, which guarantees a minimum firing granularity of 1 minute per Chrome's Manifest V3 specification. Ghosts scheduled for less than 60 seconds ahead will still fire, but Chrome may batch them to the next minute boundary. This is a Chrome platform constraint, not a bug.
All processing is local: Every formula runs inside your browser. No browsing data, tab URLs, or guilt scores are ever transmitted to any external server.
Real-World Usage Scenarios
Scenario 1: The Developer Who Closes Too Many Stack Overflow Tabs
A front-end developer opens 6 Stack Overflow tabs while debugging a React issue. After fixing it, they close all 6. The Nerd ghost fires 20 minutes later: "I was a Stack Overflow tab. Still couldn't fix it, could you?" They realise one of the closed tabs contained a different approach they hadn't tried. They click Resurrect in the Graveyard and save 45 minutes of re-searching.
Scenario 2: The Online Shopper Who Dismissed a Sale
A user opens a product page during a 24-hour sale event, spends 4 minutes on it, and closes it after deciding to "think about it." The Shopper ghost fires 2 hours later: "That sale ended at midnight. I hope it was worth it." The user checks the Graveyard, finds the URL, and reopens the product page with 3 hours of the sale remaining.
Scenario 3: The Researcher Who Closed Before Saving
A student closes a JSTOR article after reading the abstract but before bookmarking it. The Scholar ghost fires 45 minutes into their writing session: "The answer was in my third paragraph." They click Visit Again, reopen the article, and cite it in their essay.
Frequently Asked Questions
chrome.storage.local on your device only.
maxDelay to several days, it's possible the ghost fires close to the 7-day limit. To prevent this, reduce maxDelay to 2 hours or less in Settings → Timing.
chrome://extensions will remove all data stored by Tab Haunting, including the ghost queue, graveyard, exorcism log, and settings. Alternatively, to clear just the ghost queue without uninstalling, click "Exorcise All" from the popup — this clears all pending ghosts.
chrome://extensions → Tab Haunting → "Allow in incognito."
