mit einem Klick
add-integration
// Add a new third-party integration (Jira/Linear-style) — per-workspace credentials, 90s auth-health poller, settings page, link/import buttons. Use when scaffolding a new external service integration.
// Add a new third-party integration (Jira/Linear-style) — per-workspace credentials, 90s auth-health poller, settings page, link/import buttons. Use when scaffolding a new external service integration.
Write and run web E2E tests (Playwright) using TDD — locations, patterns, commands, and debugging.
Debug a running kandev development instance. Use when the user reports a bug, unexpected behavior, or asks to investigate an issue while kandev is running via `make dev`. Triages the bug class first (backend-logic → Go test, live-instance → /debug/export, UI → browser), launches an ISOLATED parallel instance when a running app is needed, and tears down only what it started.
Ensures UI feature work ships with desktop and mobile parity, responsive behavior, and mobile Playwright E2E coverage. Use when implementing, planning, reviewing, or testing any new feature, page, component, workflow, form, dialog, sidebar, navigation, dashboard, or visual UI change; if work touches frontend or user-facing UI, this skill must run even when user mentions only desktop or says "new feature".
Add debug logs (temporary console.log / structured Warn, or permanent namespaced loggers) to investigate or instrument runtime behaviour. Use whenever the user wants to add logs, log statements, console.logs, trace, instrument, or print runtime behaviour to debug a frontend or backend issue. Triggers include "add debug logs", "add some logs", "log this", "trace this", "instrument", "investigate why", "print", "console.log around". Temporary debug logs must be stripped before creating a PR; persistent ones (frontend `createDebugLogger`, backend tier-appropriate level) stay.
Commit, push, and create a PR. Default is ready-for-review with auto-fixup. Use --draft to skip review/fixup.
Wait for CI checks and automated reviews (CodeRabbit, Greptile, Claude, cubic) on a PR, fix failures and address comments, then push.
| name | add-integration |
| description | Add a new third-party integration (Jira/Linear-style) — per-workspace credentials, 90s auth-health poller, settings page, link/import buttons. Use when scaffolding a new external service integration. |
Jira and Linear are the model: per-workspace credentials, a 90s auth-health poller, a settings page with status banner + reconnect CTA, link/import buttons that gate on availability. New integrations should reuse the shared shapes rather than copying either.
apps/backend/internal/<name>/)service.go, store.go, client.go, provider.go, handlers.go, models.go, poller.go. Expose Provide(writer, reader *sqlx.DB, secrets SecretStore, eventBus bus.EventBus, log *logger.Logger) (*Service, func() error, error). Pass nil for eventBus when the integration doesn't publish events; both Jira and Linear take and use it for issue-watch publishing.internal/integrations/secretadapter instead of writing your own upsert wrapper around secrets.SecretStore. The adapter satisfies any per-integration SecretStore interface shaped as {Reveal, Set, Delete, Exists}.internal/integrations/healthpoll for the auth-health loop. Implement the Prober interface (ListConfiguredWorkspaces + RecordAuthHealth) on a small adapter and let healthpoll.New("name", prober, log) own Start/Stop/ticker. Keep integration-specific loops (JQL polling, webhook reconciliation, etc.) separate, like jira's issue-watch loop.init<Name>Service(...) helper in cmd/kandev/services.go, not inline in provideServices.mock_client.go + mock_controller.go next to the real client. Provide branches on KANDEV_MOCK_<NAME>=true and returns the in-memory client; RegisterMockRoutes(router, svc, log) mounts /api/v1/<name>/mock/* only when the service was built with the mock. The e2e backend fixture sets the env var so Playwright tests drive the mock via apiClient.mock<Name>*() helpers — see jira/linear for the layout.hooks/domains/<name>/, not components/<name>/.hooks/domains/integrations/use-integration-availability.ts and use-integration-enabled.ts — each integration's useXAvailable / useXEnabled should be a one-line wrapper passing the storage key + sync event + config-fetch function.<IntegrationAuthStatusBanner> (components/integrations/auth-status-banner.tsx).<IntegrationAuthErrorMessage> (components/integrations/auth-error-message.tsx) — supply the integration's display name, regex check, and reconnect href.<ValidatedPopover> (components/integrations/validated-popover.tsx) — supply the icon, label, key regex, fetch function, and success callback.SearchFilter as JSON in filter_json (Linear has no JQL equivalent). The orchestrator emits NewJiraIssueEvent / NewLinearIssueEvent respectively and dedups by issue key (Jira) vs identifier (Linear).linear_configs row carries an org_slug captured from successful probes; Jira's row does not.