A minimal alternative to Tampermonkey for running custom scripts on any website.
- Run custom JavaScript on any website using
@matchpatterns - Simple dashboard for managing scripts
- Per-script enable/disable toggle
- Familiar userscript metadata format
- Libraries - Create reusable code modules that scripts can import
# Install dependencies
npm install
# Build for production
npm run buildThe built extension will be in the dist/ directory.
- Build the extension (see above)
- Open Chrome and navigate to
chrome://extensions/ - Enable Developer mode (toggle in top-right corner)
- Click Load unpacked
- Select the
dist/folder from this project - The extension icon should appear in your toolbar
Click the extension icon and open the Dashboard. Create a new script with the following format:
// ==BareScript==
// @name My Script
// @match https://example.com/*
// @run-at document-end
// ==/BareScript==
console.log('Hello from userscript!');| Directive | Description | Example |
|---|---|---|
@name |
Script name displayed in dashboard | @name My Script |
@type |
Script type: script (default) or library |
@type library |
@match |
URL pattern where the script runs (can have multiple) | @match https://example.com/* |
@run-at |
When to inject the script | @run-at document-end |
@run-at values:
document-end(default) - Run after page is fully loadeddocument-start- Run as soon asdocument.bodyis available (earliest possible)
*://*/*- All HTTP/HTTPS URLshttps://example.com/*- Specific domainhttps://*.example.com/*- Domain with subdomain wildcard
Libraries let you share code between scripts. Create reusable utilities once and import them in any script.
Click + New Library in the Dashboard:
// ==BareScript==
// @name my-utils
// @type library
// ==/BareScript==
export default {
hide(el) {
if (el) el.style.display = 'none';
},
show(el) {
if (el) el.style.display = '';
}
};Import with ES module syntax:
// ==BareScript==
// @name My Script
// @match https://example.com/*
// ==/BareScript==
// Default import
import utils from 'my-utils';
utils.hide(document.querySelector('.ad'));
// Or named imports
import { hide, show } from 'my-utils';
hide(document.querySelector('.banner'));Libraries are inlined at injection time - no runtime loading or global pollution.
# Run in development mode with hot reload
npm run devSee RELEASING.md for release instructions.
BareScript requires the following Chrome extension permissions:
| Permission | Why It's Needed |
|---|---|
storage |
Save your userscripts and settings locally |
scripting |
Inject userscripts into web pages |
tabs |
Detect page navigation to trigger script injection |
webNavigation |
Detect SPA navigation (pushState/replaceState) to re-run scripts |
host_permissions: *://*/* |
Allow scripts to run on any HTTP/HTTPS URL matching your @match patterns |
Privacy note: BareScript does not collect any data. All scripts and settings are stored locally on your device. See our Privacy Policy for details.
Static site for landing page and privacy policy is in docs/.
# Preview locally
npx serve docs
# Or with specific port
npx serve docs -p 3000- TypeScript
- Preact
- Vite
- Chrome Extension Manifest V3
