Skip to content

selfagency/skeeditor

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

319 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Skeeditor βœοΈπŸ¦‹

The edit button Bluesky never gave you. Until now.

You know the feeling β€” you hit post, look at it for 0.3 seconds, and spot a typo. Or a bad take that needs a slightly less bad take. So you copy your post text, delete the post, and re-post it without the error, only to spot another error. And as you sit there, stewing in frustration, you cry out, "WHY IS THERE NO EDIT BUTTON?!"

Skeeditor is a cross-browser extension that adds a real, working ✏️ Edit button to your posts on bsky.app. Click it, fix your regrets, save. Done. No copy-paste gymnastics, no deleting and reposting, no shame spiral.

It authenticates via OAuth 2.0 + PKCE, fetches the actual record from the Bluesky PDS, and writes it back β€” preserving your links, mentions, hashtags, embeds, and timestamps like nothing ever happened. 🀫

πŸ“– Full documentation β†’ | πŸ¦‹ Bluesky Account: @skeeditor.link


✨ Features

  • πŸ–ŠοΈ In-place editing β€” an edit button appears right on bsky.app next to your posts, where it always should have been
  • πŸ‘₯ Multi-account β€” sign in with multiple Bluesky accounts and switch between them from the toolbar popup
  • 🏷️ Edited label β€” posts you edit are marked with an "edited" label via the Skeeditor labeler service (opt-in; requires subscribing to @skeeditor.link)
  • ⏱️ Edit time limit β€” optionally configure a 0.5–5 minute window after posting during which the Edit button is active
  • πŸ”’ Secure by design β€” OAuth 2.0 + PKCE + DPoP; tokens stored only in extension storage, with access-token forwarding only to the Skeeditor labeler emit endpoint when labeler integration is active
  • πŸ’… Rich text preserved β€” links, @mentions, and #hashtags are re-detected and byte-offset facets recalculated on every save
  • πŸ›‘οΈ Conflict-safe β€” CID-based optimistic locking detects concurrent edits and prompts before overwriting
  • 🌍 Cross-browser β€” Chrome 120+, Firefox 125+ (Safari coming soon)

Browser support

Browser Minimum version
Chrome 120+
Firefox 125+
Safari πŸ”œ Coming soon

Development

Prerequisites

  • Node.js 20+
  • pnpm 9+
  • Chrome or Firefox for manual testing

Install

git clone https://github.com/selfagency/skeeditor.git
cd skeeditor
pnpm install

Build

task build:chrome   # β†’ dist/chrome/
task build:firefox  # β†’ dist/firefox/
task build:safari   # β†’ dist/safari/
task build          # alias for build:chrome

Watch mode:

task build:watch:chrome
task build:watch:firefox

Load in your browser

Chrome: chrome://extensions β†’ Developer mode β†’ Load unpacked β†’ dist/chrome/

Firefox: about:debugging#/runtime/this-firefox β†’ Load Temporary Add-on β†’ dist/firefox/manifest.json

Safari: Build, then open the generated Xcode project under dist/safari/ and run it. See Cross-Browser Platform docs for full instructions.

Debugging in VS Code

  1. Launch mode (simplest):

    • Hit F5 with "Debug: Full Extension (build + launch + content)" selected.
    • VS Code will build the extension, open a fresh Chrome instance with the extension pre-loaded, and attach the debugger to the content script context on bsky.app.
    • Breakpoints in TypeScript source will be hit automatically.
  2. Attach mode (keeps your normal Chrome profile):

    • Run the task "Open Chrome (remote debug on 9222)" (or launch Chrome manually with --remote-debugging-port=9222).
    • Select "Debug: Content Script on bsky.app (attach)" and hit F5.
    • VS Code will attach to the running Chrome instance and breakpoints will work.
  3. Debugging the service worker or popup:

    • Use "Debug: Service Worker (attach)" or "Debug: Popup (attach)" after launching Chrome with remote debugging enabled.

All configs support source maps and skip third-party scripts (hls.js, etc.) to avoid noisy warnings.

See .vscode/launch.json and .vscode/tasks.json for full configuration details.

Test

task test               # unit + integration
task test:unit          # Vitest (jsdom + browser API mocks)
task test:integration   # Vitest + MSW (HTTP mocking)
task test:e2e           # Playwright (Chrome + Firefox, requires built dist/)
task test:watch         # watch mode

Code quality

task lint          # oxlint
task format        # oxfmt (write)
task format:check  # oxfmt (check only)
task typecheck     # tsc --noEmit

Lexicons

task lex:install   # download AT Protocol lexicon JSON files
task lex:build     # compile lexicons β†’ TypeScript types in src/lexicons/
task lex:sync      # both steps in order

Architecture

The extension has three contexts that communicate via typed runtime messages:

  • Content script (src/entrypoints/content.ts, src/content/) β€” runs on bsky.app; detects your posts, injects the Edit badge, shows the edit modal
  • Background worker (src/entrypoints/background.ts, src/background/) β€” manages OAuth sessions (keyed by DID for multi-account), makes all XRPC calls to the Bluesky PDS, checks labeler subscription after sign-in
  • Popup (src/entrypoints/popup/) β€” toolbar button UI for sign-in, sign-out, account switching, labeler consent, and settings navigation
  • Options page (src/entrypoints/options/) β€” full-tab settings page for configuring the edit time limit

Tokens never touch the content script. All authenticated network requests go through the background worker.

See the Architecture and Message Protocol docs for details.


Documentation

Section Description
User Guide Installation, usage, privacy & security, FAQ
Architecture Extension context model, data flow
Getting Started Dev environment setup
Build System WXT config, per-browser builds, lexicon pipeline
Testing Unit, integration, E2E test layers
Contributing Beans workflow, branch naming, TDD, PR requirements
Authentication OAuth PKCE+DPoP flow, multi-account sessions, token refresh
XRPC Client getRecord, putRecordWithSwap, conflict handling
Facets & Rich Text Link/mention/hashtag detection, byte offsets
Cross-Browser Platform API differences, manifest structure, Safari setup
Labeler Services "Edited" label, Cloudflare Worker, consent flow

Contributing

All work is tracked with Beans. Before writing code, find or create a bean and create the issue branch. All changes require tests (TDD: red β†’ green β†’ refactor). See Contributing for the full workflow.

Commits follow Conventional Commits. PRs require passing CI (lint, typecheck, unit + integration tests) and must reference a bean ID.


License

MIT Β© selfagency

About

βœοΈπŸ¦‹ Cross-browser Bluesky post editor extension

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors