feature-flags-authoring
Skill321 starsChanged 54 days agoApache-2.0View on GitHub
Add, edit, or remove a Packmind feature flag across the shared registry, the frontend gate, and the backend helper. Use when the user wants to create a new feature flag, gate a feature behind a flag, open or restrict a flag to a domain/email, change a flag audience, retire or delete a flag, or asks how the feature-flag system is wired. This is the developer how-to counterpart to the feature-flags-audit skill.
- Reads credentials
In this repository92 other files it gives its agents.
- AGENTS.mdAGENTS.md
- apps/AGENTS.mdAGENTS.md
- packages/AGENTS.mdAGENTS.md
- apps/CLAUDE.mdCLAUDE.md
- CLAUDE.mdCLAUDE.md
- packages/CLAUDE.mdCLAUDE.md
- .cursor/rules/packmind/standard-backend-tests-redaction.mdcCursor rule
- .cursor/rules/packmind/standard-changelog.mdcCursor rule
- .cursor/rules/packmind/standard-code-comments.mdcCursor rule
- .cursor/rules/packmind/standard-compliance-logging-personal-information.mdcCursor rule
- .cursor/rules/packmind/standard-typescript-good-practices.mdcCursor rule
- agent-skill-frontmatter-auditSkill
- amplitude-listener-events-adoptionSkill
- cli-e2e-test-authoringSkill
- datadog-analysisSkill
- doc-auditSkill
- feature-specSkill
- feature-sprintSkill
- packmind-onboardSkill
- packmind-update-playbookSkill
- playbook-cli-auditSkill
- product-mapSkill
- qa-reviewSkill
- release-proprietarySkill
- upgrade-runtime-stackSkill
- working-with-playground-appSkill
- working-with-pm-design-kitSkill
- agentic-design-sessionSkill
- agentic-doc-ingestSkill
- agentic-feature-framingSkill
- agentic-orchestratorSkill
- agent-skill-frontmatter-auditSkill
- amplitude-listener-events-adoptionSkill
- cli-e2e-test-authoringSkill
- create-run-e2e-testsSkill
- creating-end-user-documentation-for-packmindSkill
- datadog-analysisSkill
- doc-auditSkill
- feature-flags-auditSkill
- feature-flags-authoringSkill
- feature-specSkill
- feature-sprintSkill
- how-to-write-typeorm-migrations-in-packmindSkill
- improve-claude-mdSkill
- packmind-onboardSkill
- packmind-update-playbookSkill
- playbook-cli-auditSkill
- product-mapSkill
- qa-reviewSkill
- release-proprietarySkill
- upgrade-runtime-stackSkill
- working-with-playground-appSkill
- working-with-pm-design-kitSkill
- agent-skill-frontmatter-auditSkill
- amplitude-listener-events-adoptionSkill
- cli-e2e-test-authoringSkill
- creating-end-user-documentation-for-packmindSkill
- datadog-analysisSkill
- doc-auditSkill
- feature-flags-auditSkill
- The first 60 shown.
The file
We split this skill into the rules it gives an agent
4 rules. About 0 are common, 2 are distinctive, and 2 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈2
Distinctive · estimate
This author's own choices. Worth a look.
2
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 27
Add the key constant, the audience entry, and extend the union.
- Distinctive: line 91
Delete every call site:
- Very specific: line 95
Run the feature-flags-audit skill to confirm no orphaned keys, map entries, or call sites remain.
- Very specific: line 100
Never log an email in clear text: If you log a flag decision, mask the email (first 6 chars + *) or, better, log only the flag key and the …
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill 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.
Files
Feature Flags Authoring
A developer how-to for the full lifecycle of a Packmind feature flag: add, edit, remove. Flags gate a feature by email domain (or exact email). The same decision function runs on frontend and backend, so behavior never diverges. Follow the steps below exactly — every flag touches three places.
For inventorying existing flags, orphan detection, and audience audits, use the feature-flags-audit skill instead. This skill changes flags; that one scans them.
Where things live
- Shared registry —
@packmind/feature-flags(pure,env:shared, browser-safe). The single source of truth:registry.ts— the*_FEATURE_KEYconstants,DEFAULT_FEATURE_DOMAIN_MAP(Record<string, readonly string[]>mapping each flag's string value to allowed entries), and theFeatureFlagKeyunion.isFeatureFlagEnabled.ts— the pure evaluator:isFeatureFlagEnabled({ featureKeys, featureDomainMap, userEmail }).
- Frontend gate —
<PMFeatureFlag>from@packmind/ui(or a directisFeatureFlagEnabled(...)call). The keys,DEFAULT_FEATURE_DOMAIN_MAP, andisFeatureFlagEnabledare re-exported from@packmind/uifor back-compat, so existing consumers can import from either place. - Backend gate —
isFeatureEnabled(flag, { userEmail }), a plain async helper from@packmind/node-utils. It resolves the env kill-switch first, then defers to the shared email-domain rule. It is NOT a port and has no DI — import it and call it. - Env kill-switch —
FF_<SCREAMING_SNAKE>(e.g.FF_CHANGE_PROPOSALS_IN_WEBAPP).on/all/trueforce the flag on;off/none/falseforce it off; unset or empty falls through to the email-domain map.
Two flags exist today: 'change-proposals-in-webapp' and 'orga-space-management'.
Add a flag
1. Register it in @packmind/feature-flags
Add the key constant, the audience entry, and extend the union. Do all three — a constant with no map entry is never enabled for anyone; a map entry with no union member can't be typed at call sites.
// registry.ts
export const MY_FEATURE_KEY = 'my-feature' as const;
export type FeatureFlagKey =
| 'change-proposals-in-webapp'
| 'orga-space-management'
| 'my-feature';
export const DEFAULT_FEATURE_DOMAIN_MAP: Record<string, readonly string[]> = {
// ...
'my-feature': ['@packmind.com'], // domains keep the `@`; exact emails have no leading `@`
};2. Gate the frontend
Wrap the UI that should appear only when the flag is on:
import { PMFeatureFlag } from '@packmind/ui';
import { MY_FEATURE_KEY, DEFAULT_FEATURE_DOMAIN_MAP } from '@packmind/feature-flags';
<PMFeatureFlag
featureKeys={[MY_FEATURE_KEY]}
featureDomainMap={DEFAULT_FEATURE_DOMAIN_MAP}
userEmail={currentUser.email}
>
{/* gated UI */}
</PMFeatureFlag>For a branch (route, tab, boolean), call isFeatureFlagEnabled({ featureKeys: [MY_FEATURE_KEY], featureDomainMap: DEFAULT_FEATURE_DOMAIN_MAP, userEmail }) directly.
3. Gate the backend
Inside a member use case, command.user.email is available. Branch on the helper:
import { isFeatureEnabled } from '@packmind/node-utils';
import { MY_FEATURE_KEY } from '@packmind/feature-flags';
if (await isFeatureEnabled(MY_FEATURE_KEY, { userEmail: command.user.email })) {
// new path
} else {
// old path
}4. (Optional) Env override
Set FF_MY_FEATURE=on to force the flag on everywhere, or FF_MY_FEATURE=off to force it off, regardless of the domain map. Leave unset to defer to the map. Document the var in the deploy config if you rely on it.
Edit a flag
Change the allowed audience in DEFAULT_FEATURE_DOMAIN_MAP — add or remove domains (@company.com) or exact emails (user@company.com). This is the only place audience lives; the frontend and backend both read it.
Remember: the FF_* env kill-switch overrides the map at runtime. If a flag looks stuck on or off in an environment, check the env var before editing the map.
Remove a flag
- In
@packmind/feature-flags: delete the*_FEATURE_KEYconstant, itsDEFAULT_FEATURE_DOMAIN_MAPentry, and itsFeatureFlagKeyunion member. - Delete every call site:
- Frontend: remove the
<PMFeatureFlag>wrappers (keep the children — the UI ships unconditionally now) and anyisFeatureFlagEnabledbranches. - Backend: remove the
isFeatureEnabledbranches, keeping the winning branch inline.
- Frontend: remove the
- Drop any
FF_<SCREAMING_SNAKE>env var from deploy config. - Run the
feature-flags-auditskill to confirm no orphaned keys, map entries, or call sites remain.
Conventions
- Audience is email-domain only (Proposal A). No org, plan, team, or percentage targeting exists yet — do not describe or build it.
- Never log an email in clear text. If you log a flag decision, mask the email (first 6 chars +
*) or, better, log only the flag key and the boolean outcome. - Keep
@packmind/feature-flagspure and browser-safe. Noenv:nodeimports (no@packmind/node-utils, noConfiguration.getConfig, noprocess.env). It ships to the browser bundle. - The backend gate is a plain helper call, not an injected port. Import
isFeatureEnabledand call it directly; do not add a port/adapter/registry.
See also
feature-flags-audit— the review/scan counterpart: inventories every flag, its audience, its usages, and flags orphans. Run it after removing a flag and whenever you need the current state of the system.
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
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.

