- Babashka (bb)
- Node.js (for npm dependencies)
npm installStart the development environment:
If you are using VS Code:
- Run the default build task (Cmd/Ctrl+Shift+B) - starts Squint watch, unit test watcher, and Scittle Dev REPL
- Start Squint nREPL:
bb squint-nrepl(or run the "Squint nREPL" VS Code task) - Connect your editor to the Squint nREPL (port 1337)
- Calva: "Connect to a running REPL" -> select "squint"
VS Code tasks (defined in .vscode/tasks.json):
Start Dev Environment(default build) - runs Squint watch, test:watch, and Scittle Dev REPL in parallelSquint nREPL- starts the Squint nREPL server on port 1337Scittle Dev REPL- starts the browser-nrepl relay (ports 31337/31338)
Manual alternative (separate terminals):
bb watch # Terminal 1: Auto-compile on save
bb test:watch # Terminal 2: Unit test watcher
bb squint-nrepl # Terminal 3: Squint nREPLThe Squint REPL lets you evaluate code in a Node.js environment, useful for testing pure functions that do not need the browser execution environment. See the epupp-squint skill for details.
For experimenting with Scittle code (the runtime used in browser pages), the project includes a Joyride-based setup for connecting a Scittle repl, named scittle-dev-repl:
-
Automatic setup: The Joyride workspace activation script (
.joyride/scripts/workspace_activate.cljs) automatically:- Starts the browser-nrepl relay if not already running
- Opens a Calva Flare webview with Scittle + nREPL client
- Prompts to connect Calva
-
Manual setup: Run the Joyride script directly:
Joyride: Run Workspace Script->scittle_repl.cljs- Or connect Calva using "Scittle Dev REPL" sequence (port 31337)
Ports:
- nREPL: 31337
- WebSocket: 31338
The Scittle REPL runs in a VS Code webview, providing a browser-like environment for testing Scittle code before deploying to actual web pages.
For architecture and behavior drift sweeps, use the Documentation Ground Truth Sweep Checklist.
Run unit tests once:
bb testCompile only (no tests), pass Squint args directly:
bb squint-compile src/log.cljs
bb squint-compile --paths src test --output-dir build/testStart unit test watchers (Squint + Vitest in parallel):
bb test:watchUnit tests use Vitest and live in test/*.cljs. Squint compiles them to build/test/*.mjs which Vitest watches and runs.
Default (AI Agents and Automated Testing):
bb test:e2e # All E2E tests in Docker (headless), includes REPL integrationFor humans (headed tests with visible browser):
bb test:e2e:headed # Run tests (builds extension first)
bb test:e2e:ui:headed # Interactive Playwright UIFilter tests: Pass Playwright options to any e2e task:
bb test:e2e --grep "popup" # Run only popup tests
bb test:e2e:headed --debug # Debug mode with inspector (headed)See testing.md for: complete testing strategy, fixtures, utilities, and troubleshooting.
GitHub Actions runs on every push and PR:
┌───────────────┐ ┌─────────────┐
│ build-release │ │ build-test │ <- Parallel builds
└───────────────┘ └──────┬──────┘
│
┌───────┴───────┐
▼ ▼
┌────────────┐ ┌────────────┐
│ unit-tests │ │ e2e-tests │ <- Parallel tests
└────────────┘ └────────────┘
│ │
└───────┬───────┘
▼
┌─────────┐
│ release │ <- On version tags only
└─────────┘
See .github/workflows/build.yml for details.
Build for all browsers (production):
bb buildBuild for development (bumps dev version for testing):
bb build:devBuild for e2e tests (dev config without version bump):
bb build:testThe build:test task uses dev config (needed for test-only message handlers like e2e/find-tab-id) but doesn't bump the manifest version. This prevents version drift when running e2e tests repeatedly.
Build for specific browser:
bb build:chrome
bb build:firefox
bb build:safariDev versions use 4-part format (0.0.7.0, 0.0.7.1). The 4th number is the build number, bumped by bb build:dev.
Chrome:
- Unpack
epupp-chrome.zip(will unpack achromefolder) - Go to
chrome://extensions - Enable "Developer mode"
- Click "Load unpacked"
- Select the
chromefolder
Firefox:
- Go to
about:debugging#/runtime/this-firefox - Click "Load Temporary Add-on"
- Select any file in
epupp-firefox.zipfile
Safari:
- Safari → Settings → Developer → Click "Add Temporary Extension"
- Select the
epupp-safari.zipfile - Ensure the extension is enabled in Safari → Settings → Extensions
Use the automated publish workflow:
bb publishThis will:
- Verify git is clean and on master branch
- Check CHANGELOG.md has unreleased content
- Strip build number from version (e.g.,
0.0.7.8->0.0.7) - Update CHANGELOG with release date
- Commit, tag
vN.N.N, and push - Bump to next dev version (e.g.,
0.0.8.0)
GitHub Actions then handles the rest automatically:
- Builds all three browser versions (Chrome, Firefox, Safari)
- Runs unit and E2E tests
- Creates a GitHub Release with downloadable artifacts
- Publishes to Chrome Web Store (auto-publish)
- Submits to Firefox AMO (with source code for review)
Safari remains manual (submit via Xcode to App Store Connect).
Chrome Web Store: The publish_chrome CI job uploads the zip and auto-publishes. Updates typically go live within minutes. Uses chrome-webstore-upload-cli with a GCP service account.
Firefox AMO: The publish_firefox CI job submits the xpi along with a git archive source bundle for reviewer reproducibility. AMO review is asynchronous - the CI job submits and exits without waiting. Uses web-ext sign with JWT API credentials.
Safari: Manual. Submit via Xcode to App Store Connect.
Store publishing requires credentials stored in GitHub environment secrets:
chrome-storeenvironment:CWS_SERVICE_ACCOUNT_KEY(GCP service account JSON key),CHROME_EXTENSION_ID(variable)firefox-storeenvironment:AMO_API_KEY(JWT issuer),AMO_API_SECRET(JWT secret)
To validate credentials without publishing, run the "Check Store Credentials" workflow manually from the Actions tab.
If a publish job fails after a successful release:
- The GitHub Release and artifacts are unaffected
- Re-run only the failed job from the Actions UI (no rebuild needed)
- Check the job logs for credential or API errors
- For persistent issues, publish manually using the store dashboards as a fallback
- testing.md - Test strategy and utilities
- architecture.md - Overview and navigation to the detailed architecture docs
- userscripts-architecture.md - Userscript design decisions
- ui.md - Script editor UX and ID behavior