
Create Hec Event Integration
- 9 installs
- 13.5k repo stars
- Updated August 5, 2026
- bitwarden/clients
create-hec-event-integration is a Claude Code skill for adding a token-authenticated HEC (HTTP Event Collector) event integration to the Bitwarden web client.
About
This skill adds a new HEC (HTTP Event Collector) event integration to the Bitwarden web client using the Splunk token authentication model with a Bearer token and URI. It walks through adding a service-name constant, a feature flag, card registration behind the flag, and tests. A developer uses it when wiring a new SIEM-style event destination. It supports token authentication only and does not cover API-key integrations.
- Adds a new HEC (HTTP Event Collector) SIEM event integration to the Bitwarden web client
- Implements the Splunk-style Bearer token + URI authentication model behind a feature flag
- Walks service constant, feature flag, card registration, and tests step by step
Create Hec Event Integration by the numbers
- 9 all-time installs (skills.sh)
- Ranked #3,606 of 4,347 Backend & APIs skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
create-hec-event-integration capabilities & compatibility
- Capabilities
- integration scaffolding · siem integration · feature flagging · api development
- Works with
- splunk · github
- Use cases
- api development · security audit
What create-hec-event-integration says it does
Use when adding a new HEC (HTTP Event Collector) event integration to the Bitwarden web client.
Implements the Splunk token authentication model (Bearer token + URI).
Does not apply to API key integrations or integrations requiring a custom connect dialog.
npx skills add https://github.com/bitwarden/clients --skill create-hec-event-integrationAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 9 |
|---|---|
| repo stars | ★ 13.5k |
| Last updated | August 5, 2026 |
| Repository | bitwarden/clients ↗ |
What it does
Add a token-authenticated HEC event integration (e.g. Splunk, Panther) to the Bitwarden web client behind a feature flag.
Who is it for?
Wiring a new token-authenticated SIEM/event destination (Splunk, CrowdStrike, Panther) into the Bitwarden web client.
Skip if: API key integrations or integrations requiring a custom connect dialog.
When should I use this skill?
When adding a new HEC event integration using the Splunk-style Bearer token authentication model to the Bitwarden web client.
What you get
A new token-authenticated HEC event integration registered behind a feature flag with tests.
- Service-name constant
- Feature flag and default
- Card registration behind the flag
By the numbers
- 5-step workflow
- 3 prompts before implementation
- token-auth only
Files
Create HEC Event Integration (Token Auth)
Step 1 - Prompts
Ask these questions one at a time — wait for each answer before proceeding.
Prompt 1 — Service name: "What is the service name for this integration?" (e.g. Splunk, CrowdStrike, Panther)
Use the answer as <ServiceName> throughout. The string value in the constant must exactly match what you use as the card's name in Step 4 — a mismatch silently saves the config with the wrong service name.
Prompt 2 — Authentication: "How is this integration authenticated?" (e.g. Token, API key)
- If Token — continue with the steps below.
- If anything else — stop and inform the user: "This skill currently only supports token-based authentication. Support for other authentication methods hasn't been added yet."
Prompt 3 — Logos: "Do you have the integration logo(s) ready to provide?"
- If yes — ask for the light-mode SVG file path, and optionally a dark-mode SVG path. Copy both to
apps/web/src/images/integrations/using the naming conventionlogo-<service-name-kebab>-color.svgandlogo-<service-name-kebab>-darkmode.svg. Use those filenames in Step 4. - If no — use placeholder paths in Step 4 and add a
// TODO: add logo before shippingcomment.
Step 2 — Add service name constant
File: bitwarden_license/bit-common/src/dirt/organization-integrations/models/organization-integration-service-type.ts
Add to OrganizationIntegrationServiceName:
export const OrganizationIntegrationServiceName = Object.freeze({
CrowdStrike: "CrowdStrike",
Datadog: "Datadog",
Huntress: "Huntress",
<ServiceName>: "<ServiceName>", // ← add here
} as const);Step 3 — Add feature flag
File: libs/common/src/enums/feature-flag.enum.ts
Add the enum entry and its default. The enum key is PascalCase; the string value is kebab-case (e.g. CrowdStrike → crowdstrike, Sumo Logic → sumo-logic):
// In the FeatureFlag enum:
EventManagementFor<ServiceName> = "event-management-for-<service-name-kebab>",
// In the defaultFlags object:
[FeatureFlag.EventManagementFor<ServiceName>]: FALSE,Example for Panther:
EventManagementForPanther = "event-management-for-panther",
[FeatureFlag.EventManagementForPanther]: FALSE,Step 4 — Register the card behind the feature flag
File: bitwarden_license/bit-web/src/app/dirt/organization-integrations/organization-integrations.resolver.ts
If logos were provided, copy them to apps/web/src/images/integrations/ first, then use the actual filenames below. If not, use the placeholder paths with the TODO comment:
const <serviceName>FeatureEnabled = await firstValueFrom(
this.configService.getFeatureFlag$(FeatureFlag.EventManagementFor<ServiceName>),
);
if (<serviceName>FeatureEnabled) {
integrations.push({
name: OrganizationIntegrationServiceName.<ServiceName>, // must match Step 1 exactly
linkURL: "https://bitwarden.com/help/<service-name>-siem/",
image: "../../../../../../../images/integrations/logo-<service-name>-color.svg", // TODO: add logo before shipping (if not yet provided)
imageDarkMode: "../../../../../../../images/integrations/logo-<service-name>-darkmode.svg", // TODO: add logo before shipping (omit if no dark mode variant)
type: IntegrationType.EVENT,
canSetupConnection: true,
integrationType: OrganizationIntegrationType.Hec,
});
}No changes needed to IntegrationCardComponent — new HEC services fall into the existing else branch, which calls openHecConnectDialog → saveHec → deleteHec. These methods already call buildHecConfiguration and buildHecTemplate using the card's name as the service name.
Step 5 — Add tests
File: bitwarden_license/bit-common/src/dirt/organization-integrations/models/integration-builder.spec.ts
Add one it block inside the existing describe("buildHecConfiguration", ...) block, and one inside describe("buildHecTemplate", ...). Use typed property access — do not use JSON.parse:
// Inside describe("buildHecConfiguration", ...)
it("should work with <ServiceName> service name", () => {
const config = OrgIntegrationBuilder.buildHecConfiguration(
"https://test.<servicename>.com/hec",
"test-token",
OrganizationIntegrationServiceName.<ServiceName>,
);
expect(config).toBeInstanceOf(HecConfiguration);
expect((config as HecConfiguration).uri).toBe("https://test.<servicename>.com/hec");
expect((config as HecConfiguration).scheme).toBe("Bearer");
expect((config as HecConfiguration).token).toBe("test-token");
expect(config.bw_serviceName).toBe(OrganizationIntegrationServiceName.<ServiceName>);
});
// Inside describe("buildHecTemplate", ...)
it("should work with <ServiceName> service name", () => {
const template = OrgIntegrationBuilder.buildHecTemplate(
"test-index",
OrganizationIntegrationServiceName.<ServiceName>,
);
expect(template).toBeInstanceOf(HecTemplate);
expect((template as HecTemplate).index).toBe("test-index");
expect(template.bw_serviceName).toBe(OrganizationIntegrationServiceName.<ServiceName>);
});Step 6 — Run unit tests
Run the unit tests for the spec file and confirm they all pass before finishing:
npx jest bitwarden_license/bit-common/src/dirt/organization-integrations/models/integration-builder.spec.tsAll tests must pass. If any fail, fix them before proceeding.
Common Mistakes
| Mistake | Fix |
|---|---|
name in card doesn't match OrganizationIntegrationServiceName value | They must be identical strings — saveHec() casts the name directly |
Feature flag default not set to FALSE | Always add the default entry in defaultFlags; new flags without a default will not work correctly |
| Kebab-case mismatch in flag string | Convert consistently: lowercase, spaces → hyphens |
Adding a new OrganizationIntegrationType | Not needed — all HEC services share OrganizationIntegrationType.Hec |
| Creating a new config/template class | Not needed — HecConfiguration and HecTemplate handle all HEC services |
| Referencing an image path without copying the file | Copy SVGs to apps/web/src/images/integrations/ first; if logos aren't ready, leave the TODO comment |
Example: Blumira HEC Integration (Token Auth)
A completed walkthrough of the skill using Blumira as the service name.
---
Step 1 - Prompts
| Prompt | Answer |
|---|---|
| Service name | Blumira |
| Authentication | Token |
| Logos ready? | Yes — light + dark SVGs provided |
---
Step 2 — Service name constant
File: bitwarden_license/bit-common/src/dirt/organization-integrations/models/organization-integration-service-type.ts
export const OrganizationIntegrationServiceName = Object.freeze({
Blumira: "Blumira",
CrowdStrike: "CrowdStrike",
Datadog: "Datadog",
Huntress: "Huntress",
} as const);---
Step 3 — Feature flag
File: libs/common/src/enums/feature-flag.enum.ts
// In the FeatureFlag enum (DIRT section):
EventManagementForBlumira = "event-management-for-blumira",
// In defaultFlags (DIRT section):
[FeatureFlag.EventManagementForBlumira]: FALSE,---
Step 4 — Card registration
Logos were provided in Step 1, so copy them first:
apps/web/src/images/integrations/logo-blumira-color.svgapps/web/src/images/integrations/logo-blumira-darkmode.svg
File: bitwarden_license/bit-web/src/app/dirt/organization-integrations/organization-integrations.resolver.ts
const blumiraFeatureEnabled = await firstValueFrom(
this.configService.getFeatureFlag$(FeatureFlag.EventManagementForBlumira),
);
if (blumiraFeatureEnabled) {
integrations.push({
name: OrganizationIntegrationServiceName.Blumira,
linkURL: "https://bitwarden.com/help/blumira-siem/",
image: "../../../../../../../images/integrations/logo-blumira-color.svg",
imageDarkMode: "../../../../../../../images/integrations/logo-blumira-darkmode.svg",
type: IntegrationType.EVENT,
canSetupConnection: true,
integrationType: OrganizationIntegrationType.Hec,
});
}---
Step 5 — Add tests
File: bitwarden_license/bit-common/src/dirt/organization-integrations/models/integration-builder.spec.ts
Added inside the existing describe("buildHecConfiguration", ...) and describe("buildHecTemplate", ...) blocks:
// Inside describe("buildHecConfiguration", ...)
it("should work with Blumira service name", () => {
const config = OrgIntegrationBuilder.buildHecConfiguration(
"https://test.blumira.com/hec",
"test-token",
OrganizationIntegrationServiceName.Blumira,
);
expect(config).toBeInstanceOf(HecConfiguration);
expect((config as HecConfiguration).uri).toBe("https://test.blumira.com/hec");
expect((config as HecConfiguration).scheme).toBe("Bearer");
expect((config as HecConfiguration).token).toBe("test-token");
expect(config.bw_serviceName).toBe(OrganizationIntegrationServiceName.Blumira);
});
// Inside describe("buildHecTemplate", ...)
it("should work with Blumira service name", () => {
const template = OrgIntegrationBuilder.buildHecTemplate(
"test-index",
OrganizationIntegrationServiceName.Blumira,
);
expect(template).toBeInstanceOf(HecTemplate);
expect((template as HecTemplate).index).toBe("test-index");
expect(template.bw_serviceName).toBe(OrganizationIntegrationServiceName.Blumira);
});---
Step 6 — Run unit tests
npx jest bitwarden_license/bit-common/src/dirt/organization-integrations/models/integration-builder.spec.tsResult: 32 tests passed