RepoDepot
Other

tweakcc

by Piebald-AI
Claude Code customization CLI — patches cli.js to add themes, toolsets, system prompts, and UI tweaks

tweakcc is a CLI tool that extensively customizes your Claude Code experience, enabling personalized system prompts, themes, and UI elements. It works by patching Claude Code's minified cli.js file, supporting both npm and native binary installations across all major OS. The tool also introduces new features like /toolset command, AGENTS.md support, and session memory unlock.

View on GitHub ↗
Key features
  • Customize all Claude Code system prompts and subagent models
  • Create custom toolsets accessible via the /toolset command
  • Apply custom themes, thinking verbs, and spinner animations
  • Unlock hidden session memory and add a /remember skill
  • Patch native Claude Code binaries on Windows, macOS, and Linux
Languages
TypeScript96%JavaScript4%Python0%
Top contributors
Topics
agenticanthropicbunclaude-codeclaude-code-nativeclaude-code-system-promptsclaude-code-themesclaude-code-uicommand-lineconfigurationcustomizationdeveloper-toolspersonalizationrefined-claude-codestylingsystem-promptsterminalthemestoken-countertweak

Check out Piebald

We've released Piebald, the ultimate agentic AI developer experience.
Download it and try it out for free! https://piebald.ai/

Join our Discord X

Scroll down for tweakcc. :point_down:

hero

tweakcc

tweakcc on npm Mentioned in Awesome Claude Code ClaudeLog - A comprehensive knowledge base for Claude.

tweakcc is a CLI tool that upgrades your Claude Code experience. Customize its system prompts, add custom themes, create toolsets, and personalize the UI. From the team behind Piebald.

Animated GIF demonstrating running `npx tweakcc`, creating a new theme, changing all of Claude Code's UI colors to purple, changing the thinking format from '<verb>ing...' to 'Claude is <verb>ing', changing the generating spinner style to a 50ms glow animation, applying the changes, running Claude, and using '/config' to switch to the new theme, and sending a message to see the new thinking verb format.

[!IMPORTANT] NEW in 4.0.0: tweakcc now has an API; use npm i tweakcc to add to your project and see API!

NEW in 4.0.0: You can now create custom patches via sandboxed scripts! Works with native installations. No need to fork tweakcc just to make a quick patch! See tweakcc adhoc-patch.

NEW in 4.0.0: You can also apply customizations from a remote URL to a config file. See Remote Config.

Also see tweakcc --restore, tweakcc unpack, and tweakcc repack.

[!NOTE] NEW: tweakcc 4.0.0 also introduces several new patches:

With tweakcc, you can

  • Customize all of Claude Code's system prompts (NEW: also see all of Claude Code's system prompts)
  • Create custom toolsets that can be used in Claude Code with the new /toolset command
  • Highlight custom patterns while you type in the CC input box with custom colors and styling, like how ultrathink used to be rainbow-highlighted.
  • Manually name sessions in Claude Code with /title my chat name or /rename (see our blog post for implementation details)
  • Create custom themes with a graphical HSL/RGB color picker
  • Add custom thinking verbs that will show while Claude's working
  • Create custom thinking spinner animations with different speeds and phases
  • Style the user messages in the chat history beyond the default plain gray text
  • Remove the ASCII border from the input box
  • Expand thinking blocks by default, so that you don't need to use the transcript (Ctrl+O) to see them
  • Configure which Claude model each subagent (Plan, Explore, and general-purpose) uses
  • Switch between table formats - Claude Code default, Unicode (┌─┬─┐), ASCII/markdown (|---|), Unicode without top/bottom borders.

tweakcc also

  • Fixes a bug where the spinner animation is frozen if you have the CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC environment variable set (#46)
  • Allows you to change the context limit (default: 200k tokens) used with models from custom Anthropic-compatible APIs with a new environment variable, CLAUDE_CODE_CONTEXT_LIMIT
  • Adds the opusplan[1m] model alias, combining Opus for planning with Sonnet's 1M context for execution—reducing "context anxiety" (#108)
  • Adds a message to Claude Code's startup banner indicating that you're running the patched version of CC (configurable)
  • Speeds up Claude Code startup by ~50% with non-blocking MCP connections and configurable parallel connection batch size (#406)

tweakcc supports Claude Code installed on Windows, macOS, and Linux, both native/binary installations and those installed via npm, yarn, pnpm, bun, Homebrew/Linuxbrew, nvm, fnm, n, volta, nvs, nodenv, and Nix (including NixOS and nix-darwin), as well as custom locations.

tweakcc supports Claude Code's native installation, which is a large platform-specific native executable containing the same minified/compiled JavaScript code from npm, just packaged up in a Bun binary. We support patching the native binary on macOS, Windows, and Linux, including ad-hoc signing on Apple Silicon, via node-lief, our Node.js bindings for LIEF (Library to Instrument Executables).

While tweakcc has a large library of built-in patches, you can create custom patches by using tweakcc's API. If you don't want to create an npm package, you can use tweakcc adhoc-patch, which applies a custom Node.js script to your default Claude Code installation. Because adhoc-patch supports running scripts from an HTTP URL, you can even host a script on a GitHub Gist or pastebin for easy distribution.

Run without installation:

$ npx tweakcc

# Or use pnpm:
$ pnpm dlx tweakcc

Table of contents

How it works

tweakcc works by patching Claude Code's minified cli.js file, reading customizations from ~/.tweakcc/config.json. For npm-based installations cli.js is modified directly, but for native installations it's extracted from the binary using node-lief, patched, and then the binary is repacked. When you update your Claude Code installation, your customizations will be overwritten, but they're remembered in your configuration file, so they can be reapplied by just running npx tweakcc --apply.

tweakcc is verified to work with Claude Code 2.1.62. In newer or earlier versions various patches might not work. However, if we have the system prompts for your version then system prompt patching is guaranteed to work with that version, even if it's significantly different from the verified CC version—the version number stated above is only relevant for the non-system-prompt patches. We get the latest system prompts within minutes of each new CC release, so unless you're using a CC version older than 2.0.14, your version is supported.

You can also create custom patches using tweakcc without having to fork it or open a PR. tweakcc adhoc-patch supports using custom scripts that work with native and npm-based installs and that automatically detect your Claude Code installation.

Remote Config

While tweakcc usually works by applying customizations from your local ~/.tweakcc/config.json, you can optionally pass the --config-url <http URL> flag when you use tweakcc --apply to have tweakcc fetch config from a remote URL and apply it to your local Claude Code installation. This is useful for testing someone else's config when shared via a Gist or pastebin, for example.

Example:

npx tweakcc@latest --apply --config-url https://gist.githubusercontent.com/bl-ue/27323f9bfd4c18aaab51cad11c1148dc/raw/b24b5fe08874ce50f4be6c093d9589d184f91a70/config.json

Your local config will not be overwritten; the remote config will be copied into your config.json under remoteConfig.settings.

CLI Commands

In addition to the interactive TUI (npx tweakcc) and the --apply flag, tweakcc provides three subcommands for advanced use: unpack, repack, and adhoc-patch.

unpack

Extract the embedded JavaScript from a native Claude Code binary and write it to a file. This is useful for inspecting Claude Code's source, writing custom patches, or making manual edits before repacking. Note that unpack only works with native/binary installations; it will error if pointed at an npm-based installation (cli.js), because it can already be read directly from disk. unpack takes the path to the JS file to write to, and an optional path to a native binary, which if omitted will default to the current installation.

npx tweakcc unpack <output-js-path> [binary-path]
repack

Read a JavaScript file and embed it back into a native Claude Code binary. This is the counterpart to unpack — after inspecting or modifying the extracted JS, use repack to write it back. Like unpack, this only works with native installations. repack takes a path to a JS file to read from, and an optional path to a native binary, which if omitted, as above, will default to the current installation.

npx tweakcc repack <input-js-path> [binary-path]

Example:

# Extract, edit, and repack
npx tweakcc unpack ./claude-code.js
# ... make your edits to claude-code.js ...
npx tweakcc repack ./claude-code.js
adhoc-patch

Apply a one-off or ad-hoc patch to a Claude Code installation without going through the tweakcc UI or config system. It supports three modes and works with both native and npm-based installations.

3 modes of patching are supported.

--string

A fixed/static old string is replaced with a fixed/static new string, analogous to grep -F.

  • By default, all instances of the old string are replaced, but you can use --index to specify a particular occurrence by 1-based index, e.g. --index 1 to replace only the first, --index 2 to replace only the second, etc.

--regex

All matches of a regular expression are replaced with a new string.

  • The new string can contain $D replacements, where D is the 0-based index of a group matched by the regular expression; $0 = the entire matched text, $1 = the first user-defined match group, etc.

  • The regular expression must begin and end with a forward slash in JavaScript style, e.g. /my.+regex/. An optional list of flags—characters from the set g, i, m, s, u, and y—may be appended after the last delimiting forward slash, e.g. /claude/ig

  • Like --string, --regex supports the use of --index to specify by index which occurrence to replace, without which all occurrences are replaced.

--script

This is the most powerful option. A short snippet of JavaScript code running in Node.js takes the JavaScript content of the CC installation as input and returns the entire input, modified as output.

  • Security: The script is run in a sandboxed/isolated node child process with the --experimental-permission option to prevent the script from using file system and network APIs. This option requires that you have Node.js 20+ installed and on your PATH. Due to this sandboxing, scripts themselves (including those downloaded from HTTP URLs) are safe to run without prior review; however, because the scripts are patching Claude Code, which is an executable, it's technically possible for a script to patch malicious code into your Claude Code executable that would execute when you run claude. As a result, it's highly advised to review the diff tweakcc prints when it asks you if you'd like to apply the changes proposed by the patch.

  • Input/output: Claude Code's JavaScript code is passed to the script via a global variable, js, available inside the script's execution context. To return the modified file content, simply use the return keyword. For example, to write a very simple script that replaced all instances of "Claude Code" with "My App", you could write the following:

    js = js.replace(/"Claude Code"/g, '"My App"');
    return js;
    
  • Utility vars: Because complicated patches may need to make use of common functions and global variables like chalk, React, require, and the low-level module loader function, and also common Ink/React components like Text and Box, tweakcc also provides a vars global variable to the script. vars is an object containing the names of the common variables listed above; here's an example:

    const vars = {
      chalkVar: 'K6',
      moduleLoaderFunction: 's',
      reactVar: 'Yt8',
      requireFuncName: 'C1',
      textComponent: 'f',
      boxComponent: 'NZ5',
    };
    
  • Script source: Scripts can be passed in 3 ways: directly on the command-line, via a local file on disk, and via an HTTP URL. In order to specify a file, pass the path to the file prefixed with @ (similar to curl -d). To specify an HTTP URL, use @ and ensure the URL is prefixed with http:// or https://. HTTP scripts themselves are safe to run as a result of our sandboxing, with one notable pitfall, as mentioned above.

Usage

# Replace a fixed string with another string:
npx tweakcc adhoc-patch --string '"Claude Code"' '"My App"'

# Replace all CSS-style RGB colors with bright red:
npx tweakcc adhoc-patch --regex 'rgb\(\d+,\d+,\d+\)' 'rgb(255,0,0)'

# Erase all of CC's code and replace it with a simple console.log:
npx tweakcc adhoc-patch --script $'return "(function(){console.log(\"Hi\")})()"'

# Run a script from a local file:
npx tweakcc adhoc-patch --script '@path/to/script.js'

# Run a script from an HTTP URL (warning: this script makes everything in CC blue and changes "Claude Code" to "ABC Code CLI", which BREAKS CC):
# Its contents are:
#
#   js = js.replace(/Claude Code/g, "ABC Code CLI")
#   js = js.replace(/rgb\(\d+,\d+,\d+\)/g, "rgb(0,128,255)")
#   return js
#
npx tweakcc adhoc-patch --script '@https://gist.githubusercontent.com/bl-ue/2402a16b966176c994ea7bd5d11b0b09/raw/eeb0b78a6387f0e6a15182eeabd95f0e84e4ccd7/patch_cc.js'

Here's a demo of adhoc-patch using a script from an HTTP URL (link to Gist):

https://github.com/user-attachments/assets/221ce577-933e-41d9-ae14-88ce5457a321

[!CAUTION] adhoc-patch does not create a backup of the Claude Code installation that is modified. You'll need to use --apply first to get a backup created if you want to be able to use --restore/--revert after an adhoc-patch.

API

tweakcc can be used as an npm dependency and provides an easy API that projects can use to patch Claude Code without worrying about where it's installed and whether it's native or npm-based. The functions are divided into 5 groups: config, installation, I/O, backup, and utilities.

Config •  Functions to access tweakcc's own config, if it exists on the machine.
/**
 * Returns the absolute path to tweakcc's config dir.  By default it's
 * `~/.tweakcc` but it also can use `~/.claude/tweakcc` and it also respects
 * `XDG_CONFIG_HOME`—see [Configuration Directory](#configuration-directory).
 */
function getTweakccConfigDir(): string;

/**
 * Returns the absolute path to tweakcc's config file.  It's named `config.json`
 * and lives in the config dir as returned by `getTweakccConfigDir`.
 */
function getTweakccConfigPath(): string;

/**
 * Returns the absolute path to the directory containing the user-editable
 * system prompt markdown files.  It's named `system-prompts/` and lives in the
 * config dir.
 */
function getTweakccSystemPromptsDir(): string;

/**
 * Reads and returns the tweakcc config (as determined by `getTweakccConfigDir`).
 */
function readTweakccConfig(): Promise<TweakccConfig | null>;

Demo:

> tweakcc.getTweakccConfigDir()
'/home/user/.tweakcc'

> tweakcc.getTweakccConfigPath()
'/home/user/.tweakcc/config.json'

> tweakcc.getTweakccSystemPromptsDir()
'/home/user/.tweakcc/system-prompts'

> await tweakcc.readTweakccConfig()
{
  ccVersion: '2.1.32',
  ccInstallationPath: '/home/user/.local/bin/claude',
  lastModified: '2026-02-05T21:18:48.551Z',
  changesApplied: true,
  settings: { ... }
}
Installation  •   Utilities to find installed versions of Claude Code.
/**
 * Finds all Claude Code installations on the machine via `$PATH` and hard-coded
 * search directories.
 */
async function findAllInstallations(): Promise<Installation[]>;

/**
 * Prompts the user to select one of the specified Claude Code installations
 * interactively using the same UI tweakcc uses, powered by [Ink + React](https://github.com/vadimdemedes/ink).
 */
async function showInteractiveInstallationPicker(
  candidates: Installation[]
): Promise<Installation | null>;

/**
 * Attempts to detect the user's preferred Claude Code installation.  Detection procedure:
 * 0. options.path
 * 1. Uses $TWEAKCC_CC_INSTALLATION_PATH if set.
 * 2. Uses ccInstallationPath in tweakcc config.
 * 3. Discovers installation from `claude` in PATH
 * 4. Looks in hard-coded search paths:
 *   a. If the search yields one installation, uses it
 *   b. If it yields multiple and options.interactive is true, display a picker
 *      via showInteractiveInstallationPicker().
 */
async function tryDetectInstallation(
  options: DetectInstallationOptions = {}
): Promise<Installation>;

Demo:

> const insts = await tweakcc.findAllInstallations()
[
  {
    path: 'C:\\Users\\user\\.local\\share\\claude\\versions\\2.0.60',
    version: '2.0.60',
    kind: 'native'
  },
  {
    path: 'C:\\Users\\user\\.local\\share\\claude\\versions\\2.0.76',
    version: '2.0.76',
    kind: 'native'
  },
  {
    path: 'C:\\Users\\user\\AppData\\Local\\Volta\\tools\\image\\packages\\@anthropic-ai\\claude-code\\node_modules\\@anthropic-ai\\claude-code\\cli.js',
    version: '2.1.32',
    kind: 'npm'
  }
]

> await tweakcc.tryDetectInstallation()
{
  path: 'C:\\Users\\user\\AppData\\Local\\Volta\\tools\\image\\packages\\@anthropic-ai\\claude-code\\node_modules\\@anthropic-ai\\claude-code\\cli.js',
  version: '2.1.32',
  kind: 'npm'
}

> await tweakcc.showInteractiveInstallationPicker(insts)
No claude executable was found in PATH, but multiple Claude Code installations were found on this machine. Please select one:

❯ C:\Users\user\.local\share\claude\versions\2.0.60 (native-binary, v2.0.60)
  C:\Users\user\.local\share\claude\versions\2.0.76 (native-binary, v2.0.76)
  C:\Users\user\AppData\Local\Volta\tools\image\packages\@anthropic-ai\claude-code\node_modules\@anthropic-ai\claude-code\cli.js (npm-based, v2.1.32)

Your choice will be saved to ccInstallationPath in ~\.tweakcc/config.json.

Use ↑↓ arrows to navigate, Enter to select, Esc to quit
I/O  •   Functions to read and write the content of an npm-based or native (Bun-based) installation.
/**
 * Read Claude Code's JavaScript content.
 *
 * - npm installs: reads cli.js directly
 * - native installs: extracts embedded JS from binary
 */
async function readContent(installation: Installation): Promise<string>;

/**
 * Write modified JavaScript content back to Claude Code.
 *
 * - npm installs: writes to cli.js (handles permissions, hard links)
 * - native installs: repacks JS into binary
 */
async function writeContent(
  installation: Installation,
  content: string
): Promise<void>;

Demo:

> const native2076Inst = { path: 'C:\\Users\\user\\.local\\share\\claude\\versions\\2.0.76', kind: 'native' };

// Reading native content:
> let content = await tweakcc.readContent(native2076Inst);
> content.length
10639722  // 10.6 MB
> content.slice(4153122, 4153122+236)
"var be$=\"You are Claude Code, Anthropic's official CLI for Claude.\",UBD=\"You are Claude Code, Anthropic's official CLI for Claude, running within the Claude Agent SDK.\",GBD=\"You are a Claude agent, built on Anthropic's Claude Agent SDK.\""

// Updating and re-reading native content:
> content = content.replace(/Claude Code/g, 'My App')
> content = content.replace(/Anthropic(?: PBC)?/g, 'My Corp')
> await tweakcc.writeContent(native2076Inst, content)
undefined
> (await tweakcc.readContent(native2076Inst)).slice(4153122+16, 4153122+172)
"var be$=\"You are My App, My Corp's official CLI for Claude.\",UBD=\"You are My App, My Corp's official CLI for Claude, running within the Claude Agent SDK.\",GBD=\"You are a Claude agent, built on My Corp's Claude Agent SDK.\""
Backup  •   Simple utilities to handle creating and restoring backups of the native binary or `cli.js` in order to revert patches.
/**
 * Backup a file to a specified location, creating parent directories if needed.
 * Leaves the original file untouched.
 */
async function backupFile(
  sourcePath: string,
  backupPath: string
): Promise<void>;

/**
 * Restore a file from a backup, breaking hard links, which are common with pnpm/bun
 * installations, and preserving execute permissions.
 */
async function restoreBackup(
  backupPath: string,
  targetPath: string
): Promise<void>;

Demo:

// Make a backup of the original install:
> const native2076Inst = { path: 'C:\\Users\\user\\.local\\share\\claude\\versions\\2.0.76', kind: 'native' };
> const backupPath = path.join(os.homedir(), ".myapp", `cc-${native2076Inst.kind}-backup`);
> await tweakcc.backupFile(native2076Inst.path, backupPath);
undefined
> fs.statSync(backupPath).size
234454688   // <-- It was made successfully; 234.5 MB.

// Now patch the original:
> await tweakcc.writeContent(native2076Inst, "(function(){console.log(\"Hi\")})");
> (await tweakcc.readContent(native2076Inst)).length
31          // <-- Original was successfully modified.

// Restore the backup:
> await tweakcc.restoreBackup(backupPath, native2076Inst.path)
> (await tweakcc.readContent(native2076Inst)).length
234454688   // Original, unpatched size.
Utilities  •   General utilities to help with patching.
// Utilities to find various commonly-used variables in CC's code.
// See the docs for `tweakcc adhoc-patch --script` above for more details.
findChalkVar(fileContents: string): string | undefined;
getModuleLoaderFunction(fileContents: string): string | undefined;
getReactVar(fileContents: string): string | undefined;
getRequireFuncName(fileContents: string): string | undefined;
findTextComponent(fileContents: string): string | undefined;
findBoxComponent(fileContents: string): string | undefined;
/**
 * Clears the process-global caches that some of the above functions populate
 * to speed up subsequent repeated calls.  Use this when processing multiple CC
 * installs in one process.
 */
clearCaches(): void;

/**
 * Debug function for showing diffs between old and new file contents using smart word-level diffing.
 *
 * Uses the `diff` library to compute word-level differences and displays them with
 * chalk-styled colors: green background for additions, red background for removals, and
 * dim text for unchanged portions.
 *
 * Only outputs when --verbose flag is set.
 *
 * @param oldFileContents - The original file content before modification
 * @param newFileContents - The modified file content after patching
 * @param injectedText - The text that was injected (used to calculate context window)
 * @param startIndex - The start index where the modification occurred
 * @param endIndex - The end index of the original content that was replaced
 * @param numContextChars - Number of context characters to show before and after diff.
 */
export const showDiff = (
  oldFileContents: string,
  newFileContents: string,
  injectedText: string,
  startIndex: number,
  endIndex: number,
  numContextChars: number = 40
): void;

/**
 * Performs a global replace on a string, finding all matches first, then replacing
 * them in reverse order (to preserve indices), and calling showDiff for each replacement.
 *
 * @param content - The string to perform replacements on
 * @param pattern - The regex pattern to match (should have 'g' flag for multiple matches)
 * @param replacement - Either a string or a replacer function (same as String.replace)
 * @returns The modified string with all replacements applied
 *
 * @example
 * ```ts
 * const result = globalReplace(
 *   content,
 *   /throw Error\(`something`\);/g,
 *   ''
 * );
 * ```
 */
export const globalReplace = (
  content: string,
  pattern: RegExp,
  replacement: string | ((substring: string, ...args: unknown[]) => string)
): string;

Demo of showDiff:

const pattern = /function [$\w]+\(\)\{return [$\w]+\("my_feature_flag"/;
const match = file.match(pattern)!;
const insertIndex = match.index + match[0].indexOf('{') + 1;
const insertion = 'return true;';

const newFile = file.slice(0, insertIndex) + insertion + file.slice(insertIndex);

showDiff(file, newFile, insertion, insertIndex, insertIndex);

Demo of globalReplace:

newFile = globalReplace(newFile, /"Claude Code",/g, '"My App"');

System prompts

tweakcc allows you to customize the various parts of Claude Code's system prompt, including

  • the main system prompt and any conditional bits,
  • descriptions for all 17 builtin tools like Bash, TodoWrite, Read, etc.,
  • prompts for builtin Task/Plan/Explore subagents, and
  • prompts for utili

Similar other

Added to RepoDepot ·