--- name: epupp-squint description: 'Epupp-specific Squint source conventions for src/**. Use when: editing Squint/ClojureScript in src/, testing pure functions via squint-nrepl, debugging Squint-to-Scittle message interop, avoiding direct .mjs edits, or rewriting legacy JS interop to Clojure style. For universal Squint semantics (keywords, data structures, async, compilation model) load the universal Squint skill separately. IMPORTANT: Also load when planning changes to src/** Squint code.' --- # Epupp Squint Conventions For universal Squint semantics (keywords, data structures, async, function availability, compilation model), load the **Squint skill**. This skill covers only epupp-specific patterns. ## Prefer Clojure Style Over JS Interop Squint supports most of `clojure.string` and the core library. Prefer idiomatic Clojure functions over JavaScript interop when an equivalent exists. This keeps code consistent across the three places normalization logic lives: source, web installer userscript, and the HQ sync script. The existing codebase has legacy JS interop patterns. When touching them, prefer rewriting to Clojure style. ## Squint-to-Scittle Interop When Scittle's `clj->js` converts maps with namespaced keywords, it strips the namespace prefix. This affects any code where Scittle sends data to Squint extension code via messages: ```clojure ;; Scittle side sends {:epupp/inject ["scittle://reagent.js"]} ;; After clj->js, the key becomes "inject" (namespace stripped) (aget manifest "inject") ; correct (aget manifest "epupp/inject") ; nil - namespace was stripped ``` Use `(js/Object.keys obj)` to verify actual keys when debugging cross-runtime message passing. Never edit `.mjs` files directly - they're generated by Squint. ## Testing Code in Squint nREPL Use the Squint nREPL to test pure functions before editing files. ### Verifying the REPL is Available 1. Use `clojure_list_sessions` to check available REPL sessions 2. Look for a session with `"sessionKey": "cljs"` - this is the Squint nREPL 3. Test connectivity by evaluating a simple expression: `(+ 1 2)` If no Squint session is available, **ask the human to start it**: > "I need the Squint nREPL to test this code. Please run `bb squint-nrepl` and connect Calva to it (port 1339)." Do NOT start the server yourself - the human manages their terminal sessions. ### Testing Pure Functions Once connected, test interactively: ```clojure ;; Test pure functions from url_matching.cljs (require '[url-matching :refer [url-matches-pattern?]]) (url-matches-pattern? "https://github.com/foo" "*://github.com/*") ;; => true ;; Test storage helpers (require '[storage :refer [generate-script-id]]) (generate-script-id "My Cool Script") ;; => "my-cool-script" ``` **What works in Squint nREPL:** - Pure functions (data transformations, URL matching, ID generation) - Core Squint functions (`map`, `filter`, `assoc`, etc.) - String manipulation, regex operations **What doesn't work:** - Browser APIs (`chrome.*`, `document.*`, `window.*`) - Extension-specific code (message passing, storage) - Anything requiring the DOM **Workflow:** Develop and test pure logic in the nREPL first, then integrate into browser-specific code with confidence.