From kinoa-dashboard
A thin, self-contained CLI over the Kinoa **feature-settings** admin API
How this skill is triggered — by the user, by Claude, or both
Slash command
/kinoa-dashboard:kinoa-dashboard-feature-settingsThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
A thin, self-contained CLI over the Kinoa **feature-settings** admin API
A thin, self-contained CLI over the Kinoa feature-settings admin API
(dashboard.kinoa.io/featuresettingsapi), plus the one public runtime read on
gate.kinoa.io/featureset. Every subcommand makes one HTTP call and prints one JSON
object: { http_status, ok, response | request_body, …context }. HTTP errors are
serialized, never raised — so the caller can branch on ok/http_status.
This skill holds no workflow logic. It's the admin surface that
kinoa-sync-feature-settings-integration (Phase 5) delegates to. It's also handy
on its own for one-off admin tasks ("create a schema", "publish that config",
"check what player X resolves").
Feature settings stack up in a fixed shape — internalize it before touching the commands, because every argument follows from it:
SCHEMA (typed columns, status DRAFT→ACTIVE)
└─ VERSION (version "1", "2", … — newest = largest number; has tableFields[])
SETTING (key + name, binds ONE schema by schemaId; no version, no status)
└─ CONFIGURATION (data rows for ONE schema version; lifecycle DRAFT→IN_REVIEW→SCHEDULED→ACTIVE)
At runtime the app asks for a setting key + a schema version number
and gets back the matching configuration's data. So the chain to a working
runtime read is: create+publish a schema → create a setting on it → create a
configuration (bound to a version), load its data, publish it → fetch by key.
| Surface | Host | Auth |
|---|---|---|
Admin (every subcommand except get-config) | dashboard.kinoa.io/featuresettingsapi | Authorization: Bearer + Game + Game-Id |
Runtime (get-config only) | gate.kinoa.io/featureset | game: <game_secret> (no bearer) |
get-config deliberately uses the public game-secret auth because it exercises
the exact path the shipped application uses. Never emit bearer-carrying code into
an application — that's an admin token.
The helper auto-loads ~/.kinoa/session.env. Run /kinoa-init first. A 401
from an admin call means the session token expired (~24h) — re-run /kinoa-init
with a fresh token.
python "${CLAUDE_SKILL_DIR}/kinoa_dashboard_feature_settings.py" <subcommand> [args]
| Command | Call | Notes |
|---|---|---|
list-schemas [--rows N] | GET /schemas | summaries |
active-schemas-meta | GET /schemas/active/meta | id+name of ACTIVE schemas — use to let a user pick |
get-schema --schema-id ID | GET /schemas/{id} | full record incl. versions[].tableFields |
latest-version --schema-id ID | derived | prints {schema_version_id, version} — the newest version (max numeric version); this is what a configuration binds to |
create-schema … | POST /schemas | creates a DRAFT; see below |
publish-schema --schema-id ID | POST /schemas/{id}/publish | DRAFT → ACTIVE |
Creating a schema — two forms:
SchemaDto produced by
kinoa-csv-schema-infer into --body-file or stdin.
python .../kinoa_csv_schema_infer.py infer --csv boosters.csv --name BoostersConfig \
| python .../kinoa_dashboard_feature_settings.py create-schema
--name plus a tableFields array. order,
level (default 1), and isRequired (default true) are filled in for you.
python .../kinoa_dashboard_feature_settings.py create-schema --name BoostersConfig \
--fields-json '[{"name":"id","type":"integer"},{"name":"label","type":"string"}]'
Column types: integer, number, long, boolean, string, long_string, bundle_key, date, enumeration, version, object.
| Command | Call | Notes |
|---|---|---|
list-settings [--rows N] | GET /settings | |
get-setting --setting-id ID | GET /settings/{id} | |
create-setting --key K --name N --schema-id ID [--description D] | POST /settings | key is the runtime lookup key (e.g. BoostersConfig); the setting holds only schemaId — no version, no status |
| Command | Call | Notes |
|---|---|---|
list-configs --setting-id ID | GET /settings/{id}/configurations | |
get-configuration --config-id ID | GET /configurations/{id} | |
create-config --setting-id ID --schema-id ID --schema-version-id ID --name N [--default] [--priority N] | POST /configurations | creates a DRAFT with no data; auto-builds the required tableColumns (one per schema field) and sends status DRAFT; --default makes it resolve for any player; ids come from get-schema / latest-version |
import-config-data --config-id ID --csv PATH | PUT /configurations/{id}/import | multipart CSV upload; header row must match the schema field names |
submit-config --config-id ID | PATCH … status→IN_REVIEW | required before publish — lifecycle is DRAFT → IN_REVIEW → SCHEDULED |
mark-config-default --config-id ID | PATCH …/mark-as-default | promotes an already-published (SCHEDULED/ACTIVE/PAUSED) config to default; rejects a DRAFT — for a fresh config use create-config --default instead |
publish-config --config-id ID | POST …/publish | IN_REVIEW → SCHEDULED (then auto-ACTIVE once the start time passes; visible at runtime after a short propagation lag) |
add-test-players --config-id ID --player-id ID … | POST …/test-players | let specific players resolve a not-yet-public config |
test-config --config-id ID --player-id ID | GET …/test/{playerId} | admin-side resolve (data + filters), no runtime needed |
delete-config --config-id ID | DELETE /configurations/{id} |
| Command | Call | Notes |
|---|---|---|
get-config --setting-key K --player-id ID --version V [--checksum VAL ...] [--checksum-only] [--include-filters] [--get-default] | POST gate.kinoa.io/featureset/features-configurations | the real runtime call; --version is effectively required; response settings[].status is OK / KEY_NOT_FOUND / VERSION_NOT_FOUND / DEFAULT_NOT_FOUND, plus a checksum. getDefault is false in normal use (omit --get-default). Checksum caching: pass the checksum(s) the client holds via --checksum; an unchanged config returns status OK with data: null (same checksum); a changed one returns fresh data + a new checksum — the client caches on data:null. |
Stand up a working config and confirm a player resolves it:
H="${CLAUDE_SKILL_DIR}/kinoa_dashboard_feature_settings.py"
# 1. schema (DRAFT → ACTIVE)
python "$H" create-schema --name BoostersConfig --fields-json '[{"name":"id","type":"integer"},{"name":"reward","type":"number"}]'
python "$H" publish-schema --schema-id <SCHEMA_ID>
# 2. binding + version
python "$H" create-setting --key BoostersConfig --name "Boosters" --schema-id <SCHEMA_ID>
python "$H" latest-version --schema-id <SCHEMA_ID> # → schema_version_id, version
# 3. configuration: create (default) → load data → submit → publish
python "$H" create-config --setting-id <SETTING_ID> --schema-id <SCHEMA_ID> --schema-version-id <VER_ID> --name "v1 defaults" --default
python "$H" import-config-data --config-id <CONFIG_ID> --csv boosters.csv
python "$H" submit-config --config-id <CONFIG_ID> # DRAFT → IN_REVIEW
python "$H" publish-config --config-id <CONFIG_ID> # IN_REVIEW → SCHEDULED → ACTIVE
# 4. verify exactly as the app would (allow a few seconds / retry — the runtime caches briefly)
python "$H" get-config --setting-key BoostersConfig --version 1 --player-id <PLAYER_ID>
# 4b. checksum delta — pass the checksum from step 4; unchanged settings come back with data:null
python "$H" get-config --setting-key BoostersConfig --version 1 --player-id <PLAYER_ID> --checksum <checksum>
Lifecycle that the chain encodes (learned the hard way, validated live):
schema DRAFT→ACTIVE (publish-schema); configuration DRAFT→IN_REVIEW
(submit-config)→SCHEDULED (publish-config)→ACTIVE (auto, once start time passes).
A config must carry one tableColumn per schema field (handled by create-config),
and either be --default or carry segmentation to leave DRAFT. The runtime read
requires the version; expect a brief cache lag before a freshly-published config
resolves.
ok.2 with a kinoa-init hint._load_session_env/_request/… by
design) so it installs in isolation. Don't extract a shared module.npx claudepluginhub kinoa-labs-ltd/integration-skills --plugin kinoa-dashboardGuides creation, editing, and verification of skills for AI coding agents using test-driven development with subagent scenarios. Use when authoring or debugging skills.