Updates your Slack status to reflect the task you're currently tracking time for, and updates it again for end of day. Optionally pauses your Slack notifications while you're in Focus Mode.
Super Productivity installs plugins from a ZIP file — there's no load-from-folder option, and no way to install one via its REST API, so this is the only route.
-
Get
slack-status-sync.zip, either by downloading it from the latest release or by building it from the repo root:npm run package
The files must be at the top level of the archive, not inside a folder — Super Productivity looks up
manifest.jsonby exact name and won't find it under a directory. That's whatnpm run package(and the release workflow) guarantees; if you build the zip by hand, it'szip -j slack-status-sync.zip manifest.json plugin.js index.html icon.svg. -
In Super Productivity: Settings → Plugins → Install Plugin, choose the zip, and accept the permission prompt.
-
A new "Slack Status Sync" entry appears in the left-hand menu.
To pick up later changes, rebuild the zip, install it again, then toggle the plugin off and on. There is no hot reload.
Slack retired the old "legacy token generator," so you create a small internal Slack app for yourself:
- Go to https://api.slack.com/apps → Create New App → From scratch.
- Name it anything (e.g. "My Status Sync"), pick your workspace.
- Left sidebar → OAuth & Permissions.
- Under Scopes → User Token Scopes, add
users.profile:write. If you want the notification-pausing feature (see below), also adddnd:write. - Scroll up, click Install to Workspace, approve it.
- Copy the User OAuth Token (starts with
xoxp-) — not the Bot token.
- Click Slack Status Sync in the left menu.
- Paste the
xoxp-...token into the Slack token field and click Save settings. The token is stored locally on this device only — it is never synced, exported, or backed up.- On save the plugin calls Slack's
auth.testto confirm the token works, and shows which user and workspace it resolved to. A token Slack positively rejects (invalid, revoked, expired, or a Bot token pasted by mistake) is reported and not saved. If Slack simply can't be reached, the token is saved and the panel says it couldn't be verified. - Verify token re-runs that check at any time.
- On save the plugin calls Slack's
- Adjust the status text/emoji for "while tracking a task" and "end of day"
as you like (
{title}and{project}are available as placeholders in the tracking text). - Click Send test status to confirm it's wired up correctly — you should see your Slack status change within a couple of seconds.
Does the same thing as clicking your profile photo in Slack → "Pause notifications" while you're in Super Productivity's Focus Mode, and "Resume notifications" when focus mode ends. This is what actually changes your availability to teammates (a moon icon appears next to your name, and desktop/mobile pushes stop) — it's the real, API-accessible feature behind what most people mean by "focus mode" in Slack.
One thing this can't do: Slack also has a separate, purely client-side "Focus mode" that just hides sidebar clutter in the Slack app itself. That one has no public API at all, so no plugin (this one included) can toggle it remotely — only "Pause/Resume notifications" is reachable via the API, which is what this plugin uses.
Why this needs action-type strings: Super Productivity's plugin API
doesn't have a dedicated "focus mode started/ended" hook. This plugin
instead listens to the generic action hook (every NgRx action the app
dispatches) and watches for Focus Mode's action type strings.
The defaults are taken from Super Productivity's actual focus-mode actions (verified against 18.19.0) rather than guessed:
| Action types | |
|---|---|
| Start | [FocusMode] Start Session |
| End | [FocusMode] Complete Session, [FocusMode] Cancel Session, [FocusMode] End Flowtime Session |
A session that runs to completion dispatches Complete Session; one you
abort dispatches Cancel Session. Show Overlay / Hide Overlay are
deliberately not used — they're pure UI events that also fire when you
merely open or close the focus screen, so triggering DND from them would
pause your notifications just for looking at the focus tab.
If your installed version differs, use the built-in diagnostics panel (no DevTools needed) rather than editing the fields blind:
- Open the plugin settings and scroll to Diagnostics under "Pause Notifications (Focus Mode)".
- Start a focus session in Super Productivity, then end/cancel it.
- Back in the plugin settings, click Refresh.
- If "Actions seen" stays at
0, the plugin isn't receiving any app events at all — that's a different problem than wrong action names (try reloading the plugin, or removing and re-adding it). - If the counter goes up but the list below stays empty, Focus Mode's
actions in your installed version don't contain the word "focus" in
their type string. Fall back to DevTools (
F12/Ctrl+Shift+I→ Console) and check "Log Focus Mode actions to the console" — though at that point you may need to widen what you search the console for, since the type names apparently don't match the "focus" filter this panel uses. - If entries do show up, click "Use as start" / "Use as end"
next to the right ones, then Save settings. Entries are grouped by
type with an occurrence count, so
[FocusMode] Timer Tick— which fires once a second during a session — doesn't bury the start/end actions you're looking for. - Reset to defaults puts the table above back if you want to start over.
- If "Actions seen" stays at
- Use "Simulate focus start" / "Simulate focus end" to test the Slack side (pause notifications + status) independently of the detection itself, then trigger a real focus session to confirm everything's connected end to end.
Notes on the notification-pausing behavior itself:
- Slack's
dnd.setSnoozeAPI (what powers "Pause notifications") always requires a fixed duration in minutes.[FocusMode] Start Sessioncarries the real session length, so the plugin uses that. The fallback pause length setting is only used when a session reports no duration (Flowtime mode, or the "Simulate focus start" button). Ending focus mode callsdnd.endSnooze("Resume notifications") immediately either way, so the snooze length is a ceiling rather than a commitment. - The custom focus status (if enabled) is separate — pausing notifications already shows a moon icon on your Slack profile automatically, on its own, without any status text change.
- While a session is running the focus status takes precedence over task tracking, so starting or switching tasks won't overwrite it. When the session ends, your tracking status is restored.
PluginAPI.setSecret / getSecret / persistDataSynced / loadSyncedData
aren't reliably reachable from inside the settings iframe (index.html) in
current Super Productivity builds, even though they're part of the
documented API surface. So all config/secret handling lives in plugin.js
(host-side, always running), which exposes a plain object on
window.slackStatusBridge. The iframe reaches it via
window.parent.slackStatusBridge — this works because iframe plugins render
with allow-same-origin. The iframe still uses PluginAPI.showSnack
directly for simple one-way notifications, which does work fine from inside
the iframe.
If a future SP release fixes iframe access to those APIs, the bridge can be
removed and index.html can call PluginAPI directly again — the UI code
is already written against a small getBridge()-shaped interface to make
that swap easy. The bridge deliberately never hands the token itself to the
iframe — only whether one is set, and who it belongs to.
Slack calls go through PluginAPI.request() where available, which is the
sanctioned HTTP path: it's gated by the "http" permission plus
"allowedHosts": ["slack.com"] in the manifest (both fail-closed), and it
applies Super Productivity's own URL/private-network protections. Older
builds without request() fall back to fetch, which is why
minSupVersion stays at 14.0.0.
- Start/switch a task → Slack status becomes your tracking template (e.g. "Working on: Fix login bug"), optionally auto-clearing after N hours so a crash can't leave it stuck.
- Stop tracking (no active task) → status clears, if "Clear Slack status when I stop tracking" is checked.
- Focus session starts → notifications pause, focus status applied, and task changes stop touching your status until the session ends.
- Focus session ends → notifications resume and the tracking status is restored.
- Click "Finish day now" in the plugin's settings → status becomes your end-of-day text/emoji, and optionally auto-clears itself after N hours (Slack handles the expiry, not the plugin — so it works even if Super Productivity isn't running). This outranks focus mode: a session ending afterwards won't overwrite it. Super Productivity's own "Finish Day" button doesn't currently notify plugins when pressed (a gap in Super Productivity itself, not this plugin), so use the button in the settings panel instead — see Notes / limitations.
- Super Productivity's real "Finish Day" button doesn't dispatch the event plugins need to react to it (confirmed against the 18.19.0 app bundle: the action that would trigger it is never actually fired), so end-of-day status updates use a "Finish day now" button in the plugin's own settings panel instead. Worth re-checking after a Super Productivity upgrade in case this gets fixed upstream.
- Uses Slack's Web API directly from the app, so it only works while Super Productivity itself is running (there's no background server component).
- Status text is capped at 100 characters (Slack's limit) — longer task titles are truncated with an ellipsis.
users.profile.setis a Tier 3 method (~50 requests/minute). Task changes are debounced by 2 seconds so a burst of rapid switches costs one call, and rate-limited or transient 5xx responses are retried with a backoff.- Slack writes are serialized, so a focus transition and a task change landing at the same moment can't apply out of order.
- One Slack workspace/token per install of the plugin.
- If you use Super Productivity on multiple devices, you'll need to paste the token again on each device (secrets are intentionally per-device, not synced).
npm install # ESLint + Prettier (needs Node >= 18.18)
npm run lint # ESLint over *.js
npm run lint:fix
npm run format # Prettier over js/html/json/md/yaml
npm run format:check
npm run package # build slack-status-sync.zipESLint only sees plugin.js — it can't parse the inline <script> in
index.html — so logic belongs in plugin.js, where it gets checked.
Prettier does format the whole file, inline script included.
The repo ships a pre-commit config that runs Prettier and ESLint (plus JSON/YAML sanity checks) on the files you're committing:
pre-commit install # once, to enable the git hook
pre-commit run --all-files # run everything on demandBoth hooks auto-fix and pin their own Node, so they work even if your shell's active Node is too old for ESLint 9. When a hook rewrites a file the commit is aborted — re-stage the fixes and commit again.
.github/workflows/ci.yml runs ESLint, prettier --check and a manifest.json
sanity check on every push and pull request.
On pull requests it additionally builds the ZIP as a test build and posts a download link as a single comment that's edited in place on each push, so you can install the exact build under review. The shipped ZIP is only ever built by the release workflow — the PR build is a packaging check, not a deliverable.
Bump version in manifest.json, commit, then tag it:
git tag v1.2.1 && git push origin v1.2.1.github/workflows/release.yml verifies the tag matches manifest.json, lints,
builds the ZIP, asserts its entries sit at the archive root, and publishes it as
a GitHub release asset. A tag that disagrees with the manifest fails instead of
publishing.
Mostly correctness fixes; two of them change behavior you may have worked around already:
- Focus sessions that finished normally never resumed your notifications.
The shipped end-action list was missing
[FocusMode] Complete Sessionand contained two action names that never existed in any SP version ([FocusMode] Session Done,[FocusMode] Unload). Existing installs are migrated automatically — but only if you never edited those fields, so hand-corrected values are preserved. [FocusMode] Show Overlayno longer starts a focus session, so simply opening the focus screen doesn't pause your notifications.- Task changes no longer overwrite the focus status mid-session, and the tracking status is restored when a session ends.
- Pause length now comes from the real session duration.
- End-of-day status is no longer clobbered by a session ending after it.
- Token is verified against Slack on save; Bot tokens are caught explicitly.
- Status text is truncated to Slack's 100-character limit.
- Task-change debouncing, rate-limit retries, and serialized writes.
- A status set with an expiry is re-sent once Slack has cleared it, instead of being suppressed forever as "already applied".
- Derived UI fields (
hasToken,inFocusMode) no longer leak into synced config data. - Manifest declares the
httppermission andslack.cominallowedHosts, so its network access is visible in Super Productivity's plugin UI.
The plugin holds a Slack user token, so what it can and can't reach is documented in SECURITY.md, along with how to report a vulnerability privately.
MIT © Diane Pryseski