This guide summarizes how to explore, modify, and validate the WhatsApp HTTP API (WAHA) codebase when assisting as an automation or coding agent.
- WAHA ships in Core and Plus editions. Core lives under
src/coreand only supports the default session plus minimal media features. Plus extends core viasrc/plusto add multi-session orchestration, richer media handling, and external storage integrations. - Core code must remain free from Plus-only references. A pre-commit hook
rejects the word
plusinside core files; reuse abstractions exposed through@waha/core/**instead of importing Plus modules from Core. - Commit subjects are validated: changes that touch
src/plusrequire a[PLUS] …prefix and must not include non-Plus files; everything else must use[core] …. Verify against./.precommit/validate_commit_message.pyif unsure.
- Runtime: Node.js 22.x, Yarn 3.6 (Berry). Always install packages and run scripts with Yarn.
- Framework: NestJS v11 with dependency injection, modular controllers in
src/api, and Pino-based logging vianestjs-pino. - Engines: WhatsApp engines are abstracted (
WEBJS,GOWS,NOWEB). Core usesSessionManagerCore; Plus swaps toSessionManagerPluswith extra storage backends (Mongo/Postgres/SQLite). - ESM Bridge: ESM-only dependencies (Baileys) load through
src/vendor/esm.ts. Add new ESM modules there to ensure they load exactly once. - Utilities: RxJS streams (
SwitchObservable,DefaultMap) drive webhook event fan-out. Prefer existing helpers insrc/utilsandsrc/core/utilsbefore adding bespoke logic.
src/main.ts: runtime entry point; dynamically loads the correct AppModule (Core vs Plus) and configures global interceptors/filters.src/api/**: REST controllers and WebSocket gateway. Keep handlers thin; delegate to managers/services. HTTP routes follow/api/{sessionName}/…; always thread the session name through request DTOs and guards instead of hardcodingdefault.src/core/**: shared abstractions (config services, engine bootstrap, storage, session management). Core only allows thedefaultsession and cleans up storage on boot.src/plus/**: multi-session orchestration, advanced media services, and external persistence layers (Mongo, Postgres). Reuse this layer when adding Plus-only capabilities.src/apps/**: integrations (e.g., ChatWoot) and application-specific services.src/structures/**andsrc/utils/**: DTOs, enums (event names followdomain.action), helper utilities. Maintain naming consistency when introducing new events.tests/**: Jest-based suites; do not add new tests unless explicitly asked, but keep existing tests working.
- Favor composable, long-lived solutions. If a helper already exists (e.g.,
parseBool,DefaultMap, media factories), extend it instead of reinventing logic. Lodash ships with the project—prefer its utilities over hand-rolled helpers. Import lodash as a namespace (import * as lodash from 'lodash';) so helpers likelodash.camelCasestay consistent across files. When a new third-party library seems necessary, confirm with the user, especially if the package looks stale. - Stick to NestJS patterns: inject dependencies through constructors, expose provider tokens from modules, and keep controllers free from business logic.
- Logging goes through injected
PinoLoggeror helpers insrc/utils/logging.ts.console.logis blocked by pre-commit. - Respect path aliases (
@waha/...) defined intsconfig.json; keep imports consistent (use absolute aliases, not relative../../../). - Avoid naming unused variables with a leading underscore; if a parameter is
required by a signature, explicitly
voidit instead. - For configs, prefer runtime configurability over constants. Environment keys
follow
WAHA_*for global values andWAHA_SESSION_CONFIG_*/session.config.*for per-session overrides. If both env and config are supported, honor both (WAHA_WEBJS_CONFIG_*vs.session.webjs.config.*).
- Keep identifiers (classes, methods, variables) and code comments in English so the codebase stays consistent for the global team.
- Route user-visible strings through the existing i18n structure rather than
hardcoding text. ChatWoot copy belongs in
src/apps/chatwoot/i18nwith English as the source locale before adding translations.
- Avoid introducing synthetic events; map onto existing webhook or engine events
whenever plausible. Always use the official ChatWoot API client located in
src/apps/chatwoot/client. - When adding events, align consumer names with webhook/event identifiers (e.g.,
message.any).
- Identify whether work targets Core, Plus, or shared layers. If Plus-only,
isolate changes to
src/plusand ensure the commit prefix matches. - Lean on existing services/managers; extend the appropriate session manager rather than branching logic inline.
- After edits run:
pre-commit run --all-filesyarn buildyarn testUse Node 22. Address lint or formatting issues before proceeding.
- Do not start the application yourself; ask the user to run it if runtime validation is required.
- Capture any assumptions or open questions for the user, especially when touching configs, introducing dependencies, or modifying public APIs.
- Concurrency-sensitive sections (session start/stop) rely on
async-lock. When adding async flows, reuseSessionManager.withLockor existing retry utilities (promiseTimeout,waitUntil). - Media features centralize through
MediaManagerandMediaStorageFactory. When altering media behavior, update both Core and Plus variants where applicable. - Keep docs and code ASCII unless a file already uses other characters. When updating documentation, mirror the concise, actionable tone used here.
Following this playbook keeps contributions aligned with WAHA’s structure, automation hooks, and release process.