Canonical context for Slash, EJ's personal AI-native browser. Read this
first when starting a session on this project. Pair with DESIGN.md (visual
system), BROWSER-UI.md (feature roadmap), and docs/research/ (the deep
research EJ supplied).
A personal, local, open-source, modifiable, low-usage web browser with a
built-in AI panel. Built as a custom Electron shell over Chromium (route
"A": own the UI, rent the engine). NOT a Firefox/Chromium fork. The folder is
Desktop\slash (codename was "Loom"); the product is named Slash.
- Name: Slash. Wordmark
/slash(leading yellow slash) in Space Grotesk. The/is the mark AND a real feature (the slash-command key). On the hero it is a blinking yellow cursor. - Color: soft yellow
#f1cb53, themeable at runtime (settings), dark text on the accent. Default lives inlib/settings.js. - Look: near-black chrome (
#1c1c1f/ titlebar#141416), system font for UI (Segoe UI), conventional Chrome/GX layout. No left rail. - App icon: yellow rounded tile + dark
/(src/icon.png, regenerated frommockups/icon.html). - Rejected directions (do not revisit): Catppuccin dark, warm-clay light, warm-neutral "Claude" light, GX-red with a left sidebar. EJ has strong, specific taste; match real references, do not generate looks from adjectives.
cd Desktop\slash
npm start # uses launch.js to strip ELECTRON_RUN_AS_NODE (see below)
Critical gotcha: ELECTRON_RUN_AS_NODE=1 is set globally on EJ's PC, which
makes the Electron binary run as plain Node (app is undefined,
electron --version prints the Node version). launch.js strips it. Always
launch via npm start, never electron . directly.
NO AI image generation for UI (EJ rejected it). Mockups are HTML/CSS in
mockups/, rendered to PNG with headless Edge, then opened for EJ:
& msedge --headless=new --disable-gpu --hide-scrollbars --window-size=1280,840 \
--screenshot="out.png" "file:///.../mockups/mockup.html"
mockups/mockup.html is the approved full-browser reference. The real app
chrome matches it.
Electron BaseWindow holding stacked WebContentsViews (main.js):
- chromeView (
index.html/chrome.js/styles.css): tab strip + toolbar + bookmarks bar. Trusted,preload.js->window.slash. - heroView (
hero.*): the/slashspeed-dial start page. Shown for any tab that has not navigated. Trusted,hero-preload.js->window.hero. - per-tab pageViews: live web content, untrusted, no preload. Tab model in main.js (Map of tabId -> view; only active visible).
- aiView (
ai.*): docked right AI panel. Trusted,ai-preload.js. - popoverView (
overlay.*): top-right menu / profile / downloads / history layer (avoids clipping; sized per kind). Trusted,overlay-preload. - findView (
find.*): find-in-page bar. Trusted,find-preload.js.
Runtime accent theming: main injects the user's accent into every chrome view
via webContents.insertCSS (applyAccent / broadcastAccent).
- AI runs through Squire (
@pythonluvr/squire, npm) which spawns the provider CLI as a subprocess on the user's subscription (no API cost), OR a direct BYOK API call (lib/api.js, SSE streaming). - Providers in
main.jsPROVIDERS: Claude (default), Gemini, ChatGPT. Each has a CLI variant and an API variant. CLI uses default permission mode (no bypass) so it answers conversationally with no autonomous tool powers. - Verified: Squire ->
claudeCLI streams.claude,gemini,codexCLIs all present on EJ's PC. - Hero "Ask AI" mode sends the prompt + chosen model into the panel
(
hero:ask-ai->ai:prompt).
lib/settings.js->userData/slash-settings.json: AI selection, BYOK API keys, model ids, accent. Reads the pre-renameloom-settings.jsonas a fallback so old installs keep their keys.lib/store.js->userData/slash-data.json: bookmarks + history.
Done: tabs (model, strip, keyboard Ctrl+T/W/Shift+T/Tab/1-9), omnibox, hero
speed-dial (engines one-click row, Google default, search suggestions via
suggest:get, / slash-command flips to AI, AI model pills from
providers:get), AI panel (CLI+API, themeable accent picker in settings),
downloads (tracked), zoom, top-right cluster (menu/profile/downloads/history),
bookmarks bar + star (Ctrl+D), find-in-page (Ctrl+F), history popover.
Accessibility baseline (aria-labels, focus-visible, reduced-motion).
Also done (2026-06-04): right-click context menus (src/context.*); a
privacy/safe layer (see PRIVACY.md): encrypted API keys (safeStorage),
hardened shell (sandbox/CSP/nav-block), DoH, DuckDuckGo default, per-site
permission prompts + site-info omnibox button/popover, HTTPS-only with a
fallback interstitial.
Not done / next (see BROWSER-UI.md + PRIVACY.md): tracker/ad blocker
(EasyList), third-party-cookie + referrer hardening, clear-data + private
window, a real settings surface (to expose the privacy toggles), SQLite for
history/bookmarks, session restore, real extensions, tab groups, F11
fullscreen, then OSS publish to PythonLuvr/slash.
The internal loom -> slash rename is done (bridge window.slash,
slash-settings.json with legacy fallback, titles, system prompt, docs); the
dead GX-red sidebar.* files were removed.
Authored as public OSS: nothing hardcoded (no keys/paths/personal data), BYOK
only, depends on the published @pythonluvr/squire from npm (not a local
file: path). Has README.md + .gitignore. Fonts bundled (IBM Plex +
Space Grotesk, OFL). Eventual repo: PythonLuvr/slash, MIT.
- No AI image gen for UI/mockups (HTML/CSS/SVG only).
- No em dashes anywhere (a write hook enforces it).
- Match real references; do not invent looks from adjectives.
- Show pixels, iterate fast; he reacts to renders, not descriptions.