This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Smesh Signer is a browser extension for managing multiple Nostr identities and signing events without exposing private keys to web applications. It implements NIP-07 (window.nostr interface) with support for NIP-04 and NIP-44 encryption.
npm ci # Install dependencies
npm run build:chrome # Build Chrome extension (outputs to dist/chrome)
npm run build:firefox # Build Firefox extension (outputs to dist/firefox)
npm run watch:chrome # Development build with watch mode for Chrome
npm run watch:firefox # Development build with watch mode for Firefox
npm test # Run unit tests with Karma
npm run lint # Run ESLint
Important: After making any code changes, rebuild both extensions before testing:
npm run build:chrome && npm run build:firefox
This is an Angular 19 CLI monorepo with three projects:
The extension follows a three-layer communication model:
smesh-signer-content-script.ts): Injected into web pages, bridges messages between page scripts and the background service workersmesh-signer-extension.ts): Injected into page context, exposes window.nostr API to web applicationsbackground.ts): Handles NIP-07 requests, manages permissions, performs cryptographic operationsMessage flow: Web App → window.nostr → Content Script → Background → Content Script → Web App
Each browser (Chrome/Firefox) has its own handler implementations in projects/{browser}/src/app/common/data/.
The vault uses Argon2id + AES-256-GCM for password-based encryption:
BrowserSyncData.salt)BrowserSessionData.vaultKey) to avoid re-derivation on each operationNote: Argon2id runs on main thread via WebAssembly (hash-wasm) because Web Workers cannot load external scripts in browser extensions due to CSP restrictions. A deriving modal provides user feedback during the ~3 second operation.
Both extensions use @angular-builders/custom-webpack to bundle additional entry points beyond the main Angular app:
background.ts - Service workersmesh-signer-extension.ts - Page-injected scriptsmesh-signer-content-script.ts - Content scriptprompt.ts - Permission prompt popupoptions.ts - Extension options pageThe @common import alias resolves to projects/common/src/public-api.ts. Key exports:
StorageService: Central data management with encryption/decryptionCryptoHelper, NostrHelper: Cryptographic utilities (nostr-tools based)Argon2Crypto: Vault encryption with Argon2id key derivationPermissions are stored per identity+host+method combination. The background script checks permissions before executing NIP-07 methods:
allow/deny policies can be stored for each methodsignEventChrome:
chrome://extensionsdist/chromeFirefox:
about:debuggingdist/firefoxgetPublicKey() - Return public keysignEvent(event) - Sign Nostr eventgetRelays() - Get configured relaysnip04.encrypt/decrypt - NIP-04 encryptionnip44.encrypt/decrypt - NIP-44 encryption