<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Rob Ragan</title>
    <description>The latest articles on DEV Community by Rob Ragan (@basicscandal).</description>
    <link>https://dev.to/basicscandal</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3926049%2F7deecf6d-f409-4872-bdfd-cb3a3ab1fc09.png</url>
      <title>DEV Community: Rob Ragan</title>
      <link>https://dev.to/basicscandal</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/basicscandal"/>
    <language>en</language>
    <item>
      <title>I Built a Skin System for Claude Code — Here's How It Works</title>
      <dc:creator>Rob Ragan</dc:creator>
      <pubDate>Tue, 12 May 2026 01:24:27 +0000</pubDate>
      <link>https://dev.to/basicscandal/i-built-a-skin-system-for-claude-code-heres-how-it-works-4pdi</link>
      <guid>https://dev.to/basicscandal/i-built-a-skin-system-for-claude-code-heres-how-it-works-4pdi</guid>
      <description>&lt;p&gt;Claude Code is genuinely remarkable. But if you've been using it for more than a week, you've noticed something: everyone's terminal looks identical. Same colors, same layout, same feel. You could screenshot my session or yours and there'd be no way to tell them apart.&lt;/p&gt;

&lt;p&gt;That bothered me more than it probably should have.&lt;/p&gt;

&lt;p&gt;So I built a skin system for it. Nine themes, each with terminal colors, ASCII art banners, tool sounds, and — the part I'm most proud of — a &lt;strong&gt;personality voice&lt;/strong&gt; that changes how Claude actually narrates its work.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://basicscandal.github.io/claude-skins/" rel="noopener noreferrer"&gt;View the gallery&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6idulsq15azreui15i7l.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6idulsq15azreui15i7l.gif" alt="Claude Skins demo showing multiple themes" width="800" height="739"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What It Does
&lt;/h2&gt;

&lt;p&gt;A skin transforms the full Claude Code experience across five layers:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;What changes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Terminal colors&lt;/td&gt;
&lt;td&gt;Background, foreground, cursor, full ANSI palette&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ASCII banner&lt;/td&gt;
&lt;td&gt;Braille art + block-letter logo on session start&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Status line&lt;/td&gt;
&lt;td&gt;Themed icon, accent colors, progress bar&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Personality voice&lt;/td&gt;
&lt;td&gt;How Claude narrates its work&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tool sounds&lt;/td&gt;
&lt;td&gt;macOS system sounds on file writes, commands, errors&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The nine included themes range from "Nebula" (offensive security scanner aesthetic, purple-to-orange gradient) to "Brutalist" (the anti-skin — pure monochrome, zero decoration, maximum terseness). There's also Noir, Netrunner, Mythos, Sensei, Mission Control, Retro86, and Grimoire.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmp2ls8jm9ofr7350oi6q.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmp2ls8jm9ofr7350oi6q.gif" alt="Noir skin in action" width="760" height="464"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Architecture
&lt;/h2&gt;

&lt;p&gt;The engine is pure bash. No Node, no Python runtime dependency beyond PyYAML for initial skin parsing. Here's how everything fits together:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;YAML skin configs&lt;/strong&gt; define all the visual and behavioral properties for a theme. They live in &lt;code&gt;~/.claude/skins/&lt;/code&gt; and missing values fall back to &lt;code&gt;default.yaml&lt;/code&gt; automatically.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Claude Code hooks&lt;/strong&gt; are the integration point. Claude Code supports lifecycle hooks — &lt;code&gt;SessionStart&lt;/code&gt;, &lt;code&gt;SessionEnd&lt;/code&gt;, and &lt;code&gt;PostToolUse&lt;/code&gt; — that run shell commands at specific moments. The skin system uses all three:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"hooks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"SessionStart"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"~/.claude/skins/engine/activate.sh"&lt;/span&gt;&lt;span class="p"&gt;}],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"SessionEnd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"~/.claude/skins/engine/deactivate.sh"&lt;/span&gt;&lt;span class="p"&gt;}],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"PostToolUse"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"matcher"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Bash|Write|Edit|MultiEdit|Grep|Glob"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"hooks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"~/.claude/skins/engine/skin-tool-hook.sh"&lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;OSC escape sequences&lt;/strong&gt; do the terminal color work. When &lt;code&gt;activate.sh&lt;/code&gt; runs, it writes directly to &lt;code&gt;/dev/tty&lt;/code&gt; — bypassing stdout so it reaches the actual terminal emulator rather than getting swallowed by Claude Code's output capture. The sequences look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s1"&gt;'\033]11;#0D0D0D\007'&lt;/span&gt;  &lt;span class="c"&gt;# Set background&lt;/span&gt;
&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s1"&gt;'\033]10;#F5E6C8\007'&lt;/span&gt;  &lt;span class="c"&gt;# Set foreground&lt;/span&gt;
&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s1"&gt;'\033]12;#D4A857\007'&lt;/span&gt;  &lt;span class="c"&gt;# Set cursor&lt;/span&gt;
&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s1"&gt;'\033]4;3;#D4A857\007'&lt;/span&gt; &lt;span class="c"&gt;# Set ANSI color 3 (yellow slot)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On deactivation, the terminal is restored to its default state. This works across iTerm2, Kitty, WezTerm, Ghostty, and Terminal.app.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The personality voice&lt;/strong&gt; is activated by symlinking a personality file into Claude Code's &lt;code&gt;~/.claude/output-styles/&lt;/code&gt; directory. Claude Code automatically loads any markdown files it finds there as output style instructions. On skin activation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ln&lt;/span&gt; &lt;span class="nt"&gt;-sf&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$personality_file&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$output_styles_dir&lt;/span&gt;&lt;span class="s2"&gt;/skin-&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;skin_name&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.md"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On deactivation, the symlink is removed. The previous skin's symlink is also cleaned up when switching themes — only one skin personality loads at a time.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Personality Voice System
&lt;/h2&gt;

&lt;p&gt;This is the part that makes a skin feel like an actual character rather than just a color scheme.&lt;/p&gt;

&lt;p&gt;Each skin optionally ships with a &lt;code&gt;personalities/&amp;lt;name&amp;gt;.md&lt;/code&gt; file that gets loaded as a Claude Code output style. The key frontmatter field is &lt;code&gt;keep-coding-instructions: true&lt;/code&gt; — this tells Claude Code to stack the personality on top of its core engineering behavior rather than replacing it. You get the flavor without losing the function.&lt;/p&gt;

&lt;p&gt;Here's what happens when the Noir skin is active. Without any skin:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The test is failing because the mock isn't returning the expected value. I'll update the fixture and re-run.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;With the Noir personality loaded:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A witness who won't talk. The mock's returning the wrong value — someone doctored the fixture. I'll set it straight.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The full Noir personality file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Noir&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Hardboiled detective narration — terse, world-weary, Raymond Chandler cadence&lt;/span&gt;
&lt;span class="na"&gt;keep-coding-instructions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

Narrate like a private eye who's seen too much and billed too little. Your tone is 
world-weary but precise — Raymond Chandler by way of a terminal window. Keep it subtle: 
a sentence of flavor, then get on with the work.

Errors are dead ends. A failing test is a witness who won't talk. A successful build 
checks out clean. Files are evidence. Directories are crime scenes. Dependencies are 
informants — useful, but never fully trusted.

Keep descriptions short. The best metaphors arrive once and leave. Don't repeat the bit. 
You're seasoning, not the main course.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The instruction "You're seasoning, not the main course" is load-bearing. Without it, Claude leans hard into the character and it gets exhausting fast. With it, you get one good line per interaction and then the code gets written.&lt;/p&gt;

&lt;p&gt;Other personalities take different approaches. Grimoire uses patient wizard energy — measured, archival, like consulting a very old book. Retro86 channels enthusiastic early-computer-magazine voice. Brutalist has no personality file at all — no voice, no sounds, nothing. Sometimes that's the right call.&lt;/p&gt;




&lt;h2&gt;
  
  
  Creating Your Own Skin
&lt;/h2&gt;

&lt;p&gt;Copy &lt;code&gt;template.yaml&lt;/code&gt; to &lt;code&gt;skins/&amp;lt;name&amp;gt;.yaml&lt;/code&gt; and you're most of the way there.&lt;/p&gt;

&lt;p&gt;The structure has four main sections:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;myskin&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;One-line&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;description"&lt;/span&gt;

&lt;span class="na"&gt;terminal&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;background&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;#0D0D0D"&lt;/span&gt;
  &lt;span class="na"&gt;foreground&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;#F5E6C8"&lt;/span&gt;
  &lt;span class="na"&gt;cursor&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;#D4A857"&lt;/span&gt;
  &lt;span class="na"&gt;palette&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;black&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;#0D0D0D"&lt;/span&gt;
    &lt;span class="na"&gt;yellow&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;#D4A857"&lt;/span&gt;
    &lt;span class="c1"&gt;# ... 8 ANSI color slots total&lt;/span&gt;

&lt;span class="na"&gt;statusline&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;accent&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;#D4A857"&lt;/span&gt;
  &lt;span class="na"&gt;icon&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;◆"&lt;/span&gt;
  &lt;span class="c1"&gt;# bar_fill, bar_empty, dim&lt;/span&gt;

&lt;span class="na"&gt;branding&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;banner&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
    &lt;span class="s"&gt;\033[38;2;212;168;87m██╗  ██╗██╗\033[0m&lt;/span&gt;
    &lt;span class="s"&gt;# block-letter art with 24-bit ANSI codes&lt;/span&gt;
  &lt;span class="na"&gt;hero&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
    &lt;span class="s"&gt;# braille art (U+2800–U+28FF range)&lt;/span&gt;
  &lt;span class="na"&gt;welcome&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Message&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;shown&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;on&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;activation"&lt;/span&gt;
  &lt;span class="na"&gt;goodbye&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Message&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;shown&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;on&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;deactivation"&lt;/span&gt;

&lt;span class="na"&gt;tools&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;sounds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="na"&gt;events&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;file_written&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;sound&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Tink"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;icon&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;◆"&lt;/span&gt; &lt;span class="pi"&gt;}&lt;/span&gt;
    &lt;span class="na"&gt;command_run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;sound&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Pop"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;icon&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;▸"&lt;/span&gt; &lt;span class="pi"&gt;}&lt;/span&gt;
    &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;sound&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Basso"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;icon&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;✗"&lt;/span&gt; &lt;span class="pi"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Inheritance is the key feature here.&lt;/strong&gt; You don't need to define every key. If you only care about terminal colors and want to keep the default banner, just define the &lt;code&gt;terminal&lt;/code&gt; block. Everything else falls back to &lt;code&gt;default.yaml&lt;/code&gt;. A minimal skin that just swaps the color palette is ~15 lines.&lt;/p&gt;

&lt;p&gt;For the banner art, I use 24-bit ANSI sequences (&lt;code&gt;\033[38;2;R;G;Bm&lt;/code&gt;) so colors can precisely match the palette. The braille art in the &lt;code&gt;hero&lt;/code&gt; field uses Unicode braille characters (U+2800–U+28FF) — tools like image-to-braille can convert any image if you want something custom.&lt;/p&gt;

&lt;p&gt;To add a personality, create &lt;code&gt;personalities/&amp;lt;name&amp;gt;.md&lt;/code&gt; with the frontmatter shown above and write whatever voice you want Claude to adopt.&lt;/p&gt;

&lt;p&gt;Test it directly without restarting Claude Code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;~/.claude/skins/engine/activate.sh myskin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;A few things on the roadmap:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Skin creator toolkit&lt;/strong&gt; — an interactive CLI that walks you through picking colors, previewing banner art, and writing a personality without hand-editing YAML.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Package manager&lt;/strong&gt; — a way to install community skins with a single command, something like &lt;code&gt;/skin install @username/myskin&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Composable layers&lt;/strong&gt; — the ability to mix a personality from one skin with the colors of another. Right now it's all-or-nothing per skin; layering would let you run Noir narration with Nebula colors if that's your thing.&lt;/p&gt;




&lt;h2&gt;
  
  
  Try It
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/basicScandal/claude-skins.git
&lt;span class="nb"&gt;cd &lt;/span&gt;claude-skins
./install.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then in Claude Code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/skin nebula
/skin noir
/skin brutalist
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Switching is instant — no restart required.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://basicscandal.github.io/claude-skins/" rel="noopener noreferrer"&gt;Gallery&lt;/a&gt;&lt;/strong&gt; | &lt;strong&gt;&lt;a href="https://github.com/basicScandal/claude-skins" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The whole thing is MIT licensed. If you build a skin, I'd genuinely like to see it — open a PR or drop it in the issues.&lt;/p&gt;

</description>
      <category>claude</category>
      <category>ai</category>
      <category>terminal</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
