Skip to main content

flag-create

This skill should be used to create a runtime feature flag end-to-end across Flagsmith, server.ts, .env.example, and Doppler.

Source facts

Repository
jikig-ai/soleur
Last source activity
October 2, 2026 at 06:54
Detected SKILL.md language
English
Stars
16
Forks
5

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

File Explorer
2 files

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
flag-create
description
This skill should be used to create a runtime feature flag end-to-end across Flagsmith, server.ts, .env.example, and Doppler.
<!-- soleur-cloud-mode:start --> **Cloud Mode (Devin):** before pipeline work run `bash "${CLAUDE_PLUGIN_ROOT}/scripts/cloud-detect.sh"`. If `CLAUDE_PLUGIN_ROOT` is unset (cloud exec shells do not export it), resolve the root by IDENTITY, never by script basename: for `d` in `"$HOME/.local/share/devin/cli/plugins/cache"` and `/opt/.devin/plugins`, skip unless `[ -d "$d" ]`, then `MANIFEST="$(find "$d" -path '*/.claude-plugin/plugin.json' -exec grep -l '"name"[[:space:]]*:[[:space:]]*"soleur"' {} + 2>/dev/null | head -1)"`, `ROOT="${MANIFEST%/.claude-plugin/plugin.json}"` — one resolution, two consumers: `$ROOT/scripts/cloud-detect.sh` and `$ROOT/scripts/precommit-guard.sh`. (Shape check, not authentication: a planted `{"name":"soleur"}` dir passes — ADR-179 A11.) `local` or `not-local:no-devin-env` proceeds normally; any other `not-local:<reason>` applies `<plugin-root>/devin/INSTRUCTIONS.md` §Cloud Mode: emit the `--banner`, fan out sequentially with `Reviewed-Coverage: sequential-fallback` disclosure (never claim an independent review ran), `message_user` ack before any secrets read or production mutation, and run `precommit-guard.sh` before any `git commit` — hooks do not fire in cloud. <!-- soleur-cloud-mode:end --> <!-- grok-harness-invoke:start --> **Grok Build (`plugins/soleur/lib/harness.ts` `invokeSkill()`):** Read this SKILL.md in this process and run it to completion. A one-segment `soleur:<name>` in this document names a SKILL — on Grok Build, Read `plugins/soleur/skills/<name>/SKILL.md` in this process; it is not a nested tool_use. A multi-segment id such as `soleur:<domain>:<name>` names an AGENT: spawn it, never Read it, and on Grok Build spawn_subagent takes the id with its colons replaced by hyphens (`agentIdToGrokSubagentType`). **Claude Code:** Skill tool for a skill (`soleur:<name>`), Task tool with `subagent_type` for an agent. Forbidden is executing a subset, not the Read. <!-- grok-harness-invoke:end --> # flag-create Creates a new runtime feature flag in Flagsmith **and** wires it into the codebase + Doppler in one step. Use this instead of the Flagsmith UI when adding a flag that the app needs to read. ## When to use - Adding a new runtime flag (server-side resolution path; client consumes via `useFeatureFlag()` after rebuild). ## When NOT to use - Adding an env-only DCE flag (like `dev-signin`) — those don't go through Flagsmith; just hand-edit `ENV_FLAGS` in `server.ts` + `.env.example`. - Toggling an existing flag → use `soleur:flag-set-role`. ## Arguments <arguments> #$ARGUMENTS </arguments> Required positional: `<kebab-flag-name>`. Optional: `--description "<text>"`, `--dev-on` (default off), `--prd-on` (default off), `--dry-run`, `--flagsmith-only`. `--flagsmith-only` creates **only** the Flagsmith feature for a flag that is **already code-wired** (already in `RUNTIME_FLAGS` + `.env.example` + Doppler). It skips the server.ts / `.env.example` / Doppler mutations **and** the "already appears in server.ts" exit-1 precheck (which would otherwise fire precisely because the flag is already wired). Use it to back-fill the Flagsmith feature for a flag that shipped its code wiring in an earlier PR, before scoping it per-org with `soleur:flag-set-role <flag> <env> on --org <orgId>`. ## Prerequisites - Doppler authed with access to `soleur` configs `dev`, `prd`, `cli_ops`. - Worktree of the soleur repo (script edits files in `apps/web-platform/`). - `curl` + `python3` on PATH. ## Procedure The agent runs only the preview: ```bash bash "${CLAUDE_PLUGIN_ROOT}/skills/flag-create/scripts/create.sh" <flag-name> \ [--description "..."] [--dev-on] [--prd-on] --dry-run ``` ## The write is the one typed-`yes` handoff (ADR-249) The write path asks for a typed `yes` through the operator-script library's TTY acknowledgement, because the audit row this script writes records only that kind of acknowledgement (ADR-249); moving it to the staged agent-run approval gate that generated operator scripts use is tracked in #9387. It has no skip variable and no flag. An agent's shell has no TTY, so a write run there stops with exit `64` and `SOLEUR_BOOTSTRAP_INPUT_REQUIRED` on stdout, before any credential is fetched. Exit `64` is a refusal, never a success. The agent therefore does every other step itself (reads, the dry-run preview, preflight, verification) and hands over only the typed-`yes` write: 1. Runs the script with `--dry-run` and shows the preview. That mode needs no TTY and makes no writes. 2. Prints the exact write command below, in a fenced block, for the operator to type at a terminal prompt (Warp), the one step an agent cannot take. It replaces `<WORKTREE>` with the absolute path of the worktree that holds this change (`git rev-parse --show-toplevel`) and `<ARGS>` with `<flag-name>` plus any `--description`, `--dev-on`, `--prd-on` or `--flagsmith-only` the operator chose, without `--dry-run`. It never prints a `${CLAUDE_PLUGIN_ROOT}` or repo-relative form. The script also edits repo files in the directory it runs from, so an operator running it from the main checkout or another worktree would land the code wiring in the wrong tree while Flagsmith and Doppler change. 3. Does not run the command, and does not run it through Claude Code's `!` prefix either (whether that gives the command a TTY is unmeasured, ADR-249). The printed command is an undone operator step under `wg-block-pr-ready-on-undeferred-operator-steps`: record it where the pipeline tracks operator steps, and do not mark a PR ready until the operator says it ran. <!-- operator-write-command --> ```bash cd <WORKTREE> && bash <WORKTREE>/plugins/soleur/skills/flag-create/scripts/create.sh <ARGS> ``` The operator types `yes` at the prompt. Any other answer stops the script with exit `1` and `SOLEUR_BOOTSTRAP_ABORTED stage=ack`, before anything is written. The script (full in [scripts/create.sh](./scripts/create.sh)): 1. **Validate name** — kebab-case, not already in `RUNTIME_FLAGS`, not in `ENV_FLAGS`, not already a feature in Flagsmith. 2. **Print proposed mutations** (4 lines): - Flagsmith: create feature `<name>` with default_enabled=false. - server.ts: append `"<name>": "FLAG_<NAME>"` to `RUNTIME_FLAGS`. - .env.example: insert `FLAG_<NAME>=0` under the runtime flags section. - Doppler dev + prd: `FLAG_<NAME>=<0|1>` (mirrors prd-segment initial state). 3. **Operator ack** — a typed `yes` at the TTY prompt (no flag skips it; no TTY means exit `64` before any credential fetch). 4. **Create feature in Flagsmith** — `POST /api/v1/projects/39082/features/` with `name`, `description`, `default_enabled: false`. 5. **Apply segment overrides** (if `--dev-on` or `--prd-on`) — for each env, push a v2 version with `feature_states_to_create` setting the target segment's enabled state to true. Same pattern as `soleur:flag-set-role`. 6. **Edit files** — append `RUNTIME_FLAGS` entry; append `FLAG_<NAME>=<0|1>` to `.env.example`. 7. **Mirror Doppler** — `doppler secrets set FLAG_<NAME>=<0|1>` in dev + prd. 8. **Print next-action hint** — "commit `server.ts` + `.env.example` so the resolution path can read the new flag". ## Exit codes - `0` — success / dry-run. - `1` — name validation failure, or the operator did not type `yes` (`SOLEUR_BOOTSTRAP_ABORTED stage=ack`; nothing written). - `2` — prerequisite missing, or a `--description` value that starts with `--`. - `3` — Flagsmith API error. - `4` — file edit or audit append failed. - `5` — Doppler write failed. - `64` — a write run with no TTY (`SOLEUR_BOOTSTRAP_INPUT_REQUIRED`): hand the command to the operator (above). ## Sharp edges - The skill edits source files. Run from a clean worktree where you're prepared to commit the changes. Skill prints the `git diff` after. - New flag's identifier sent to Flagsmith uses the same `role:<role>` cache pattern as existing flags (see `apps/web-platform/lib/feature-flags/server.ts`); no per-user behavior. - This skill does NOT create a CI verify probe or test for the new flag. Add one in the PR that consumes the flag. ## Cross-references - ADR: `knowledge-base/engineering/architecture/decisions/ADR-038-feature-flags-flagsmith.md` - Sibling skills (flag CRUD set): `soleur:flag-set-role` (Update), `soleur:flag-list` (Read), `soleur:flag-delete` (Delete), `soleur:user-set-role`
View on GitHub