Skip to content
Back to skills

New Setting

ASecurity

Guided workflow for adding a new user setting or global setting to JellyRock. Walks the canonical recipe from docs/dev/new-user-setting.md (pick the bucket, add to settings/settings.json, wire JellyfinUserSettings, surface in the settings UI, write a registry migration if the schema changes, write tests, regenerate the settings docs). Stops at each step to verify and gives the user the relevant file paths. Use when adding a new toggle / dropdown / numeric setting that the user can change in t...

  • 45 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added September 20, 2026
toolsbashnodeapi

Works with

  • api

Security analysis

A100/100

Scanned October 5, 2026

npx -y skills add jellyrock/jellyrock --skill new-setting --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of New Setting?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for New Setting
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/jellyrock-new-setting/badge)](https://www.skillsdirectory.com/skills/jellyrock-new-setting)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: new-setting
description: Guided workflow for adding a new user setting or global setting to JellyRock. Walks the canonical recipe from docs/dev/new-user-setting.md (pick the bucket, add to settings/settings.json, wire JellyfinUserSettings, surface in the settings UI, write a registry migration if the schema changes, write tests, regenerate the settings docs). Stops at each step to verify and gives the user the relevant file paths. Use when adding a new toggle / dropdown / numeric setting that the user can change in the JellyRock Settings screen.
model: sonnet
effort: low
---

# /new-setting — guided workflow

Wraps [`docs/dev/new-user-setting.md`](../../../docs/dev/new-user-setting.md) as a step-by-step. The doc is the source of truth — this skill is a launcher that ensures none of the steps get skipped.

## Step 0 — Confirm a setting is the right answer

JellyRock has three types of "settings"-shaped state. Make sure you're adding the right one:

1. **User Settings** — registry per-user, managed by JellyRock. Stored under the user's session-keyed registry section. Examples: playback preferences, UI choices.
2. **Global Settings** — registry per-device, applies to all users on this Roku. Examples: developer mode, debug flags.
3. **User Configuration** — server-authoritative from Jellyfin API. **NEVER** stored in JellyRock's registry. Read live from `m.global.user`.

If the value is server-authoritative (anything Jellyfin already tracks per-user), STOP — don't add it as a setting. Read it from `m.global.user` directly. Only proceed if the user controls the value from inside JellyRock.

## Step 1 — Pick the bucket (User vs Global)

User Settings ⇔ "this is a personal preference and changes per signed-in user." Global Settings ⇔ "this applies to the device and survives user changes." If unsure, default to User Settings — it's the more common case.

## Step 2 — Add the default to `settings/settings.json`

This is the **single source of truth** for defaults. Defaults are loaded at app startup via `user.settings.SaveDefaults()`. Defaults are NEVER written to registry — only user-set values are persisted.

Pick a stable kebab-case key. Match the JSON shape of nearby existing entries (type, default value, optional description). Read [`settings/settings.json`](../../../settings/settings.json) before editing to confirm the shape.

## Step 3 — Wire it into `JellyfinUserSettings`

Edit [`components/data/jellyfin/JellyfinUserSettings.xml`](../../../components/data/jellyfin/JellyfinUserSettings.xml) and the `.bs` sibling. The XML declares the field's type (`assocarray` / `node` / `nodearray` / `string` / `int` / `float` / `boolean`); the BS reads the default from `settings.json` and exposes the field for downstream observation.

`user.Login()` ([`source/utils/session.bs`](../../../source/utils/session.bs)) reads the user's registry section at login and applies every key that names a field on this node through `user.settings.Save()`, which converts it to the field's type. Loading needs no code: confirm only that the field `id` matches the `settings.json` name, because that id is the registry key.

## Step 4 — Surface in the Settings UI (if user-facing)

Add the toggle / dropdown / numeric input to the relevant Settings screen under [`components/`](../../../components/) (typically a screen under `components/data/` or a Settings-prefixed component). Use the existing settings controls as templates — don't invent a new control unless none of the existing shapes fit.

## Step 5 — Write a registry migration (only if schema changes)

If you're RENAMING an existing setting key, REMOVING one, or changing the data shape, write a registry migration via the [`/new-migration`](../new-migration/SKILL.md) skill. Brand-new settings DO NOT need a migration — they get their default from `settings.json` for users who haven't changed them.

## Step 6 — Write tests

Per [`docs/dev/unit-tests.md`](../../../docs/dev/unit-tests.md): registry-touching tests use `test-*` section names so they don't pollute production data. Set `m.needsRegistrySetup = true` in the suite's setup so the BaseTestSuite clears `test-*` between tests.

Tests should cover: default value loaded correctly when registry is empty; saved value persists across the autoSync mechanism; setting affects the downstream behavior it's supposed to.

## Step 7 — Regenerate the settings docs

```bash
npm run docs:settings
```

This generates [`docs/user/app-settings.md`](../../../docs/user/app-settings.md) from `settings.json`. Run it after editing `settings.json`. The pre-push hook also runs it, but better to land it in the same commit as the new setting.

## Step 8 — Verify end-to-end

```bash
npm run lint:bs
npm run validate
npm run lint:docs
```

Then on hardware (if reachable):

```bash
npm run test:tdd
```

If hardware isn't reachable, say so explicitly — don't claim "tested" without a green run.

## Common pitfalls (from the doc)

- **Forgetting to add the default** to `settings.json`. Without it, the field reads a Roku-default (empty string / 0) and downstream code may misbehave.
- **Writing the default to registry**. Defaults belong only in `settings.json`. Writing them to registry breaks the "saved-vs-default" distinction the migration system relies on.
- **Not setting `m.needsRegistrySetup = true`** in test suites that touch the registry. Cross-test leakage will produce flaky failures.
- **Committing without running `npm run docs:settings`**. The hook auto-runs but committing it explicitly makes the diff cleaner.

## When NOT to use

- The value is server-authoritative — read from `m.global.user` directly.
- You're renaming an existing setting — use `/new-migration` for the rename, not `/new-setting`.
- You're adding a developer-only debug flag — see [`docs/dev/debug-flags.md`](../../../docs/dev/debug-flags.md); flags are different infrastructure.

## Sub-agent invocation

To invoke from a sub-agent: parent passes `Read .claude/skills/new-setting/SKILL.md and follow the steps for adding $ARGUMENTS=<setting-name>; surface each step's file paths and the diffs to apply but do NOT commit` in the Task prompt.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…