course-video
Skill1 starsChanged 10 days agoMITView on GitHub
Build a branded, captioned course video with HyperFrames. It has two modes. (A) Enhance an existing screen recording (.mp4) with a branded title card, word-by-word captions, fly-in note panels and on-screen code highlights. (B) Build a narrated lecture from a module's slide deck + per-slide voiceover.md: TTS narration, each slide a scene, word-by-word captions, in-context line-by-line code highlighting. Drafts use free local Kokoro (af_heart @ 0.95); finals can use your own ElevenLabs voice via env vars once the script is locked. Brand (palette, fonts, pronunciations) comes from a brand folder (example-brand/ included). Bundles the pronunciation rules and the code-animation + keyword-emphasis conventions so videos stay consistent without re-explaining. Use whenever the user wants to caption, brand, enhance, narrate, or add notes/code-highlights to a course recording, lecture, walkthrough, slide deck, or demo, with phrasings like "make a lecture video from these slides", "narrate this module", "add CC and notes to this recording", "fly in notes about the commands", or "enhance this walkthrough", even when they don't say "HyperFrames". Also trims the front off a recording before enhancing.
- Reads credentials
In this repository14 other files it gives its agents.
- ai-text-detectorSkill
- code-demo-videoSkill
- humanizerSkill
- react-router-reviewerSkill
- roastSkill
- security-scannerSkill
- seo-auditSkill
- sonarqube-triageSkill
- storm-researchSkill
- talking-head-motionSkill
- technical-reviewSkill
- update-docsSkill
- watchSkill
- wire-secretsSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
16 rules. About 0 are common, 5 are distinctive, and 11 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈5
Distinctive · estimate
This author's own choices. Worth a look.
11
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 51
All brand values live in one folder holding brand.json (plus a human-readable brand.yaml, a PRONUNCIATIONS.md, and optionally a logo and …
- Very specific: line 90
If the narration is an AI voice (including a clone of the instructor), say so where the video is published (brand.json …
- Very specific: line 96
Use the humanizer skill if it's installed.
- Very specific: line 148
Keep one folder per video (e.g.
- Very specific: line 172
Use small.en only for English audio.
- Very specific: line 232
Add a HIGHLIGHTS array alongside NOTES in build-data.mjs.
- Very specific: line 237
Keep markers visibility:hidden when inactive so the WCAG checker skips them (the same rule as notes).
- Distinctive: line 247
If the instructor edits the code while talking, re-check the rectangle, because the line may have moved.
- Very specific: line 248
Verify every highlight from rendered frames (step 5): it must sit on the right region and clear on out.
- Distinctive: line 270
Read the PNGs and check that:
- Distinctive: line 296
Use this when there's no recording, just a module's slide deck and a per-slide script.
- Very specific: line 328
Run voiceover-source.md through the humanizer pass (see *Humanize generated narration & scripts* above) and save the cleaned result back to …
- Very specific: line 335
Default (af_heart): node build-narration.mjs writes narration/sceneNN.txt with all conventions applied (respellings, keyword emphasis, …
- Very specific: line 343
Default: for each scene, run npx hyperframes tts narration/sceneNN.txt --voice af_heart --speed 0.95 -o assets/audio/sceneNN.wav.
- Distinctive: line 375
Verify frames: the title, a code slide with a highlight and a caption word, and the wrap.
- Distinctive: line 389
Always regenerate before rendering.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Course Video Builder
Produce a branded, captioned course video. In Mode A the raw screen recording stays the predominant full-frame layer. On top of it go a short branded title card, word-by-word closed captions transcribed from the audio, and fly-in note panels. The panels surface relevant detail (a command's syntax and flags, or a concept or step) exactly when the instructor talks about it.
This is a proven pipeline. Per video you mostly edit one config block. The default flow is proof-first: render a short segment, confirm the look, then render the whole thing.
Below, <SKILL_DIR> is this skill's folder (e.g. ~/.claude/skills/course-video).
Core principle: point the student's eyes. Any time a segment is just code on screen while the instructor talks through the logic, put a visible highlight on the exact thing being discussed. Don't make students hunt the page for what "this line" or "that variable" refers to. Draw a box, border or tint around it, synced to when it's spoken, and remove it when the topic moves on. A simple highlight or border is enough. Step through the code line by line when that helps. See Highlight the code being discussed.
Two production modes: pick by what you're handed
- Mode A: enhance a screen recording. You have a
walkthrough.mp4. Overlay a branded title card, word-by-word captions, fly-in note panels and code highlights on top of it. This is the Workflow section below. - Mode B: lecture from a slide deck + voiceover. There's no recording. You have a module's slide deck (HTML
pages with
class="slide", styled by a sharedslides.css) and a per-slidevoiceover.md. Generate TTS narration, render each slide as a scene, and add word-by-word captions and in-context code highlighting. See Mode B, or batch it withengine/build-module.sh(engine/README.md).
Both modes share the Brand, Voice and Conventions sections below.
Brand (both modes)
All brand values live in one folder holding brand.json (plus a human-readable brand.yaml, a
PRONUNCIATIONS.md, and optionally a logo and captions.css). The skill ships example-brand/, a neutral
placeholder ("Example College", slate and blue). To use your own:
- Copy
example-brand/somewhere outside the skill (e.g.~/brands/my-school/), then editbrand.json:brand.nameandurlvideo.palette(primary, primary_dark, accent, accent_bright, canvas, term_green)fonts.displayandfonts.monovideo.voice.respellings(whole-word TTS fixes for your terms)- optionally a logo (
example-brand/LOGO.md)
- Point the skill at it:
export COURSE_VIDEO_BRAND=~/brands/my-school. You can also passengine/build-module.sh --brand <dir>, or copybrand.jsoninto the project (Mode A: next tobuild-data.mjs; Mode B: the project root).
What reads the brand:
- Mode A's
build-data.mjswrites the palette and fonts into theBRANDblock ofindex.html. - Mode B's
build-lecture.mjstakes the highlight colour, caption box and caption font from it. build-narration.mjsapplies the respellings.
Without a brand file, the neutral built-in palette applies.
Voice (both modes)
- Drafts: Kokoro
af_heart@ speed 0.95 (free, local, unlimited). Build and review every video in Kokoro first:npx hyperframes tts <file> --voice af_heart --speed 0.95 -o <out>.wav. Finals (optional): your ElevenLabs voice, once the script is locked. Run
engine/_scripts/tts-eleven.mjs(copied into each Mode B project). It reads everything from the environment:ELEVENLABS_API_KEYandELEVENLABS_VOICE_ID: required, never stored in the skill or the project.- optional
ELEVENLABS_MODEL_ID(defaulteleven_turbo_v2_5),ELEVENLABS_STABILITY(0.5),ELEVENLABS_SIMILARITY(0.75) andELEVENLABS_SPEED(0.92).
It refuses to spend quota until the script passes the words gate (
references/script-review.md;SKIP_SCRIPT_REVIEW="<reason>"overrides it, and the override is logged). Mind your plan's monthly character quota: check the remaining characters before voicing a batch, and keep the wav files, because re-generating spends them again.- When using ElevenLabs, build the narration in clean mode (
VOICE=eleven node build-narration.mjs). That skips the Kokoro respellings ("pie-thawn" would be read literally) and applies the ElevenLabs-specific ones and the quote emphasis instead. Everything downstream (transcribe, captions, code highlight, render) is the same as on the af_heart path. - If the narration is an AI voice (including a clone of the instructor), say so where the video is published
(
brand.jsonvideo.voice.disclosure).
Humanize generated narration & scripts (both modes): REQUIRED
Any narration or script text you generate for a video must go through a humanizer pass before it's used.
Use the humanizer skill if it's installed; otherwise do a careful manual pass for AI tells (see the lint in
references/script-review.md). TTS faithfully speaks whatever AI-isms you leave in, so an un-humanized script
produces a video that sounds AI-written. Steer it toward a spoken, read-aloud teaching voice: this is narration
spoken to students, not an article.
- What to humanize: prose you wrote. In Mode B that's
voiceover-source.md. In Mode A it's any note-cardsummary/bulletsand title text you authored. - What NOT to humanize: text transcribed from a real recording. Mode A captions are the instructor's actual spoken words, so leave them exactly as transcribed.
- Order matters: humanize the RAW script first, before the mechanical passes. The Kokoro respellings and
keyword emphasis (
applyConventions()inbuild-narration.mjs) and the Whisper caption transcript come after. So the flow is: write the script → humanizer pass →build-narration.mjs→ TTS. Humanizing after the respellings would rewrite "pie-thawn" and the quote/dash emphasis into nonsense. - Preserve structure: the humanizer must keep every
### Slide Nheader and the one-block-per-slide split intact. Re-run the count check afterwards: the headers must still equal the slide count.
Conventions (both modes): applied automatically by the generators
These are baked into the lecture generators, so you don't re-explain them per video:
Pronunciations (
<brand>/PRONUNCIATIONS.md; the example is example-brand/PRONUNCIATIONS.md). Kokoro respellings:- Python → pie-thawn, Kali → kal-ee, elif → el-if, str → stir,
re→ "R E", OOP → "O O P", VS Code, macOS - decimals → "…point…", IP/dotted addresses → "…dot…"
- plus the brand's own
respellings
These are Kokoro-only and skipped for ElevenLabs, which has its own short list. Add new module-specific terms as you confirm them.
- Python → pie-thawn, Kali → kal-ee, elif → el-if, str → stir,
references/VIDEO-CONVENTIONS.md covers keyword/operator emphasis:
for→ em-dashes;while/break/if/etc. → quotes; dashes when defining an operator.
It also covers in-context code highlighting: a line-by-line highlight bar synced to the narration plus an accent window glow on the code block, both cleared once the narration moves on. Palette: accent = "look here", green = correct/result, red = error/untaken branch. Inactive overlays stay
visibility:hidden.
engine/_scripts/build-narration.mjs (applyConventions()) encodes the pronunciations, keyword emphasis and
IP/decimal handling. engine/_scripts/build-lecture.mjs encodes the 2× slide scaling, captions, code
highlights, entrance animations, and the float-safe timing cascade.
Prerequisites
node≥ 18,ffmpeg, andnpx hyperframes(the CLI fetches itself). Runnpx hyperframes doctorif unsure.- Captions use local Whisper (free, offline, word-level timestamps) via
hyperframes transcribe. - Kokoro runs in Python through
hyperframes tts. Ifkokoro-onnxis installed in a non-default Python, exportHYPERFRAMES_PYTHON=/path/to/python3. - Renders are CPU/GPU and memory heavy. On a low-RAM machine, use
--workers 2and warn the user thatvalidate/inspectmay hit a 10s page-load timeout on large (>250MB) source videos (see Gotchas).
Workflow (Mode A: enhance a screen recording)
1 · Scaffold the project
Keep one folder per video (e.g. ~/Videos/course-videos/<course>/mNN-rec-<topic>/), not next to the source
video, so there's one copy of everything:
mkdir -p <video-folder> && cd <video-folder>
npx --yes hyperframes@0.8.164 init build --example blank --non-interactive
mv "<source>.mp4" build/walkthrough.mp4 # move, don't copy: this is the one raw copy (keep mp4s out of git)
cp <SKILL_DIR>/assets/index.html build/index.html
cp <SKILL_DIR>/assets/build-data.mjs build/build-data.mjs
cp <SKILL_DIR>/assets/design.md build/design.md
cp "${COURSE_VIDEO_BRAND:-<SKILL_DIR>/example-brand}/brand.json" build/brand.json
mkdir -p build/fonts # put the brand's .woff2 files here (Inter-Variable.woff2 + JetBrainsMono-Variable.woff2 for the example)The brand values (palette, fonts) come from build/brand.json, which build-data.mjs writes into
index.html. The example brand uses Inter and JetBrains Mono (both SIL OFL; download them from Google Fonts).
2 · Transcribe the audio (word-level)
cd build
npx hyperframes transcribe walkthrough.mp4 --model small.enUse small.en only for English audio. For another language, use --model small --language <code>; the .en
models translate non-English audio instead of transcribing it. The output is transcript.json, a flat array of
{text,start,end} words. It drives both the captions and the note timing.
3 · Study the content and find real timings ⚠ most important step
Recordings improvise and diverge from any written script, and Whisper mangles short command tokens. So derive the notes and their timing from the actual transcript, not a lesson plan. Probe it without dumping it into context, with a small node script:
// probe.mjs — node probe.mjs (inside build/)
import { readFileSync } from "node:fs";
const TRIM = 0; // set to your front-trim seconds
const W = JSON.parse(readFileSync("transcript.json", "utf8")).filter(w => w.start >= TRIM);
const off=[]; let p=0, parts=[]; for(const w of W){off.push(p);parts.push(w.text);p+=w.text.length+1;}
const txt = parts.join(" ");
const at = ci => { let i=0; for(let k=0;k<off.length;k++){ if(off[k]<=ci) i=k; else break;} return i; };
const fmt = t => `${Math.floor(t/60)}:${(t%60).toFixed(1).padStart(4,"0")}`;
const probe = re => { const m=txt.match(re); return m ? `${fmt(W[at(m.index)].start)} …${txt.slice(Math.max(0,m.index-20),m.index+44).replace(/\s+/g," ")}…` : "NONE"; };
for (const [k,re] of Object.entries({ /* candidate terms → regexes */ })) console.log(k.padEnd(12), probe(re));For each candidate note, confirm three things: it's actually covered, when the teaching starts, and how the term was transcribed. A companion guide or lesson plan tells you what to look for, but trust the transcript for timing. See references/note-kb-guide.md for trigger-design rules.
4 · Fill in the config block of build-data.mjs
Edit only the CONFIG block:
TITLE_CARD:kicker(e.g. course code · course name),title,subtitle,prompt(""hides the mono line),ghost(big watermark text, e.g. the course code;""for none),logo(an image inbuild/;""for none).TRIM_START: seconds to drop off the front (0 = none).PROOF: a{start,len}window that contains a couple of notes for the look check.NOTES: one entry per fly-in card. It's a unified schema in which every field is optional excepttrigger+title.- Command cards use
code:true+subtitle+syntax/example/rows. - Concept cards use
kicker+bullets.
The full field list and trigger guidance are in references/note-kb-guide.md.
- Command cards use
4b · Highlight the code being discussed
Whenever a stretch of the recording is code on screen + the instructor narrating the logic, don't leave students scanning for "this line" or "that variable". Put a marker on the exact spot, synced to when it's spoken, and clear it when the discussion moves on. This is the single biggest comprehension win for code segments, so treat it as the default, not an extra.
What a marker is (cheapest first; a simple one is plenty):
- a border/box drawn around the line(s), block, function, or token being discussed;
- a soft highlight tint (an accent or green wash) over that region;
- an arrow / underline pointing at a single token (a variable, an operator, a flag);
- a moving highlight that steps line by line when the instructor walks through execution order. Advance it
on each "and then…", and dim lines that were skipped (e.g. an untaken
ifbranch). Use this when the flow is the point, not just one line.
How it's built in this pipeline. A marker is just another timed overlay, the same mechanism as the fly-in note panels: a positioned, semi-transparent element over the recording, shown and hidden on the transcript clock.
- Add a
HIGHLIGHTSarray alongsideNOTESinbuild-data.mjs. Each entry is{ trigger, atLine|box, style: "border"|"tint"|"arrow", out }, with the rectangle positioned over the code region in the recording. - The code lives inside the recorded video, so you must eyeball the pixel rectangle from a representative
frame (
ffmpeg -ss <t> -i walkthrough.mp4 -frames:v 1), then place the overlay there. - Keep markers
visibility:hiddenwhen inactive so the WCAG checker skips them (the same rule as notes). - Trigger and verify the timing from the transcript exactly as for notes (step 3). The highlight should land as the instructor says it, not before.
Guidance:
- One marker at a time per idea; don't light up the whole screen. Move or replace it as the topic moves.
- Match the brand palette: accent for "look here", green for "this is correct/the result", red only for an error or skip.
- A border or tint is enough for a held explanation. Save the line-by-line step for genuine execution walk-throughs.
- If the instructor edits the code while talking, re-check the rectangle, because the line may have moved.
- Verify every highlight from rendered frames (step 5): it must sit on the right region and clear on
out.
Authoring code-execution highlights from scratch (not over a recording)? If the
hyperframesskill is installed, itsreferences/css-patterns.mdcovers seek-safe marker sweeps, circles, underlines and a moving line-highlight bar pattern.
5 · Proof: generate, validate, render a short segment
node build-data.mjs proof # writes data.js, bakes timing + brand into index.html; prints the note map
npx hyperframes lint # must be clean
npx hyperframes validate # WCAG/console check (may time out on huge videos — see Gotchas)
npx hyperframes inspect --at <title,note1,note2,...> # layout overflow check at hero frames
npx hyperframes render --output renders/proof.mp4 --quality standard --workers 3Then verify by extracting frames (don't trust "it rendered") and show the user:
mkdir -p frames && for t in 2 <note-times>; do ffmpeg -loglevel error -y -ss $t -i renders/proof.mp4 -frames:v 1 frames/p_$t.png; doneRead the PNGs and check that:
- the title card is correct,
- notes fly in synced to the terminal or screen,
- captions paint on word by word,
- panels are gone when inactive.
Get the user's OK, or iterate on NOTES and styling.
6 · Full render
node build-data.mjs full
npx hyperframes render --output renders/<Name>.mp4 --quality standard --workers 3
mkdir -p ../final && mv renders/<Name>.mp4 ../final/<folder-name>.mp4Verify the output:
ffprobe -show_entries format=durationshould equal thetotalthatbuild-data.mjsprinted.Capturing frame N/Nshould matchtotal × fps.- Spot-check frames at a few note times. If you trimmed, also check a frame just after the title card to confirm the recording starts at the trim point.
Report the final path, duration and size.
Mode B — Build a lecture from a slide deck + voiceover
Use this when there's no recording, just a module's slide deck and a per-slide script.
- Inputs: a deck HTML (top-level
<div class="slide …">pages on a sharedslides.css) and avoiceover.mdwith one### Slide N(or## Slide N) block per deck page. - Output:
final/mNN-lecture.mp4in the project. Don't copy MP4s into the course repo; record the video in something like aVIDEOS.mdthere instead.
The discipline is the same proof-first one, and the two generators do the heavy lifting, so each module is mostly
copy-config-run. For a whole module or course, engine/build-module.sh runs B1–B7 in one go
(engine/README.md). The steps below are the by-hand version.
B1 · Scaffold
Make a project folder (e.g. <out>/<course>/mNN-lecture/), then:
npx --yes hyperframes init mNN-lecture --example blank --non-interactive- copy the deck's
slides.cssand any images it links →assets/ - copy this skill's scripts from
engine/_scripts/→ project root:build-narration.mjs,build-lecture.mjs,tts-eleven.mjs,patch-captions.mjs - copy
engine/qa/→qa/lib/(the words gate for ElevenLabs) - copy your brand's
brand.json→ project root - copy the deck →
deck.htmland the voiceover →voiceover-source.md(with## Slideheaders turned into### Slide) - copy the voiceover into the project's
script.mdtoo. It's the frozen record of what the video says, because the coursevoiceover.mdkeeps changing after the render.
B2 · Count check (stop if mismatch)
The number of top-level .slide pages in deck.html must equal the number of ### Slide blocks in
voiceover-source.md. If they differ, reconcile them before going further. Drift here misaligns every scene
downstream.
B2b · Humanize the script (required, before narration)
Run voiceover-source.md through the humanizer pass (see Humanize generated narration & scripts above) and save
the cleaned result back to voiceover-source.md. Do this before B3, because build-narration.mjs applies
the Kokoro respellings and has to run on the already-humanized text. The humanizer must keep every ### Slide N
header. Re-run the B2 count check afterwards to confirm the block count still matches the deck.
B3 · Narration
- Default (af_heart):
node build-narration.mjswritesnarration/sceneNN.txtwith all conventions applied (respellings, keyword emphasis, IP/decimal handling, brand respellings). It logs any leftoverpythonor bare decimals as a self-check. - ElevenLabs (only if asked):
VOICE=eleven node build-narration.mjsgives clean/raw text with no Kokoro respellings.
B4 · TTS
- Default: for each scene, run
npx hyperframes tts narration/sceneNN.txt --voice af_heart --speed 0.95 -o assets/audio/sceneNN.wav. - ElevenLabs (only if asked):
ELEVENLABS_API_KEY=… ELEVENLABS_VOICE_ID=… node tts-eleven.mjs. It loops over everynarration/sceneNN.txt, sends each to ElevenLabs, and converts the result withffmpegtoassets/audio/sceneNN.wav(44.1 kHz mono). It checks the words gate first.
B5 · Transcribe (word-level, for captions)
For each clip, run npx hyperframes transcribe assets/audio/sceneNN.wav --model small.en, then move the emitted
transcript.json to narration/sceneNN.json. Whisper usually re-hears the respellings as the real word, so
captions stay correct.
ElevenLabs only: B5b · Patch captions. A few ElevenLabs respellings don't survive Whisper: ell-iff is heard
as "LIF". Whisper also mis-hears a couple of tokens even when the audio is right (dict → "dick", kwargs →
"quarks"). Run node patch-captions.mjs after transcribe and before build-lecture. It rewrites those
mis-heard caption tokens back to the correct on-screen spelling and leaves the audio untouched. Quote-emphasized
keywords and operators need no patch, because quotes change only prosody.
B6 · Generate the composition
node build-lecture.mjs writes index.html + assets/cc-data.js:
- each
.slidewrapped in a scene andtransform: scale(2)(origin top-left) to fill 1920×1080 crisply, - word-by-word captions,
- in-context code-line highlights and window glow in the brand accent,
- entrance animations,
- the float-safe timing cascade (
scene data-duration = sceneDur − 0.01, to avoid overlap).
B7 · Lint, render, place
npx hyperframes lint must be clean. Then run
npx hyperframes render --output renders/mNN-lecture.mp4 --quality standard --workers 2.
- Verify frames: the title, a code slide with a highlight and a caption word, and the wrap.
- Confirm that the
ffprobeduration ≈ the sum of the clip durations. - Move the file to the project's
final/mNN-lecture.mp4.
Why the 2× scale: a typical deck stylesheet is a print stylesheet (e.g. 254 mm × 142.9 mm ≈ 960×540 px). Wrapping each
.slideand scaling it 2× fills 1080p while keeping every element addressable for the entrance animations, code highlights and caption sync. If your deck is already 1920×1080, drop the scale inbuild-lecture.mjs(.slide-wrap).
Gotchas (learned the hard way)
- Render duration comes from STATIC html attributes, read at compile time before any runtime JS.
build-data.mjsbakesdata-duration/data-media-startintoindex.htmlfor this reason. If a "full" render comes out the length of the proof, you ranrenderwithout re-runningnode build-data.mjs fullfirst. Always regenerate before rendering. - Detection is windowed. A command spoken in a trimmed or discarded section can't claim a card. That's good,
but it means triggers must match something said after
TRIM_START. - Whisper ≠ the script. Trigger on distinctive spoken phrases, not literal tokens. Verify every note's timestamp.
- Fonts: self-host the brand fonts. Copy the
.woff2files into the build'sfonts/; the template's@font-facerules load them. Arial/Arimo are not in the renderer's font list and will warn and fall back. - Contrast false-positives: note and caption text sits over the video, so inactive overlays are
visibility:hiddenand the WCAG checker skips them. Keep that; don't switch to opacity-only. - Big videos + low RAM:
validate/inspectload the page in headless Chrome with a 10s navigation timeout. A 290MB video under memory pressure can exceed it.lintstill works, so verify the layout from rendered frames instead, and consider--workers 2. - Always verify by looking at rendered frames, never by the render exit code alone.
- Guardrails (from
brand.json): no student names, IDs or grades on screen. Code shown on screen must run for real first.
Regenerating / tweaking later
Everything is regenerable. Edit the NOTES or title in build-data.mjs, run node build-data.mjs full, and
re-render. A brand change only needs build/brand.json replaced and build-data.mjs re-run. The composition
HTML and design.md rarely need touching.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

