This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
citadel_cli is a React component library published to npm. It provides a keyboard-driven command console (like a dev-tools terminal overlay) that can be embedded in web apps. Users trigger it with a configurable key (default: .), type hierarchical commands with auto-expansion, and see results rendered inline.
npm run dev # Start Vite dev server (demo app in src/App.tsx)
npm run build # TypeScript compile + Vite library build → dist/
npm run lint # ESLint
npm run lint:fix # ESLint with auto-fix
npm test # Vitest unit tests (run once)
npm run test:e2e # Playwright end-to-end tests
npm run coverage # Vitest with coverage reportTo run a single test file:
npx vitest --run src/components/Citadel/hooks/__tests__/useCommandParser.test.tsNote: A pre-commit hook runs the full test suite before every commit. This takes ~10–15 seconds.
Releases are tag-driven via GitHub Actions — no manual npm publish:
npm version <patch|minor|major> # bumps package.json + creates git tag
git push && git push --tags # triggers CI publish to npm- Library entry point:
src/index.ts— exportsCitadel,CommandRegistry,CitadelConfig, and result types - Dev app:
src/App.tsx— Vite dev server demo, not included in the build - Build output:
dist/citadel.es.jsanddist/citadel.umd.cjs, plusdist/citadel.css
The Citadel React component mounts a Web Component (<citadel-element>) that hosts a Shadow DOM. All React rendering happens inside that shadow root. CSS is injected as CSSStyleSheet via adoptedStyleSheets. This means Tailwind and component styles are fully isolated from the host app.
The custom Vite plugin plugins/vite-shadow-dom.ts handles CSS-in-JS bundling for this pattern.
-
CommandRegistry— holdsCommandNode[], each with orderedCommandSegment[](words + arguments), a description, and an async handler. Users build this externally and pass it to<Citadel>. -
CitadelConfigContext(src/components/Citadel/config/CitadelConfigContext.tsx) — React context wrapping the entire component tree inside the shadow DOM. Provides merged config, the command registry, storage, and a sharedSegmentStack. -
SegmentStack(src/components/Citadel/types/segment-stack.ts) — observer-pattern stack that tracks the user's current command path (e.g.,["user", "show"]). Lives in context so all hooks share one instance. -
useCommandParser(src/components/Citadel/hooks/useCommandParser.ts) — the central input-handling hook. ManagesInputState(idle|entering_command|entering_argument), auto-expansion logic (tryAutocomplete), key event handling, and command execution dispatch. -
useCitadelState(src/components/Citadel/hooks/useCitadelState.ts) — manages output history (OutputItem[]), command execution with timeout, and history navigation.
CitadelRoot renders either:
PanelController— slide-up overlay anchored to viewport bottom, toggleable viashowCitadelKey. Supports drag-to-resize.InlineController— always-visible, fills its host container. Useful for embedding in dashboards.
Both delegate to CitadelTty for the actual terminal UI.
Handlers must return one of these (all extend CommandResult):
TextCommandResult— plain textJsonCommandResult— JSON treeImageCommandResult— image displayErrorCommandResult— error styling
Command history is persisted via StorageFactory, which returns either LocalStorage or MemoryStorage based on config.storage.type. The HistoryService and useCommandHistory hook manage navigation (arrow keys) and persistence.
- Prefer oklch for defining colors over HCL or RGB.
tsconfig.app.json configures @/ as an alias for src/. Use @/components/... for imports within the library source.
- Skill path:
skills/citadel-browser-screenshots/SKILL.md - Use when: You need deterministic browser screenshots of Citadel behavior (command expansion, suggestions, output, inline/panel UI).
- Script:
skills/citadel-browser-screenshots/scripts/capture_citadel_screenshot.mjs - Sequence reference:
skills/citadel-browser-screenshots/references/citadel_sequences.md
Example:
node skills/citadel-browser-screenshots/scripts/capture_citadel_screenshot.mjs \
--url http://127.0.0.1:4173 \
--tab "Basic" \
--keys "u s 1234 Enter" \
--out /Users/jchilders/work/jchilders/citadel_cli/test-results/screenshots/citadel-basic.png \
--clip-citadel