Manage Brave as a dotfile: keyboard shortcuts, general settings (non-MAC keys), and force-installed PWAs from one TOML.
Project description
dotbrave
Manage Brave as a dotfile. Keep keyboard shortcuts, UI tweaks, and force-installed web apps in a single TOML, apply with one command, sync across machines — no Brave Sync required.
Status: alpha. Works on Linux, macOS, and Windows against Brave stable, beta, and nightly. Extracted from the multi-browser dotbrowser project as a focused, Brave-only tool with a flatter CLI (
dotbrave applyinstead ofdotbrowser brave apply). Python 3.11+, standard library only.
Quick start
The repo ships an opinionated example config: vertical tabs collapsed to
icons, decluttered new tab page, stripped-down toolbar, vim-style hjkl
shortcuts. examples/all.toml bundles all three
namespaces; shortcuts.toml,
settings.toml, and
pwa.toml are single-namespace variants.
Start from what you already have — export your current customizations as a ready-to-edit config:
dotbrave export -o brave.toml
Or apply the example directly from GitHub — no clone, no install. Fetched payloads are echoed with byte size + SHA-256 so you can see exactly what's being applied:
uvx dotbrave apply --dry-run \
https://raw.githubusercontent.com/xom11/dotbrave/main/examples/all.toml
# Apply. If Brave is already running, dotbrave uses live apply;
# first-time live setup closes Brave normally and relaunches it once.
uvx dotbrave apply \
https://raw.githubusercontent.com/xom11/dotbrave/main/examples/all.toml
Prefer to inspect / customise locally first? Download then apply:
curl -fsSL -o brave.toml https://raw.githubusercontent.com/xom11/dotbrave/main/examples/all.toml
# edit brave.toml ...
uvx dotbrave apply brave.toml
Anything you later remove from your config reverts to Brave's default on
the next apply — no orphan entries.
Install
pipx install dotbrave # global, isolated venv
uvx dotbrave <args> # run on demand, no install step
pip install dotbrave # into the active environment
Run from a branch: uvx --from git+https://github.com/xom11/dotbrave dotbrave <args>.
Local dev: pip install -e ".[test]". Nix users: the repo ships a flake
(nix run github:xom11/dotbrave).
Build your own config
A single TOML carries [shortcuts], [settings] and [pwa]. One apply
writes all three in a single backup + write cycle.
# brave.toml
[shortcuts]
toggle_sidebar = ["Control+Shift+KeyE"]
toggle_ai_chat = ["Alt+KeyA"]
# vim-style hjkl
back = ["Alt+KeyH"]
forward = ["Alt+KeyL"]
select_previous_tab = ["Alt+KeyJ"]
select_next_tab = ["Alt+KeyK"]
# Same chord on all OSes — Meta+ = Cmd on macOS, Super on Linux/Windows (auto-translated)
new_tab = ["Control+KeyT", "Meta+KeyT"]
close_tab = ["Control+KeyW", "Meta+KeyW"]
[settings]
"brave.tabs.vertical_tabs_enabled" = true
"brave.tabs.vertical_tabs_collapsed" = true
"bookmark_bar.show_on_all_tabs" = false
[pwa]
# Force-installed Progressive Web Apps. Brave fetches each manifest,
# downloads icons, registers the app in chrome://apps, and emits a
# launcher (.desktop on Linux, app shim on macOS, Start Menu shortcut on
# Windows). Removing a URL + re-applying = uninstall.
urls = [
"https://squoosh.app/",
"https://app.element.io/",
]
dotbrave apply brave.toml --dry-run # preview the diff
dotbrave apply brave.toml # live apply if Brave is running
- Shortcut keys: Chromium KeyEvent codes
joined by
+—Control+Shift+KeyP,Alt+Digit1,F11.Meta+is auto-translated toCommand+on macOS, so one config works everywhere. - Setting keys: dotted paths into the profile
PreferencesJSON. MAC-protected keys (homepage, default search engine,pinned_tabs, …) are refused with a clear error — Brave would silently reset them on launch.exportlists protected keys as comments so you know what to set in the Brave UI instead. - PWA URLs: every entry installs with
default_launch_container = "window"andcreate_desktop_shortcut = true.[pwa]is the only namespace that needs elevated privileges: it writes a managed-policy file (sudo on Linux/macOS) or the Windows Registry (Administrator). No[pwa]diff → no elevation prompt. - Empty header (e.g.
[settings]with no entries) wipes everything dotbrave previously managed in that namespace. Missing header = skip the namespace entirely.
CLI reference
Shape: dotbrave [profile-flags] <action> [action-flags] [args].
Profile flags may be given before or after the action name — the
after-action form wins when both are present. export is the inverse of
apply: produce a round-trippable TOML from the current profile state.
Profile flags
| Flag | Default | What it does |
|---|---|---|
-r, --profile-root PATH |
auto-detected | Brave's root profile directory. |
-p, --profile NAME |
Default |
Profile directory name inside the root — e.g. "Profile 1". |
--channel {stable,beta,nightly} |
stable |
Release channel; auto-detects the Brave-Browser-Beta / -Nightly profile path and targets the matching process. |
| Channel | Linux | macOS | Windows |
|---|---|---|---|
| stable | ~/.config/BraveSoftware/Brave-Browser |
~/Library/Application Support/BraveSoftware/Brave-Browser |
%LOCALAPPDATA%\BraveSoftware\Brave-Browser\User Data |
| beta / nightly | same, with -Beta / -Nightly suffix |
same, with suffix | same, with suffix |
Snap and Flatpak installs (stable only) are probed automatically on Linux.
dotbrave apply -r /custom/path -p "Profile 1" brave.toml
dotbrave apply --channel beta brave.toml
Actions
There are exactly two:
| Action | What it does |
|---|---|
export [-o FILE] [-a] [--snapshot [--clear]] |
Read your customizations as round-trippable TOML: [shortcuts] (bindings that differ from Brave defaults; -a/--all-shortcuts lists every binding with its command name), [settings] (well-known user-facing keys, keys dotbrave manages, and keys changed since the last --snapshot baseline; MAC-protected keys appear as comments), and [pwa]. --snapshot captures the baseline instead of exporting; --snapshot --clear deletes it. |
apply [-n] CONFIG | --undo |
Write [shortcuts] + [settings] + [pwa] from a file or HTTPS URL. -n/--dry-run previews the diff. URL fetches print size + SHA-256; pin with --expect-sha256 HEX; plain HTTP refused unless --allow-http. --undo restores the most recent apply-time Preferences backup instead. |
To capture settings you only know how to change in the Brave UI: run
dotbrave export --snapshot, change them in Brave, wait a few seconds
(Brave flushes Preferences on a delay), then dotbrave export — the
changed keys appear under [settings].
Both actions have detailed --help with safety notes and examples.
How it works
When Brave is closed, dotbrave patches the profile Preferences JSON
directly. Each offline apply takes one timestamped backup, writes
atomically (temp file + rename), and verifies the result by reloading.
When Brave is running, plain apply uses Brave's privileged UI APIs over
a private loopback DevTools endpoint: ordinary settings go through
chrome.settingsPrivate, New Tab settings through live New Tab UI
actions, and shortcuts through the Settings CommandsService. Supported
changes take effect without restarting. A Brave not yet carrying the
endpoint closes normally and relaunches once; a setting without a live
route falls back to the same normal-close + verified offline write. A
config whose only diff is [pwa] skips the endpoint entirely — the
managed policy is written while Brave keeps running, and Brave loads it
at its next launch. The endpoint binds to 127.0.0.1 only, and there is
no force-kill switch.
[shortcuts] and [settings] track managed entries in sidecar files
(Preferences.dotbrave.{shortcuts,settings}.json), so removing a key from
your config restores Brave's default on the next apply. [pwa] state
lives in Chromium's managed-policy storage (Linux JSON file, macOS plist,
Windows Registry) — the policy is the state. export --snapshot stores
its baseline in a third sidecar
(Preferences.dotbrave.settings-snapshot.json); apply --undo leaves it
alone.
On macOS, /Library/Managed Preferences/ is a system-managed cache that
gets reclaimed at boot on non-MDM machines, which would otherwise
uninstall your PWAs. To keep them installed, apply installs a small
root-owned self-healing helper:
/Library/LaunchDaemons/org.dotbrave.com.brave.Browser.pwa.plist— watches the managed-preferences directory and rewrites the policy if macOS removes it./Library/Application Support/dotbrave/com.brave.Browser.managed.plistandcom.brave.Browser.heal.sh— the policy source of truth and the rewrite script.
Applying an empty [pwa] table (urls = []) removes all of the above.
Brave install methods
| Install | Auto-detected | [pwa] works |
Notes |
|---|---|---|---|
.deb / .rpm / Arch / NixOS |
yes | yes | Reference install; full support. |
| Snap | yes | refused with clear error — sandbox doesn't read /etc/brave/policies/managed/ |
Use .deb for [pwa]. |
| Flatpak | yes | refused with clear error — same sandbox limitation | Relaunch goes back through flatpak run. |
macOS .dmg |
yes | yes | Includes cfprefsd cache invalidation + self-healing daemon. |
| Windows installer | yes | yes — writes HKLM\Software\Policies\BraveSoftware\Brave; requires Administrator |
Coming from dotbrowser?
dotbrave is a standalone extraction of dotbrowser's Brave support with
its own state names: sidecars are Preferences.dotbrave.*.json (was
Preferences.dotbrowser.*.json) and the macOS daemon is
org.dotbrave.<bundle>.pwa (was org.dotbrowser.<bundle>.pwa). Your
Brave profile itself is untouched by the switch, but entries previously
managed by dotbrowser are not tracked by dotbrave until you apply your
config once with dotbrave. On macOS, remove dotbrowser's daemon
(dotbrowser brave apply with an empty [pwa] table, or the manual
launchctl bootout steps in its README) before letting dotbrave manage
[pwa], so two daemons don't fight over the same plist.
Caveats
- Brave Sync can overwrite
[settings]entries on its next pulse if they fall in a synced category. UI-layout keys likebrave.tabs.vertical_tabs_*are local-only and immune.applyprints a non-fatal warning whensync.has_setup_completed=true. - A handful of settings (
homepage, default search engine,pinned_tabs, …) are integrity-protected and refused rather than silently reset by Brave on next launch. Set those in the Brave UI. [pwa]is force-install (Chromium's enterpriseWebAppInstallForceList). Apps appear inchrome://appswith an "Installed by your administrator" label and hidden right-click Remove — uninstall by deleting the URL from[pwa]and re-applying. That is the right semantics for dotfile-style management (the TOML is the source of truth), but worth knowing if you also install PWAs by hand.
License
MIT
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file dotbrave-0.2.1.tar.gz.
File metadata
- Download URL: dotbrave-0.2.1.tar.gz
- Upload date:
- Size: 1.4 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
191855e5427370971df39658c18fc9503f0b8fc1831e27c34a50e4d8b913f66d
|
|
| MD5 |
29d5f4960a7b0c3fe7d8f3193653901f
|
|
| BLAKE2b-256 |
f5abb3f41dac8511a0f975f6326cab5e064602b446054c41e31051879c1000c4
|
File details
Details for the file dotbrave-0.2.1-py3-none-any.whl.
File metadata
- Download URL: dotbrave-0.2.1-py3-none-any.whl
- Upload date:
- Size: 61.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bfc561242ef5b2ef95652a968ec70823153b4cb22f69b6de690f94db0390e5da
|
|
| MD5 |
de32d6ae4af0fe3f3cdb7bbc550949b3
|
|
| BLAKE2b-256 |
f90a6d1e4f625ca805479f94477f066f60c6adbb672c4719a53609f888b87193
|