agentleFS
leather-ioleather-io/mono/CLAUDE.md

mono

CLAUDE.md28 starsChanged 34 days agoMITView on GitHub

DO NOT ADD, REMOVE, OR MODIFY COMMENTS IN CODE — including punctuation and formatting in existing comments. Only touch comments if explicitly asked. After ANY code changes, you MUST run verification (see Verification section). Do not report a task as complete or move on until all checks pass. Leather is a Bitcoin & Stacks wallet — browser extension, mobile app (Expo/React Native), and web app. Turborepo monorepo using pnpm, organized in CLEAN architecture layers. Use the monorepo-navigation skill for detailed…

  • Reads credentials
  • Installs packages

The file

Show its rules and text

We split this CLAUDE.md into the rules it gives an agent

17 rules. About 0 are common, 6 are distinctive, and 11 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈6

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 11

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    DO NOT ADD, REMOVE, OR MODIFY COMMENTS IN CODE — including punctuation and formatting in existing comments.

    line 1
  2. Distinctive:

    After ANY code changes, you MUST run verification (see Verification section).

    line 3
  3. Very specific:

    Use the monorepo-navigation skill for the full decision tree on where new code goes.

    line 23
  4. Distinctive:

    Don't use enums.

    line 64
  5. Very specific:

    Default to interface for object shapes.

    line 65
  6. Very specific:

    Use function declarations for top-level functions and React components.

    line 66
  7. Very specific:

    Prefer Remeda (keys, entries, pipe, filter, etc.) over Object.keys/Object.entries for typed utilities and non-trivial transforms.

    line 68
  8. Very specific:

    When a rule removes a type predicate, narrow with an existing guard (isNumber, isDefined, a zod schema) before reaching for flatMap(x => …

    line 70
  9. Very specific:

    Prefer const over let. Prefer named constants over magic numbers or strings.

    line 71
  10. Distinctive:

    No nested ternary expressions.

    line 72
  11. Very specific:

    Use object method shorthand syntax in objects and interfaces ({ foo() {} } not { foo: () => {} }).

    line 73
  12. Distinctive:

    Never throw in React render paths, reducers, or selectors.

    line 81
  13. Very specific:

    Use *.spec.ts(x) for tests, co-located next to the file under test.

    line 90
  14. Very specific:

    Never import from a barrel export (index.ts) within the same package's sub-modules.

    line 94
  15. Very specific:

    Place initialState in write/slice modules, not shared read modules.

    line 95
  16. Distinctive:

    Never expose private keys, seeds, or mnemonics in error messages or logs.

    line 103
  17. Very specific:

    If working on mobile, run pnpm lingui from apps/mobile/ before running verification.

    line 123

≈ “Common” is an estimate: at least 1 in 5 of the 26,980 CLAUDE.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
CLAUDE.md

DO NOT ADD, REMOVE, OR MODIFY COMMENTS IN CODE — including punctuation and formatting in existing comments. Only touch comments if explicitly asked.

After ANY code changes, you MUST run verification (see Verification section). Do not report a task as complete or move on until all checks pass.

Claude Instructions

Leather is a Bitcoin & Stacks wallet — browser extension, mobile app (Expo/React Native), and web app.

Architecture

Turborepo monorepo using pnpm, organized in CLEAN architecture layers. Use the monorepo-navigation skill for detailed package structure and decision trees.

Presentation: apps/ (extension, mobile, web), @leather.io/ui, @leather.io/features Application: @leather.io/queries (React Query), @leather.io/services (orchestration, API calls, DI, caching) Domain: @leather.io/models (types), @leather.io/bitcoin, @leather.io/stacks State: @leather.io/state (Redux Toolkit slices for shared state) Foundation: @leather.io/utils, @leather.io/constants, @leather.io/tokens, @leather.io/crypto

  • State management: Redux Toolkit. Extension uses {feature}.slice.ts; mobile uses {feature}.write.ts (slice + actions) and {feature}.read.ts (selectors + hooks).
  • Server state: React Query (@tanstack/react-query). Queries live in packages/queries/ and app-level src/queries/.
  • Feature flags: LaunchDarkly with camelCase flag keys in extension; also used in mobile.

Use the monorepo-navigation skill for the full decision tree on where new code goes.

Development commands

First-time setup:

pnpm i && pnpm build

Run extension:

pnpm dev

Run web:

pnpm dev

Run mobile:

cd apps/mobile
pnpm 1password:env:dev    # requires 1Password CLI — or ask developer to add EXPO_PUBLIC_LAUNCH_DARKLY to .env
pnpm ios

Mobile requires an apps/mobile/.env file with EXPO_PUBLIC_LAUNCH_DARKLY set. Run pnpm 1password:env:dev to generate it, or ask the developer to provide the LaunchDarkly key.

React Native / Expo

  • Mobile app uses Expo with local prebuild + Fastlane on GitHub runners (no EAS Build, no EAS Update, no @expo/fingerprint).
  • SDK upgrades: check the official upgrade guide for deprecated/renamed APIs before starting.
  • Clear bundler cache: npx expo start --dev-client --clear.
  • BUILD_TARGET env var controls platform builds: mobile, extension, or web. Unset builds everything.

Code style

  • Don't use enums.
  • Default to interface for object shapes. Name component props ComponentNameProps.
  • Use function declarations for top-level functions and React components. Arrow functions for callbacks only.
  • Destructure props directly in the function signature.
  • Prefer Remeda (keys, entries, pipe, filter, etc.) over Object.keys/Object.entries for typed utilities and non-trivial transforms. Use native methods for trivial cases.
  • No as casts, ! non-null assertions, or any. Use runtime checks, type guards, or unknown with narrowing.
  • When a rule removes a type predicate, narrow with an existing guard (isNumber, isDefined, a zod schema) before reaching for flatMap(x => cond ? [x] : []).
  • Prefer const over let. Prefer named constants over magic numbers or strings.
  • No nested ternary expressions.
  • Use object method shorthand syntax in objects and interfaces ({ foo() {} } not { foo: () => {} }).
  • camelCase for file-level constants; SCREAMING_SNAKE_CASE in the constants package or constants.ts files.
  • The per-package eslint-suppressions.json files and .dependency-cruiser-known-violations.json are a frozen baseline of pre-existing violations. Never run eslint --suppress-all or regenerate the known-violations file, and never add entries by hand. Entries only go away by fixing the code (then eslint --prune-suppressions in that package).

Error handling

  • throw is acceptable for genuinely invalid states (wrong keychain type, missing required config).
  • For expected failure paths (user input, optional lookups), prefer returning null, undefined, or typed result objects.
  • Never throw in React render paths, reducers, or selectors.
  • In React render paths: use error boundaries for unexpected errors; return null or fallback UI for expected empty states.

File naming

  • Kebab-case file names (e.g., alternate-header-layout.tsx).
  • Platform suffixes for cross-platform code: .web.tsx, .native.tsx, .shared.ts.
  • Convention-named config files are exempt (e.g., babel.config.cjs, tsconfig.json).
  • No index.ts(x) except barrel exports from library packages or file-based router requirements.
  • Use *.spec.ts(x) for tests, co-located next to the file under test.

Circular dependencies

  • Never import from a barrel export (index.ts) within the same package's sub-modules.
  • Place initialState in write/slice modules, not shared read modules.
  • Metro require cycle warnings are bugs to fix, not warnings to ignore.
  • Concrete anti-pattern: slice → utils → store → slice. Break by keeping initialState in write/slice files and never importing from store/index.ts within slices.

Security

  • Sanitize HTML from external sources (NFT metadata, collectible descriptions) before rendering.
  • Validate responses from IPFS gateways and untrusted origins.
  • Never expose private keys, seeds, or mnemonics in error messages or logs.

Commits

  • Conventional commits format with scope: feat(mobile), refactor(web), fix(utils).
  • Imperative language. No body unless explicitly asked.
  • Branches and PRs are always based against dev, not main.

Verification

You MUST run these after any code changes. Do not consider a task complete until they pass:

pnpm format
pnpm lint
pnpm typecheck
pnpm knip
pnpm --filter @leather.io/extension lint:unused-exports

If working on mobile, run pnpm lingui from apps/mobile/ before running verification.

For faster feedback in a specific package:

pnpm --filter @leather.io/{package} lint
pnpm --filter @leather.io/{package} typecheck

Tooling

  • Turborepo + pnpm.
  • Vitest for unit/integration tests. Use the testing-patterns skill for conventions.
  • Playwright for E2E tests (extension and web). Sleeps, networkidle, waitForSelector and raw locators are lint errors in both suites. For the extension use the write-extension-e2e skill: page-object actions own their readiness waits. Avoid force: true — it hides accessibility issues. Never nest interactive elements.

Common tasks

  • Add a UI component → @leather.io/ui, use the monorepo-navigation skill
  • Add a Redux slice → Extension: {feature}.slice.ts; Mobile: {feature}.write.ts + {feature}.read.ts
  • Add a React Query hook → packages/queries/ or app-level src/queries/
  • Run a single package's tests → pnpm --filter @leather.io/{package} test:unit
  • Add or fix an extension E2E test → apps/extension/tests, use the write-extension-e2e skill

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.