CLAUDE.md raw

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

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.

Build Commands

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

Architecture

Monorepo Structure

This is an Angular 19 CLI monorepo with three projects:

Extension Architecture

The extension follows a three-layer communication model:

  1. Content Script (smesh-signer-content-script.ts): Injected into web pages, bridges messages between page scripts and the background service worker
  1. Injected Script (smesh-signer-extension.ts): Injected into page context, exposes window.nostr API to web applications
  1. Background Service Worker (background.ts): Handles NIP-07 requests, manages permissions, performs cryptographic operations

Message flow: Web App → window.nostr → Content Script → Background → Content Script → Web App

Storage Layers

Each browser (Chrome/Firefox) has its own handler implementations in projects/{browser}/src/app/common/data/.

Vault Encryption (v2)

The vault uses Argon2id + AES-256-GCM for password-based encryption:

Note: 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.

Custom Webpack Build

Both extensions use @angular-builders/custom-webpack to bundle additional entry points beyond the main Angular app:

Common Library

The @common import alias resolves to projects/common/src/public-api.ts. Key exports:

Permission System

Permissions are stored per identity+host+method combination. The background script checks permissions before executing NIP-07 methods:

Testing Extensions Locally

Chrome:

  1. Navigate to chrome://extensions
  2. Enable "Developer mode"
  3. Click "Load unpacked"
  4. Select dist/chrome

Firefox:

  1. Navigate to about:debugging
  2. Click "This Firefox"
  3. Click "Load Temporary Add-on..."
  4. Select a file in dist/firefox

NIP-07 Methods Implemented