一键导入
flipbook-config-and-flags
Configuration axes (env vars, injected globals, build channels/targets, user settings); adding new config; re-verification commands
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Configuration axes (env vars, injected globals, build channels/targets, user settings); adding new config; re-verification commands
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Special workflow for testing FlipbookCore changes through the StudioPlugins Flipbook plugin. Use only when: the engineer explicitly asks to verify changes through StudioPlugins, mentions StudioPlugins with local FlipbookCore rotriever builds, or says the StudioPlugins watcher is already running.
Load-bearing design decisions, invariants, and known weak points of Flipbook's architecture. Use when understanding or extending system design, debugging architectural mismatches, or validating deep changes (PR
Understanding the Flipbook build system from environment setup through final deployment; source→rbxm pipeline with deep focus on Darklua require transformation, environment globals injection, and dead-code elimination
Classification, gating, and review discipline for Flipbook changes: branch/PR workflow, version gating, CI gates, change-type decision table, community-first and telemetry-privacy doctrine, and the non-negotiables with their historical incidents. Use when authoring a PR, reviewing change control, understanding release requirements, or evaluating whether a change is safe to merge.
Community-first doctrine, telemetry/privacy posture, ecosystem positioning vs web Storybook and UI Labs, and claim discipline for Flipbook features
Symptom→solution runbook for Flipbook runtime issues: stale plugin behavior, stories not hot-reloading, controls re-rendering excessively, crashes on state mutations, test failures, missing logs, plugin freezing or opening uninvited. Use when you encounter a runtime symptom and need to isolate root cause quickly via discriminating experiments.
| name | flipbook-config-and-flags |
| description | Configuration axes (env vars, injected globals, build channels/targets, user settings); adding new config; re-verification commands |
| type | knowledge |
This skill catalogs every configuration axis in Flipbook: environment variables, build-time injected globals, build channels and targets, user-settable preferences, and structural constants. Use this to understand how the system is configured, extend it with new options, or debug drift.
When to use: extending Flipbook's configuration surface; understanding how a setting flows from env → code → runtime behavior; verifying that config options are documented correctly.
When NOT to use: for build pipeline mechanics, use flipbook-build-and-toolchain; for telemetry strategy specifics, use flipbook-config-and-flags (sections 5 and A); for release workflows, use flipbook-release-and-operations.
All environment variables are read from .env (loaded by lute run build); .env.template is the public contract.
| Name | Purpose | Default | Values | Prod vs Experimental | Where Used |
|---|---|---|---|---|---|
LOG_LEVEL | Min verbosity for logs sent to Help > Logs | info | trace, debug, info, warn, error, fatal | Production | workspace/flipbook-core/src/logger.luau sets MinLevelFilter(_G.LOG_LEVEL) |
ENABLE_OUTPUT_LOGGING | Route logs to Studio Output window (in addition to Logs view) | false | true or false | Production | workspace/flipbook-core/src/logger.luau checks _G.ENABLE_OUTPUT_LOGGING == "true" |
BASE_URL | Telemetry and feedback backend endpoint | https://apis.flipbooklabs.com | Valid HTTPS URL | Production | workspace/flipbook-core/src/Telemetry/fireEventAsync.luau, workspace/flipbook-core/src/Feedback/postFeedbackAsync.luau build both requests to {_G.BASE_URL}/<endpoint> |
ROBLOX_API_KEY | Open Cloud API key for cloud Jest test execution | (required, no default) | Valid Open Cloud key | Production | .lute/build.luau calls dotenv.config(); used by test runner only |
ROBLOX_UNIT_TESTING_PLACE_ID | Test place for cloud Jest execution | 123506190725771 | Roblox place ID | Production | .env.template (grep ROBLOX_UNIT_TESTING_PLACE_ID=) and build system |
ROBLOX_UNIT_TESTING_UNIVERSE_ID | Test universe for cloud Jest execution | 6599100156 | Roblox universe ID | Production | .env.template (grep ROBLOX_UNIT_TESTING_UNIVERSE_ID=) and build system |
Verification: grep -r "process.env\|dotenv" .lute .env.template.
Darklua (.darklua.json) injects these 8 globals from environment at build time, followed by dead-code elimination so channel-gated branches are pruned:
| Name | Purpose | Source | Read Locations | Prod vs Experimental |
|---|---|---|---|---|
BUILD_VERSION | Package version from wally.toml | wally.toml (grep package.version); read in .lute/build.luau (grep readWallyManifestAsync) | workspace/flipbook-core/src/About/BuildInfo.luau (grep BUILD_INFO), workspace/flipbook-core/src/About/AboutView.luau (grep BuildInfo), workspace/flipbook-core/src/Telemetry/fireEventAsync.luau (grep buildVersion) | Production |
BUILD_CHANNEL | Normalized channel name: "production" | "beta" | "development" | .lute/build.luau (grep BUILD_CHANNEL = if channel) maps channel arg to enum | workspace/flipbook-core/src/FlipbookApp.luau (grep showDevBadge), workspace/flipbook-core/src/Telemetry/fireEventAsync.luau (grep buildChannel) | Production |
BUILD_HASH | Short commit hash (git rev-parse --short HEAD) | .lute/build.luau (grep getCommitHash) | workspace/flipbook-core/src/About/BuildInfo.luau (grep BUILD_INFO), workspace/flipbook-core/src/Telemetry/fireEventAsync.luau (grep buildHash) | Production |
BUILD_TARGET | Build target: "roblox" | "rotriever" | .lute/build.luau (grep BUILD_TARGET = target) | workspace/flipbook-core/src/FlipbookApp.luau (grep showInternalBadge) | Production |
BASE_URL | Telemetry backend URL (from .env) | .lute/build.luau (grep BASE_URL = process.env.BASE_URL) reads process.env.BASE_URL | workspace/flipbook-core/src/Feedback/postFeedbackAsync.luau, workspace/flipbook-core/src/Telemetry/fireEventAsync.luau (both grep _G.BASE_URL) | Production |
LOG_LEVEL | Min log level (from .env) | .lute/build.luau (grep LOG_LEVEL = process.env.LOG_LEVEL) reads process.env.LOG_LEVEL | workspace/flipbook-core/src/logger.luau (grep MinLevelFilter) | Production |
ENABLE_OUTPUT_LOGGING | Output logging flag (from .env) | .darklua.json (grep ENABLE_OUTPUT_LOGGING) injected by Darklua into _G.ENABLE_OUTPUT_LOGGING; read from .env | workspace/flipbook-core/src/logger.luau (grep _G.ENABLE_OUTPUT_LOGGING == "true") | Production |
JEST_TEST_PATH_PATTERN | Test file filter (Jest testMatch pattern) | .lute/build.luau via --filter arg; injected by darklua for test builds only | Inlined in test Jest config (not directly grepped in src/) | Experimental — test builds only |
Verification: grep -r "inject_global_value" .darklua.json lists the 8 rules.
Determine which code is included in the binary. Passed via --channel flag to lute run build <subcommand>.
| Channel | Default? | What It Does | Dead-Code Stripping | Pruned Dirs | Pruned Files | Use Case |
|---|---|---|---|---|---|---|
dev | No | Keeps all sources: tests, stories, storybooks, code samples | No pruning | None | None | Local development; working on Flipbook itself |
beta | No | Full code (like dev) | No pruning | None | None | Beta releases (planned; not currently shipped) |
prod | Yes — default in .lute/build.luau (grep default = "prod") | Strips test artifacts and example code | Via compute_expression, remove_unused_if_branch | workspace/code-samples, workspace/example, workspace/template, workspace/test-runner (per project.luau grep prunedDirs) | *.spec.lua*, *.story.lua*, *.storybook.lua*, jest.config.lua* (per project.luau grep prunedFiles) | Production plugin releases |
Important: lute run build without --channel defaults to prod. Docs examples often show lute run build --channel dev to keep stories visible.
Determine the output platform and API surface. Passed via --target flag.
| Target | Default? | Platform | Build Output | Plugin Behavior | Use Case |
|---|---|---|---|---|---|
roblox | Yes (.lute/build.luau grep default = "roblox") | Roblox Studio plugin | build/<channel>/roblox/ → Flipbook.rbxm | Standard plugin; no internal APIs | Community releases |
rotriever | No | Roblox internal Rotriever registry | build/<channel>/rotriever/ → flipbook-core-rotriever/ package bundle | Uses internal Roblox APIs (_G.INTERNAL_BUILD_TARGET == BuildTarget.Rotriever badge shown in FlipbookApp.luau grep showInternalBadge) | Internal Roblox builds; not shipped to Creator Store |
Determine what gets built. Default is plugin.
| Subcommand | What It Builds | Output | Use Case |
|---|---|---|---|
plugin | Main Flipbook plugin binary | build/<channel>/<target>/Flipbook.rbxm (synced to Studio plugins dir or custom path) | Standard: lute run build or lute run build --channel dev |
workspace | Only flipbook-core rotriever package | build/<channel>/<target>/flipbook-core-rotriever/ | Package exports for internal consumption |
storybook | Test storybook place for deployment | build/flipbook-storybook.rbxl | For deploy-storybook CI workflow |
lute run build [subcommand] [options]
# Examples:
lute run build # prod plugin, roblox target, sync to Studio
lute run build --channel dev # dev plugin, keep stories/tests
lute run build --channel dev --watch # dev, auto-rebuild on changes
lute run build --channel dev --skip-reload # dev, don't reload in Studio
lute run build --target rotriever # rotriever target, prod channel
lute run build --target rotriever --clean # Full rebuild after dep changes
lute run build storybook # Build test storybook place
lute run build --output ~/custom.rbxm # Build to custom path
lute run build --filter "controls" # Test build with JEST_TEST_PATH_PATTERN="controls"
| Option | Alias | Type | Default | Purpose |
|---|---|---|---|---|
--channel | -c | dev|beta|prod | prod | See Channels table above |
--target | -t | roblox|rotriever | roblox | See Targets table above |
--watch | -w | flag | false | Incremental recompile on source changes |
--skip-reload | none | flag | false | Skip Studio plugin reload (only for path matching plugins dir) |
--clean | none | flag | false | Full rebuild; deletes cache |
--output | -o | path | ~/.config/Roblox/Plugins/Flipbook.rbxm (or Windows equivalent) | Custom build output path |
--filter | none | pattern | (none) | Test pattern; sets JEST_TEST_PATH_PATTERN for Jest |
Settings are persisted in the plugin's local storage (Studio plugin settings API) and read at runtime. Defined in workspace/flipbook-core/src/UserSettings/defaultSettings.luau.
| Name | Group | Type | Default | Values / Range | Description | Where Used |
|---|---|---|---|---|---|---|
rememberLastOpenedStory | Stories | boolean | true | true|false | Restore the last-viewed story on plugin open | workspace/flipbook-core/src/Storybook/useLastOpenedStory.luau (grep rememberLastOpenedStory) checks setting and skips restore if false |
theme | UI | dropdown | "system" | "system", "dark", "light" | UI theme: match Studio, force dark, or force light | workspace/flipbook-core/src/Storybook/StoryViewNavbar.luau (grep userSettings.theme) passes setting as current dropdown value |
sidebarWidth | UI | number | 260 px | 140–500 px (per constants.luau grep SIDEBAR_MIN_WIDTH|SIDEBAR_MAX_WIDTH) | Sidebar panel width, persisted across sessions | workspace/flipbook-core/src/FlipbookApp.luau (grep userSettings.sidebarWidth) sets initialSize UDim2 |
controlsHeight | UI | number | 200 px | 100–400 px (per constants.luau grep CONTROLS_MIN_HEIGHT|CONTROLS_MAX_HEIGHT) | Story controls panel height, persisted | workspace/flipbook-core/src/StoryControls/StoryControlsPanel.luau (grep userSettings.controlsHeight) sets panel initialSize UDim2 |
collectAnonymousUsageData | Telemetry | boolean | true | true|false | Opt in to anonymous usage metrics; user shown opt-in dialog on first open | workspace/flipbook-core/src/Telemetry/fireEventAsync.luau (grep collectAnonymousUsageData) returns early if false; prevents all telemetry collection |
Storage mechanism: workspace/flipbook-core/src/UserSettings/UserSettingsStore.luau wraps plugin settings API; persisted to plugin:GetSetting() and plugin:SetSetting().
Defined in workspace/flipbook-core/src/constants.luau. Not configurable by users but load-bearing for layout.
| Name | Value | Purpose |
|---|---|---|
STORY_NAME_PATTERN | "%.story$" | Pattern to detect story files (ModuleScript ending in .story) |
STORYBOOK_NAME_PATTERN | "%.storybook$" | Pattern to detect storybook files |
SIDEBAR_INITIAL_WIDTH | 260 px | Default sidebar width (matches user setting default) |
SIDEBAR_MIN_WIDTH | 140 px | Minimum sidebar width constraint |
SIDEBAR_MAX_WIDTH | 500 px | Maximum sidebar width constraint |
CONTROLS_INITIAL_HEIGHT | 200 px | Default controls panel height |
CONTROLS_MIN_HEIGHT | 100 px | Minimum controls panel height |
CONTROLS_MAX_HEIGHT | 400 px | Maximum controls panel height |
SPRING_CONFIG | { clamp = true, mass = 0.6, tension = 700 } | React Spring animation tuning |
FLIPBOOK_RUNTIME_TAG | "FlipbookRuntime" | Tag applied to runtime instances (for detection) |
FLIPBOOK_LOGO | "rbxassetid://76698965087351" | Asset ID of Flipbook logo |
Central repository for paths and semantic constants.
| Name | Value | Purpose |
|---|---|---|
PROD_CONFIG.prunedDirs | { workspace/code-samples, workspace/example, workspace/template, workspace/test-runner } | Directories stripped from prod builds via Darklua dead-code elimination (grep prunedDirs in project.luau) |
PROD_CONFIG.prunedFiles | { *.spec.lua*, *.story.lua*, *.storybook.lua*, jest.config.lua* } | File patterns stripped from prod builds (grep prunedFiles in project.luau) |
ROBLOX_STORYBOOK_UNIVERSE_ID | 10262009842 | Roblox universe ID for the public storybook deployment (deploy-storybook) |
ROBLOX_STORYBOOK_PLACE_ID | 139676401890813 | Roblox place ID for the public storybook deployment |
File: .luaurc
| Setting | Value | Purpose |
|---|---|---|
languageMode | "strict" | Luau strict type checking enabled for all source files |
aliases (8 total) | See below | Module path aliases for cleaner requires; used throughout codebase |
Aliases:
@lune → ~/.lune/.typedefs/0.9.4/ — Lune CLI typedefs@lint → ~/.lute/typedefs/1.0.0/lint — Selene lint types@lute → ~/.lute/typedefs/1.0.0/lute — Lute CLI types@std → ~/.lute/typedefs/1.0.0/std — Luau standard lib types@luaupkg → ./LuauPackages — Loom-managed packages@pkg → ./Packages — Wally-managed packages@rbxpkg → ./RobloxPackages — Roblox CLI packages@repo → . — Repo root (for project.luau)@scripts → ./.lute — Lute scripts@workspace → ./workspace — Workspace membersCreator Store asset metadata and environments.
| Asset | Environment | Type | Name | Model |
|---|---|---|---|---|
assets.prod | prod | Plugin | Flipbook | Flipbook.rbxm |
assets.dev | prod | Plugin | Flipbook (Dev) | Flipbook.rbxm |
assets.smoketest | prod | Plugin | Flipbook | Flipbook.rbxm |
Environments:
prod: Creator ID 1343930 (User), Universe 6599100156, Place 84837374448022Note: dev and smoketest also use environment = "prod" but are published to different asset IDs via CI workflow.
CLI tools pinned here; run rokit install to install all.
| Tool | Version | Purpose |
|---|---|---|
darklua | 0.17.1 | String require → Roblox require transform + dead-code elimination |
luau-lsp | 1.60.1 | IDE type server |
lune | 0.9.4 | Luau CLI runtime |
lute | 1.0.0 | Luau project runner (build system) |
roblox-packages | 0.5.0 | Flipbook Labs CLI tools |
rocale | 0.1.3 | Jest cloud runner |
rojo | 7.6.1 | Roblox project sync / packager |
selene | 0.30.1 | Linter |
stylua | 2.3.1 | Code formatter |
wally | 0.3.2 | Package manager |
wally-package-types | 1.5.1 | Wally type definitions |
Package manager dependencies.
Runtime:
Charm 0.11.0-rc.4 — Reactive state managementHighlighter 0.9.0 — Syntax highlightingLog 0.3.0 — Logging libraryLuauPolyfill 1.2.7 — JS polyfills for LuauModuleLoader 0.11.0 — Hot-reload module cache bypassReact 17.0.2 (jsdotlua) — React libraryReactCharm 0.4.0-rc.3 — Charm + React integrationReactRoblox 17.0.2 (jsdotlua) — React renderer for RobloxReactSpring 2.0.0 — Animation librarysha256 1.0.1 — HashingSift 0.0.8 — Table utilitiesStoryteller 1.12.0 — Story discovery/renderingt 3.0.0 — Type checkingDev:
Fusion 0.2.0 — Reactive UI library (stories only)Jest 3.10.0 (jsdotlua) — Test runnerJestGlobals 3.10.0 (jsdotlua) — Jest globalsRoact 1.4.4 — React-like library (stories only)Loom-managed (non-Wally) dependencies.
| Package | Source | Version |
|---|---|---|
flipbook-batteries | github.com/flipbook-labs/flipbook-batteries | v0.9.0 — Shared Lute utilities |
lute | github.com/luau-lang/lute | v1.0.0 — Build system |
dotenv | github.com/erlcx/lute-dotenv | v0.1.0 — Environment variable loader |
Deep dive into how dead-code stripping works for prod builds.
convert_require — Rewrite Luau string requires (require("@pkg/foo")) to Roblox property access (require(script.Parent.Foo)), using Rojo sourcemap at ./sourcemap-darklua.json.
inject_global_value — Inject 8 globals (see section 2); each rule maps an identifier to an environment variable.
Dead-code elimination (applied in order):
compute_expression — Simplify constant expressionsremove_unused_if_branch — Strip branches where condition is a constant (e.g., if _G.BUILD_CHANNEL == "production" then ... end becomes ... in prod)remove_unused_while — Strip while loops with constant false conditionfilter_after_early_return — Remove unreachable code after returnremove_nil_declaration — Strip assignments to nilremove_empty_do — Remove empty do ... end blocksThis means: if you gate code with if _G.BUILD_CHANNEL == "production" then, in prod builds that entire branch is the only one that remains, and in dev builds the gated-out code is completely stripped. This is how *.story.luau files disappear from prod.
Add to .env.template (public contract):
MY_NEW_VAR=default_value
# Brief description of what it controls
If runtime-needed: Add to .darklua.json:
{
"rule": "inject_global_value",
"identifier": "MY_NEW_VAR",
"env": "MY_NEW_VAR"
}
If build-time only: Read in .lute/build.luau via process.env.MY_NEW_VAR (no injection needed).
In code: Access as _G.MY_NEW_VAR (runtime) or process.env.MY_NEW_VAR (build time).
Document: Add a row to section 1 and 2 tables above; update re-verification commands.
Example: LOG_LEVEL is an env var injected globally; ROBLOX_API_KEY is build-time only (not injected).
Define in workspace/flipbook-core/src/UserSettings/defaultSettings.luau:
local myNewSetting: CheckboxSetting = {
name = "myNewSetting",
group = SettingGroup.UI, -- or Stories, or Telemetry
displayName = "My New Setting",
description = "What it does",
settingType = SettingType.Checkbox,
value = true, -- default
}
local settings = {
myNewSetting = myNewSetting,
-- ... rest
}
Export type: Update export type Settings = typeof(settings).
Access at runtime: Via UserSettingsStore.get().getStorage().myNewSetting.
UI: Settings panel auto-renders based on group and settingType; dropdown choices render from choices table.
Document: Add row to section 5 table; cite the file.
Example: collectAnonymousUsageData is a checkbox setting; theme is a dropdown.
Define in workspace/flipbook-core/src/constants.luau:
MY_NEW_CONSTANT = "value",
Use throughout code: local constants = require("@root/constants"); constants.MY_NEW_CONSTANT.
Document: Add row to section 6 table.
Example: SIDEBAR_INITIAL_WIDTH = 260.
Sentinel: Wrap code in if _G.BUILD_CHANNEL == BuildChannel.Production then ... end or similar.
Darklua strips automatically: Dead-code elimination removes non-matching branches.
Document in AGENTS.md or change control skill (not here).
Example: FlipbookApp.luau (grep showDevBadge\|showBetaBadge\|showInternalBadge) shows dev/beta/internal badges only in non-prod builds.
Add to project.luau return table:
MY_CONSTANT = "value",
Access in build scripts: local project = require("@repo/project"); project.MY_CONSTANT.
Document: Add row to section 7 table; cite usage.
Example: PROD_CONFIG.prunedDirs lists directories stripped from prod.
Run these periodically to catch drift (as of 2026-07-01):
# Section 1: Env vars in .env.template
grep "^[A-Z_]*=" .env.template | sort
# Section 2: Darklua injected globals
jq '.process[] | select(.rule == "inject_global_value") | .identifier' .darklua.json | sort
# Section 2 (detail): All places where _G. is used in source
grep -r "_G\." workspace/flipbook-core/src --include="*.luau" | grep -v "build/\|.spec\|.story" | wc -l
# Should be ~20+ (build globals read in logger, about, telemetry, feedback)
# Section 3: Build channels and targets (verify options in build.luau)
grep -A5 'channel == "dev" or channel == "beta"' .lute/build.luau
# Section 5: User settings defined
grep -E '^\s*(rememberLastOpenedStory|theme|sidebarWidth|controlsHeight|collectAnonymousUsageData)' workspace/flipbook-core/src/UserSettings/defaultSettings.luau
# Section 5: Settings reads in code
grep -r "userSettings\." workspace/flipbook-core/src --include="*.luau" | cut -d: -f2 | sort -u | head -20
# Section 6: Constants defined
grep "^[[:space:]]*[A-Z_]* =" workspace/flipbook-core/src/constants.luau
# Section 7: project.luau structure
grep -E '(PROD_CONFIG|STORYBOOK|ROBLOX)' project.luau
# Section 8: Luau aliases
jq '.aliases | keys[] as $k | "\($k): \(.[$k])"' .luaurc
# Section 9: rbxasset environments
grep "^\[assets\.\|^\[environments\." rbxasset.toml
# Section 10: Tool versions (rokit.toml)
grep -E "^[a-z-]+ =" rokit.toml
# Section 10: Wally deps
grep -E "^[A-Z][a-zA-Z]+ =" wally.toml | head -20
# Section 10: Loom deps
jq '.package.dependencies | keys[]' loom.config.luau
# Candidate issue: Check if ENABLE_OUTPUT_LOGGING is actually injected or if code is stale
grep "ENABLE_OUTPUT_LOGGING" .darklua.json
# (Should return the inject rule; if not, check logger.luau logic)
JEST_TEST_PATH_PATTERN drift: Passed via --filter to build, but not in .env.template. Verify it's documented in test runbook (see flipbook-validation-and-qa skill).
rbxasset.toml asset IDs: Asset IDs for dev (nightly 88523969718241) and smoketest versions live in CI, not in .toml. Sync with release workflow.
.env.template, .darklua.json, project.luau, .luaurc, workspace/flipbook-core/src/UserSettings/defaultSettings.luau, workspace/flipbook-core/src/constants.luau, rokit.toml, wally.toml, loom.config.luau, rbxasset.toml, and grepping _G. usage in source.