Files
grimoire/GEMINI.md
Alejandro Gómez 3b06e23686 ui: improve man page layout for options and examples
- Display option flags on separate lines with indented descriptions to prevent overflow
- Parse and separate example commands from their descriptions
- Highlight commands in accent color with muted descriptions below
- Increase spacing between items for better readability
2025-12-18 09:37:14 +01:00

3.9 KiB

GEMINI.md

This file provides context and guidance for Gemini (and other AI agents) when working with the Grimoire repository.

Project Overview

Grimoire is a Nostr protocol explorer and developer tool. It features a tiling window manager interface where each window is a Nostr "app" (profile viewer, event feed, NIP documentation, etc.). Commands are launched Unix-style via a Cmd+K palette.

Stack: React 19 + TypeScript + Vite + TailwindCSS + Jotai + Dexie + Applesauce

Core Architecture

1. Dual State System

  • UI State (src/core/state.ts + src/core/logic.ts):

    • Managed by Jotai atoms, persisted to localStorage.
    • Mutations: strict adherence to pure functions in src/core/logic.ts ((state, payload) => newState).
    • Scope: Workspaces, windows, layout tree, active account.
  • Nostr State (src/services/event-store.ts):

    • Singleton EventStore from applesauce-core.
    • Single source of truth for all Nostr events.
    • Reactive: Components subscribe via hooks (useProfile, useTimeline, useNostrEvent).
    • CRITICAL: Do NOT create new EventStore instances. Use the singleton in src/services/.
  • Relay State (src/services/relay-liveness.ts):

    • Singleton RelayLiveness tracks relay health.
    • Persisted to Dexie.

2. Window System

  • Layout: Recursive binary split layout via react-mosaic-component.
  • Structure:
    • Leaf: Window ID (UUID).
    • Branch: Split space.
  • Constraint: Never manipulate the layout tree directly. Use updateLayout() callbacks or logic.ts helpers.
  • Window Props: id, appId (type identifier), title, props.

3. Command System

  • Definition: src/types/man.ts defines commands as Unix man pages.
  • Flow: User types command -> argParser resolves props -> Helper opens specific appId viewer.
  • Global Flags: Defined in src/lib/global-flags.ts (e.g., --title overrides window title).

4. Reactive Nostr Pattern

  • Flow: Relays -> EventStore -> Observables -> Component Hooks.
  • Helpers: Use applesauce-react hooks or custom hooks in src/hooks/.
  • Replaceable Events: Handled automatically by EventStore (kinds 0, 3, 10000+, 30000+).

Key Conventions

  • Path Alias: @/ maps to ./src/.
  • Styling: TailwindCSS + HSL variables for theming (defined in index.css).
  • Organization: Domain-based (nostr/, ui/, services/, hooks/, lib/).
  • Types: Prefer applesauce-core types; extend in src/types/.

Important Patterns

Adding New Commands

  1. Add entry to manPages in src/types/man.ts.
  2. Create argument parser in src/lib/*-parser.ts.
  3. Create viewer component for the appId.
  4. Register viewer in WindowTitle.tsx (or equivalent registry).

Event Rendering

  • Pattern: Registry-based rendering.
  • Files: src/components/nostr/kinds/index.tsx.
  • Components: KindRenderer (feed) and DetailKindRenderer (detail/full view).
  • Naming: Use descriptive names (LiveActivityRenderer) not numbers (Kind30311Renderer).
  • Safety: All renderers are wrapped in EventErrorBoundary.

Testing

  • Framework: Vitest.
  • Commands:
    • npm test: Watch mode.
    • npm run test:run: CI mode (single run).
  • Focus: Test pure functions in logic.ts, parsers in lib/*-parser.ts, and utilities.

Critical Rules for Agents

Important

Do NOT create new instances of singletons.

  • EventStore, RelayPool, RelayLiveness are singletons in src/services/.

Important

Respect the Layout Tree.

  • Do not manually traverse or modify the Mosaic layout object. Use specific update callbacks.

Note

Use the Knowledge Base.

  • Refer to CLAUDE.md for the original documentation source.
  • Check .claude/skills for library-specific documentation (Applesauce, Nostr tools).