Quick reference for AI assistants working on this codebase.
- NEVER commit secrets - No API keys, tokens, passwords, .env files
- NEVER skip tests - All changes require passing tests
- NEVER skip security scans - Run
make securitybefore commits - NEVER create files >600 lines - Split by responsibility (see
.claude/rules/file-size-limits.md)
make ci-full # Complete CI: quality checks → tests → cleanup
# OR for quick checks without integration tests:
make ci # Runs: fmt → vet → lint → test-unit → test-race → security → vuln → buildDetails: See .claude/rules/go-quality.md, .claude/rules/file-size-limits.md
| Change | Unit Test | Integration Test | Update Docs |
|---|---|---|---|
| New feature | ✅ REQUIRED | ✅ REQUIRED | ✅ REQUIRED |
| Bug fix | ✅ REQUIRED | ||
| New command | ✅ REQUIRED | ✅ REQUIRED | ✅ REQUIRED |
| Flag change | ✅ REQUIRED | ❌ Not needed | ✅ REQUIRED |
See: .claude/rules/testing.md for coverage targets by package type.
Check coverage: make test-coverage
📚 See docs/INDEX.md for all documentation.
Rules: .claude/rules/documentation-maintenance.md
| Path | Reason |
|---|---|
.env*, **/secrets/** |
Contains secrets |
*.pem, *.key |
Certificates/keys |
go.sum |
Auto-generated |
.git/, vendor/ |
Managed externally |
- Language: Go (module minimum 1.24.2, use latest installed version features)
- Architecture: Hexagonal (ports and adapters)
- CLI Framework: Cobra
- API: Nylas v3 ONLY (never use v1/v2)
- Timezone Support: Offline utilities + calendar integration ✅
- Email Signing: GPG/PGP email signing (RFC 3156 PGP/MIME) ✅
- AI Chat: Web-based chat interface using locally installed AI agents ✅
- Credential Storage: System keyring (see below)
- Web UI: Air - browser-based interface (localhost:7365)
Details: See docs/ARCHITECTURE.md
| Variable | Purpose | Default |
|---|---|---|
NYLAS_DISABLE_KEYRING |
Disable system keyring, use encrypted file | false |
NYLAS_API_KEY |
Override API key from keyring (for testing) | - |
NYLAS_CLIENT_ID |
Override client ID from keyring (for testing) | - |
NYLAS_GRANT_ID |
Override grant ID (for testing) | - |
Integration test env vars: See .claude/commands/run-tests.md for full list
Credentials stored in system keyring (service: "nylas") via nylas auth config.
Key files: internal/ports/secrets.go (constants), internal/adapters/keyring/ (implementation), internal/app/auth/config.go (setup)
Keys: client_id, api_key, client_secret, org_id, grants, default_grant, grant_token_<id>
Disable keyring: NYLAS_DISABLE_KEYRING=true (falls back to encrypted file at ~/.config/nylas/)
Hexagonal layers: CLI (internal/cli/) → Port (internal/ports/) → Adapter (internal/adapters/)
Core files: cmd/nylas/main.go, internal/ports/nylas.go, internal/adapters/nylas/client.go
Quick lookup: CLI helpers in internal/cli/common/, HTTP in client.go, Air at internal/air/, Chat at internal/chat/
CLI packages: admin, ai, audit, auth, calendar, config, contacts, email, inbound, mcp, notetaker, otp, scheduler, setup, slack, timezone, webhook
Additional packages:
internal/ports/output.go- OutputWriter interface for pluggable formattinginternal/adapters/output/- Table, JSON, YAML, Quiet output adaptersinternal/httputil/- HTTP response helpers (WriteJSON, LimitedBody, DecodeJSON)internal/adapters/gpg/- GPG/PGP email signing service (2026)internal/adapters/mime/- RFC 3156 PGP/MIME message builder (2026)internal/chat/- AI chat interface with local agent support (2026)internal/cli/setup/- First-time setup wizard (nylas init)
Full inventory: docs/ARCHITECTURE.md
Quick pattern:
- Domain:
internal/domain/<feature>.go- Define types - Port:
internal/ports/nylas.go- Add interface methods - Adapter:
internal/adapters/nylas/<feature>.go- Implement methods - Mock:
internal/adapters/nylas/mock.go- Add mock methods - CLI:
internal/cli/<feature>/- Add commands - Register:
cmd/nylas/main.go- Add command - Tests:
internal/cli/integration/<feature>_test.go - Docs:
docs/COMMANDS.md- Add examples
Detailed guide: Use /add-command skill
Details: .claude/rules/testing.md
Hooks: Auto-enforce quality. See .claude/HOOKS-CONFIG.md
Skills: /run-tests, /add-command, /generate-tests, /security-scan
Agents: See .claude/agents/README.md
| Command | Purpose |
|---|---|
make ci-full |
Complete CI (quality + tests) - run before commits |
make ci |
Quick quality checks (no integration) |
make build |
Build binary |
nylas init |
First-time setup wizard |
nylas air |
Start Air web UI (localhost:7365) |
nylas chat |
Start AI chat interface (localhost:7367) |
Available targets: Run make help or make to see all available commands
Debugging: Check ports/nylas.go → adapters/nylas/client.go → cli/<feature>/helpers.go
API docs: https://developer.nylas.com/docs/api/v3/
When Claude makes a mistake, use: "Reflect on this mistake. Abstract and generalize the learning. Write it to CLAUDE.md."
This section captures lessons learned from mistakes. Claude updates this section when errors are caught.
- Playwright selectors: ALWAYS use semantic selectors (getByRole > getByText > getByLabel > getByTestId), NEVER CSS/XPath
- Go tests: ALWAYS use table-driven tests with t.Run() for multiple scenarios
- Air handlers: ALWAYS return after error responses (prevents writing to closed response)
- Integration tests: ALWAYS use acquireRateLimit(t) before API calls in parallel tests
- Frontend JS: ALWAYS use textContent for user data, NEVER innerHTML (XSS prevention)
- CLI clients: Use
common.GetNylasClient()directly, NEVER create package-localgetClient()wrappers - Grant IDs: Use
common.GetGrantID(args)directly, NEVER create package-localgetGrantID()wrappers - File sizes: Use
common.FormatSize()for byte formatting, NEVER create duplicate formatBytes/formatFileSize - Success/Error messages: Use
common.PrintSuccess()/common.PrintError(), delegate from package-local helpers - HTTP handlers: Use
httputil.WriteJSON()/httputil.LimitedBody()for consistent response handling - AI clients: Use shared helpers in
adapters/ai/base_client.go(ConvertMessagesToMaps, ConvertToolsOpenAIFormat, FallbackStreamChat) - Output formatting: Use
common.GetOutputWriter(cmd)for JSON/YAML/quiet support, NEVER create custom --format flags - Client helpers: Use
common.WithClient()andWithClientNoGrant()to reduce boilerplate, NEVER duplicate setup code - Status colors: Use
common.StatusColor()/StatusIcon()/ColorSprint(), NEVER create package-local status color functions - Pagination: Use
common.SetupPagination()for limit/maxItems resolution, NEVER duplicate auto-pagination logic in list commands - Pagination helpers: Use
common.NormalizePageSize()andFetchCursorPages()for cursor-based pagination boilerplate - Test JSON responses: Use
testutil.WriteJSONResponse()in httptest handlers, NEVER repeat the Content-Type/WriteHeader/Encode triplet
- Progressive disclosure: Keep main skill files under 100 lines, use references/ for details
- Self-learning: Use "Reflect → Abstract → Generalize → Write" when mistakes occur
- Session continuity: Read claude-progress.txt at session start, update at session end
- Hook debugging: Check ~/.claude/logs/ for hook execution errors
- Go build cache corruption: Fix with
sudo rm -rf ~/.cache/go-build ~/go/pkg/mod && go clean -cache - Playwright MCP not connecting: Run
claude mcp add playwrightto install plugin - Quality gate timeout: Add
timeout 120before golangci-lint in hooks
- Maximum 30 items per category
- Remove obsolete entries when adding new
- One imperative line per item
- Monthly review to prune stale advice
Quick update: Press # key to add instructions during sessions
Maintain: ALWAYS/NEVER for critical rules, max 30 LEARNINGS items, prune monthly