Claude-skill-registry add-global
Create a reactive global variable that derives from atoms with subscription support
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/add-global" ~/.claude/skills/majiayu000-claude-skill-registry-add-global && rm -rf "$T"
manifest:
skills/data/add-global/SKILL.mdsource content
Add Global Skill
Usage
/add-global <globalName>
Step 1: Ask Questions
1. Global Purpose
What derived state does this global provide? Brief description:
2. Source Atoms
Which atoms does this global derive from? (List atom names from src/atoms/) Examples: myInventoryAtom, myGardenAtom, weatherAtom
3. Derivation Logic
How is the global value computed from atoms? A) Simple merge - Combine fields from multiple atoms B) Transformation - Transform/filter atom data C) Aggregation - Compute stats/totals from atoms D) Complex - Multiple transformations
4. Update Sensitivity
Should subscribers react to every atom change? A) Yes - Every change triggers update B) No - Only meaningful changes (use subscribeStable)
5. Public API
Expose in window.Gemini.Globals? A) Yes B) No - Internal only
Step 2: Create Global File
Create src/globals/variables/<globalName>.ts
src/globals/variables/<globalName>.tsimport { createReactiveGlobal } from '../core/reactive'; import { Store } from '../../atoms'; import type { GlobalVariable, Unsubscribe } from '../core/types'; // ───────────────────────────────────────────────────────────────────────────── // Types // ───────────────────────────────────────────────────────────────────────────── export interface <GlobalName> { // Derived fields field1: string; field2: number; } // ───────────────────────────────────────────────────────────────────────────── // Derivation // ───────────────────────────────────────────────────────────────────────────── async function derive<GlobalName>(): Promise<<GlobalName>> { const atom1 = await Store.select('sourceAtom1'); const atom2 = await Store.select('sourceAtom2'); return { field1: atom1?.value ?? 'default', field2: atom2?.count ?? 0, }; } // ───────────────────────────────────────────────────────────────────────────── // Reactive Global // ───────────────────────────────────────────────────────────────────────────── const <globalName>Global = createReactiveGlobal<<GlobalName>>({ name: '<globalName>', atomKeys: ['sourceAtom1', 'sourceAtom2'], // Atoms to watch derive: derive<GlobalName>, }); // ───────────────────────────────────────────────────────────────────────────── // Public API // ───────────────────────────────────────────────────────────────────────────── let instance: GlobalVariable<<GlobalName>> | null = null; export function get<GlobalName>(): GlobalVariable<<GlobalName>> { if (!instance) { instance = <globalName>Global; } return instance; }
Step 3: Register
In src/globals/index.ts
src/globals/index.tsexport { get<GlobalName> } from './variables/<globalName>'; export type { <GlobalName> } from './variables/<globalName>';
In src/api/index.ts
(if public)
src/api/index.tsimport { get<GlobalName> } from '../globals'; Globals: { // ... existing <globalName>: get<GlobalName>(), }
Step 4: Validate
Structure
- File created in
src/globals/variables/<name>.ts - Type interface defined
- Derivation function implemented
-
with correctcreateReactiveGlobal()atomKeys - Lazy singleton getter exported
API
-
returns current valueget() -
receives all updatessubscribe(callback) -
receives meaningful updates onlysubscribeStable(callback) -
is idempotentdestroy()
Registration
- Exported from
src/globals/index.ts - Exposed in
(if public)src/api/index.ts
Usage Patterns
Basic subscription
const global = get<GlobalName>(); // Get current value const value = global.get(); // Subscribe to all changes const unsub = global.subscribe((value) => { console.log('Updated:', value); }); // Cleanup unsub();
Stable subscription (less frequent)
const unsub = global.subscribeStable((value) => { // Only fires on meaningful changes updateUI(value); });
In components/features
const cleanups: (() => void)[] = []; function start(): void { const unsub = get<GlobalName>().subscribe((value) => { onValueChange(value); }); cleanups.push(unsub); } function stop(): void { cleanups.forEach(fn => fn()); cleanups.length = 0; }
References
- Rules:
.claude/rules/state/globals.md - Existing globals:
src/globals/variables/ - Core:
src/globals/core/