RepoPilotOpen in app →

std-microblock/chromatic

Universal modifier for Chromium/V8 | 广谱注入 Chromium/V8 的通用修改器

Mixed

Missing license — unclear to depend on

worst of 4 axes
Use as dependencyConcerns

no license — legally unclear; single-maintainer (no co-maintainers visible)

Fork & modifyConcerns

no license — can't legally use code

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isConcerns

no license — can't legally use code

  • Last commit 6w ago
  • CI configured
  • Tests present
Show 2 more →
  • Solo or near-solo (1 contributor active in recent commits)
  • No license — legally unclear to depend on
What would change the summary?
  • Use as dependency ConcernsMixed if: publish a permissive license (MIT, Apache-2.0, etc.)
  • Fork & modify ConcernsMixed if: add a LICENSE file
  • Deploy as-is ConcernsMixed if: add a LICENSE file

Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests

Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.

Embed the "Great to learn from" badge

Paste into your README — live-updates from the latest cached analysis.

RepoPilot: Great to learn from
[![RepoPilot: Great to learn from](https://repopilot.app/api/badge/std-microblock/chromatic?axis=learn)](https://repopilot.app/r/std-microblock/chromatic)

Paste at the top of your README.md — renders inline like a shields.io badge.

Preview social card (1200×630)

This card auto-renders when someone shares https://repopilot.app/r/std-microblock/chromatic on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: std-microblock/chromatic

Generated by RepoPilot · 2026-05-09 · Source

🤖Agent protocol

If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:

  1. Verify the contract. Run the bash script in Verify before trusting below. If any check returns FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding.
  2. Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
  3. Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/std-microblock/chromatic shows verifiable citations alongside every claim.

If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.

🎯Verdict

WAIT — Missing license — unclear to depend on

  • Last commit 6w ago
  • CI configured
  • Tests present
  • ⚠ Solo or near-solo (1 contributor active in recent commits)
  • ⚠ No license — legally unclear to depend on

<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>

Verify before trusting

This artifact was generated by RepoPilot at a point in time. Before an agent acts on it, the checks below confirm that the live std-microblock/chromatic repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/std-microblock/chromatic.

What it runs against: a local clone of std-microblock/chromatic — the script inspects git remote, the LICENSE file, file paths in the working tree, and git log. Read-only; no mutations.

| # | What we check | Why it matters | |---|---|---| | 1 | You're in std-microblock/chromatic | Confirms the artifact applies here, not a fork | | 2 | Default branch master exists | Catches branch renames | | 3 | 5 critical file paths still exist | Catches refactors that moved load-bearing code | | 4 | Last commit ≤ 69 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>std-microblock/chromatic</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of std-microblock/chromatic. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/std-microblock/chromatic.git
#   cd chromatic
#
# Then paste this script. Every check is read-only — no mutations.

set +e
fail=0
ok()   { echo "ok:   $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }

# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
  echo "FAIL: not inside a git repository. cd into your clone of std-microblock/chromatic and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "std-microblock/chromatic(\\.git)?\\b" \\
  && ok "origin remote is std-microblock/chromatic" \\
  || miss "origin remote is not std-microblock/chromatic (artifact may be from a fork)"

# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
  && ok "default branch master exists" \\
  || miss "default branch master no longer exists"

# 4. Critical files exist
test -f "src/core/core.cc" \\
  && ok "src/core/core.cc" \\
  || miss "missing critical file: src/core/core.cc"
test -f "src/core/typescript/src/main.ts" \\
  && ok "src/core/typescript/src/main.ts" \\
  || miss "missing critical file: src/core/typescript/src/main.ts"
test -f "src/injectee/injectee.cc" \\
  && ok "src/injectee/injectee.cc" \\
  || miss "missing critical file: src/injectee/injectee.cc"
test -f "src/core/bindings/native_interceptor.cc" \\
  && ok "src/core/bindings/native_interceptor.cc" \\
  || miss "missing critical file: src/core/bindings/native_interceptor.cc"
test -f "src/core/bindings/native_ffi.cc" \\
  && ok "src/core/bindings/native_ffi.cc" \\
  || miss "missing critical file: src/core/bindings/native_ffi.cc"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 69 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~39d)"
else
  miss "last commit was $days_since_last days ago — artifact may be stale"
fi

echo
if [ "$fail" -eq 0 ]; then
  echo "artifact verified (0 failures) — safe to trust"
else
  echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/std-microblock/chromatic"
  exit 1
fi

Each check prints ok: or FAIL:. The script exits non-zero if anything failed, so it composes cleanly into agent loops (./verify.sh || regenerate-and-retry).

</details>

TL;DR

Chromatic is a universal code injection and modification framework for Chromium and V8 JavaScript engines. It enables runtime patching of Chromium-based applications (like NetEase Cloud Music, QQ Music, etc.) and V8 environments through a TypeScript/JavaScript API exposed via C++ bindings, supporting features like memory manipulation, function interception, native breakpoints, and FFI calls. Monorepo structure: src/core/ houses the C++ engine (core.cc/core.h, script.cc/script.h), src/core/bindings/ exposes native APIs (memory, FFI, interceptors, breakpoints) to JavaScript, src/core/typescript/ likely contains TypeScript definitions, and deps/ pins external C++ dependencies (libtcc, yalantinglibs, breeze-js). Build via Xmake, TypeScript artifacts bundled with esbuild.

👥Who it's for

Developers building extensions or modifications for Chromium-based applications who need runtime code injection and low-level system access (memory reads/writes, breakpoints, disassembly). Originally created for music streaming client modifiers (successor to BetterNCM), now generalized for any Chromium/V8 patching use case.

🌱Maturity & risk

Actively developed but still experimental—the README explicitly warns 'This project is still in active development' and documentation is marked '待完善' (incomplete). GitHub Actions CI/CD is configured (build.yml), suggesting continuous integration is in place, but no release tags or version indicators visible in provided file list. Single-maintainer (std-microblock) increases maintenance risk.

High complexity and low-level nature: the project directly manipulates memory, injects code into running processes, and patches V8 internals—any API instability or V8 version mismatch could break user scripts silently. Dependency on external C++ libraries (libtcc, yalantinglibs, breeze-js) and quickjs adds supply-chain risk. Documentation gaps ('待完善') mean users have limited safe usage patterns.

Active areas of work

No specific milestone or recent commit data visible in provided snapshot, but active development is indicated by TODO documentation markers and the recent migration from legacy BetterNCM codebase. The bindings layer shows breadth of features (9+ native modules: memory, FFI, disassembler, interceptor, breakpoints, etc.), suggesting ongoing API expansion.

🚀Get running

git clone https://github.com/std-microblock/chromatic.git
cd chromatic
# Install C++ dependencies via Xmake (build system listed in file structure)
xmake
# TypeScript build uses esbuild
pnpm install && pnpm run build

Daily commands: For TypeScript dev: pnpm run build outputs bundled JS to dist/index.js (requires --external:chromatic so modules link to native bindings at runtime). For C++ core: xmake build (specific targets not visible, check xmake.lua). No dev server visible—this is a library, not a service.

🗺️Map of the codebase

  • src/core/core.cc — Main entry point for the chromatic framework that initializes and manages the injection lifecycle into Chromium/V8 processes
  • src/core/typescript/src/main.ts — TypeScript API surface that all user scripts interface with; defines the public binding layer between native code and JavaScript
  • src/injectee/injectee.cc — Injection mechanism that loads and executes modifications into target Chromium processes at runtime
  • src/core/bindings/native_interceptor.cc — Core native binding for function interception, enabling modification of Chromium internals through hook mechanisms
  • src/core/bindings/native_ffi.cc — Foreign Function Interface implementation allowing TypeScript to call arbitrary C/C++ code and native functions
  • src/core/script.cc — Script lifecycle manager that handles compilation, execution, and cleanup of user TypeScript/JavaScript modifications
  • xmake.lua — Build configuration defining compilation targets, dependencies (libtcc, yalantinglibs), and platform-specific flags for the entire project

🛠️How to make changes

Add a new native binding for Chromium internals

  1. Create a new .cc/.h file in src/core/bindings/ named native_<feature>.cc (e.g., native_dom_monitor.cc) (src/core/bindings/native_dom_monitor.cc)
  2. Implement a C++ class with static methods matching the native API pattern; use QJSPP macros for binding (src/core/bindings/native_dom_monitor.cc)
  3. Register the binding in the QuickJS context in src/core/script.cc's script initialization function (src/core/script.cc)
  4. Create a corresponding TypeScript wrapper in src/core/typescript/src/dom-monitor.ts that exports user-friendly methods (src/core/typescript/src/dom-monitor.ts)
  5. Export the new module from src/core/typescript/src/main.ts so it's available in user scripts (src/core/typescript/src/main.ts)
  6. Add test cases in src/test/test_dom_monitor.cc and verify with xmake build && xmake run test (src/test/test_dom_monitor.cc)

Add a new user-facing TypeScript API method

  1. Identify which module your feature belongs to (e.g., memory.ts, interceptor/index.ts, process.ts) (src/core/typescript/src/memory.ts)
  2. Add a TypeScript function/class method that calls the native binding via chromatic global (auto-linked by the framework) (src/core/typescript/src/memory.ts)
  3. Update type definitions in src/core/typescript/src/types.ts if introducing new parameter or return types (src/core/typescript/src/types.ts)
  4. Run pnpm build in src/core/typescript/ to bundle and generate type stubs (src/core/typescript/package.json)
  5. Test by creating a minimal .ts script and injecting via the injectee (src/test/test_memory.cc)

Modify the injection pipeline or add a new hook point

  1. Review the injection flow in src/injectee/injectee.cc to understand where your hook should attach (src/injectee/injectee.cc)
  2. Update src/injectee/config.cc to add configuration keys for the new hook if user-tunable (src/injectee/config.cc)
  3. Add the hook logic in src/core/core.cc's main loop or during script initialization (src/core/script.cc) (src/core/core.cc)
  4. Expose any hook parameters to TypeScript via a new method in src/core/typescript/src/script-lifecycle.ts (src/core/typescript/src/script-lifecycle.ts)
  5. Build with xmake and test via src/test/test_script_lifecycle.cc (src/test/test_script_lifecycle.cc)

Add platform-specific functionality (e.g., ARM64 disassembly)

  1. Check xmake.lua for platform detection logic (e.g., is_arch('x86_64'), is_os('windows')) (xmake.lua)
  2. Add platform-specific source files or conditional compilation in the binding implementation (e.g., src/core/bindings/native_disassembler.cc) (src/core/bindings/native_disassembler.cc)
  3. Update TypeScript API to reflect platform availability in src/core/typescript/src/instruction.ts (src/core/typescript/src/instruction.ts)
  4. Add platform-specific tests in src/test/test_instruction.cc (src/test/test_instruction.cc)
  5. Rebuild with xmake to verify cross-platform compilation (xmake.lua)

🔧Why these technologies

  • QuickJS (embedded JavaScript engine) — Lightweight, portable VM for executing user-supplied TypeScript/JavaScript without requiring a full Node.js runtime; keeps injection footprint small
  • Frida-style function interception — Industry-standard approach for runtime code modification; allows non-invasive hooking of arbitrary functions without recompiling the target

🪤Traps & gotchas

Chromium version coupling: V8 APIs change frequently; breakpoints, disassembly, and interceptor internals may fail silently on mismatched V8 versions without fallbacks visible. QuickJS limitations: generated_bindings/quickjspp.hpp suggests QuickJS (not V8 itself) powers the JS runtime in bindings—memory limits, ES compatibility, and garbage collection behavior differ from Node/Chrome. Build system opacity: Xmake is less common than CMake/Bazel; no Makefile or setup guide visible—new contributors may struggle with dependency resolution (libtcc, yalantinglibs) on non-Linux. Incomplete docs: API.md marked incomplete in both languages; many binding names (e.g., memory_access_monitor, hw_breakpoint) lack usage examples or safety guarantees. Platform assumptions: Heavy native code likely Linux/Windows specific; macOS support unclear.

🏗️Architecture

💡Concepts to learn

  • Code Relocation (Code Patching) — Chromatic's code_relocator.cc performs runtime instruction patching to replace function bodies; understanding relocation is essential for safely hooking without corrupting memory or breaking instruction references
  • Hardware Breakpoints — native_hw_breakpoint.cc exposes CPU-level breakpoint facilities for pausing execution on specific addresses; critical for debugging and conditional patching logic without software breakpoint overhead
  • Foreign Function Interface (FFI) — native_ffi.cc allows JavaScript to call arbitrary C/C++ functions at runtime; enables users to invoke Chromium internals or system libraries directly from patches
  • Function Interception / Hooking — native_interceptor.cc implements runtime function patching (replacing function pointers or prologue code); the core mechanism for injecting custom logic into Chromium/V8 execution
  • Memory-Mapped Access & Process Memory Manipulation — native_memory.cc and native_memory_access_monitor.cc provide direct read/write access to process memory and monitoring capabilities; foundational for all low-level modifications but requires careful alignment and bounds checking
  • Disassembly / Reverse Engineering — native_disassembler.cc likely integrates a disassembler (capstone or similar) to analyze function code at runtime; required for understanding and safely patching compiled V8 bytecode or native code
  • Exception Handling & Signal Handling — native_exception_handler.cc manages SEH (Windows) or signals (POSIX) during patching; prevents crashes when injected code runs or breakpoints fire in unpredictable contexts
  • frida/frida — Industry-standard dynamic instrumentation framework with similar goals (runtime code injection, memory manipulation, function hooking) but for broader OS-level use vs. Chromatic's Chromium-specific focus
  • nodejs/node-gyp — Node.js native module binding system; shares similar C++↔JS bridging patterns and build challenges as Chromatic's QuickJS integration
  • google/v8 — Upstream V8 JavaScript engine; Chromatic directly patches V8 internals and depends on version stability
  • bellard/quickjs — QuickJS embeds the JS runtime used in Chromatic bindings (generated_bindings/quickjspp.hpp); foundational dependency
  • std-microblock/BetterNCM — Predecessor project (archived at v2 branch); Chromatic is a complete rewrite and modernization maintaining spiritual compatibility with music client patching use case

🪄PR ideas

To work on one of these in Claude Code or Cursor, paste: Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.

Add TypeScript build output validation tests

The TypeScript source in src/core/typescript/src/ is bundled via esbuild into dist/index.js, but there are no tests verifying the bundle output is correct, the bindings are properly exposed, or that native module imports work. This is critical for a universal modifier that must reliably inject code into Chromium/V8.

  • [ ] Create src/core/typescript/tests/build-output.test.ts to verify dist/index.js exports all expected modules (memory, interceptor, breakpoint, etc.)
  • [ ] Add validation that native bindings from binding_qjs.h are accessible from the bundled output
  • [ ] Add a test step in .github/workflows/build.yml to run these tests after esbuild completes
  • [ ] Verify that circular dependencies between modules (native_ffi.cc, native_interceptor.cc, etc.) don't break the bundle

Document native binding generation pipeline in scripts/bindgen.sh

The repo has generated bindings (src/core/bindings/generated_bindings/) but scripts/bindgen.sh exists with no documentation. New contributors won't know how to regenerate bindings when modifying src/core/bindings/binding_types.h or adding new native modules, causing maintenance friction.

  • [ ] Add detailed comments to scripts/bindgen.sh explaining input/output files and dependencies (binding_types.h → binding_qjs.h, binding_types.d.ts)
  • [ ] Create docs/en-US/CONTRIBUTING-BINDINGS.md and docs/zh-CN/CONTRIBUTING-BINDINGS.md documenting when/how to run bindgen.sh after adding native modules
  • [ ] Add a pre-commit hook example or CI step in .github/workflows/build.yml to detect stale generated bindings
  • [ ] Document which tools/versions bindgen.sh requires (e.g., clang, node version for TypeScript generation)

Add integration tests for native interceptor and memory access patterns

The native modules (native_interceptor.cc, native_memory_access_monitor.cc, native_breakpoint.cc) are core to chromatic's functionality but lack visible test coverage. The stress-test.sh script exists but has no documentation. This makes regressions in hook/breakpoint behavior hard to catch.

  • [ ] Create src/core/bindings/tests/interceptor.test.cc with basic tests for native_interceptor.cc function hooking and callback behavior
  • [ ] Add src/core/typescript/tests/memory-access-monitor.test.ts to test the JavaScript-facing memory monitoring API against native_memory_access_monitor.cc
  • [ ] Document scripts/stress-test.sh in docs/en-US/CONTRIBUTING.md with usage examples and expected output
  • [ ] Add a GitHub Actions workflow step (.github/workflows/build.yml) to run stress-test.sh on PR merge or schedule it weekly, capturing performance regressions

🌿Good first issues

  • Write docs/en-US/GETTING_STARTED.md with step-by-step examples for memory read/write, function interception, and FFI calls using the existing native bindings (native_memory.h, native_ffi.h, native_interceptor.h show the API surface but users have no guided tour).
  • Add unit tests in a new tests/ directory for core/ bindings, particularly code_relocator.cc and memory access patterns—these are safety-critical but no test files visible in the repo.
  • Implement and document native_memory_access_monitor.cc—the file exists but no usage examples or security guardrails are documented; add a tutorial showing how to watch for illegal memory writes in user scripts.

Top contributors

Click to expand

📝Recent commits

Click to expand
  • 91cd9c3 — fix: bump libtcc, revert preamble workaround (std-microblock)
  • 6f0e5d7 — fix: prepend dllimport preamble for user symbols on windows tcc (std-microblock)
  • d179a38 — fix: add _imp entries for windows tcc pe relocation (std-microblock)
  • 34cafdd — fix: remove stale ctx.pc on windows, use platformContext->getPc() (std-microblock)
  • 970c199 — fix: gnu hash bloom filter stride on 64-bit arm (std-microblock)
  • 8f33893 — fix: add windows.h for OutputDebugStringA (std-microblock)
  • c579496 — fix: windows stdin rvalue, xmake run args, bump breeze-js (std-microblock)
  • ba0183e — fix: android stdin rvalue, linux linkgroups, skip signal tests in ci, bump libtcc (std-microblock)
  • 268abcb — fix: bump libtcc, fix ctx->pc -> getPc() (std-microblock)
  • 42dd9e5 — feat: CModule support (std-microblock)

🔒Security observations

  • High · Unsafe Native Code Injection and FFI Bindings — src/core/bindings/native_ffi.cc, src/core/bindings/native_memory.cc, src/core/bindings/internal/code_relocator.cc. The codebase provides extensive native code injection capabilities through FFI (native_ffi.cc), code relocation (code_relocator.cc), and direct memory manipulation (native_memory.cc). These features allow arbitrary code execution at the native level without apparent input validation or sandboxing. The chromatic project is designed as a universal modifier for Chromium/V8, which inherently enables code injection. Fix: Implement strict input validation, add security context checks, provide code signing verification, implement capability-based security model, and document the security implications clearly.
  • High · Unrestricted Memory Access and Manipulation — src/core/bindings/native_memory.cc, src/core/bindings/native_pointer.cc, src/core/bindings/native_breakpoint.cc. native_memory.cc, native_memory_access_monitor.cc, and native_pointer.cc provide direct read/write access to arbitrary memory locations. Combined with breakpoint (native_breakpoint.cc) and exception handler (native_exception_handler.cc) functionality, this enables attackers to read/modify sensitive data, bypass ASLR, and corrupt program state. Fix: Implement memory bounds checking, add access control lists for sensitive memory regions, use W^X (Write XOR Execute) protection, and provide audit logging for all memory access operations.
  • High · Process Manipulation Without Restrictions — src/core/bindings/native_process.cc, src/core/bindings/native_interceptor.cc. native_process.cc provides capabilities to manipulate process state, including interceptor functionality (native_interceptor.cc), without apparent restrictions on what can be intercepted or modified. This could allow function hooking attacks. Fix: Implement whitelist/blacklist mechanisms for interceptable functions, add authorization checks, provide detailed audit logging, and restrict access to sensitive system functions.
  • Medium · Potential CModule Code Loading Risk — src/core/bindings/native_cmodule.cc. native_cmodule.cc allows loading of C modules dynamically. If module sources are not properly validated, this could lead to arbitrary code loading and execution. Fix: Implement module signature verification, use secure loading mechanisms, validate module paths, and restrict module loading to whitelisted locations or sources.
  • Medium · Disassembler Information Disclosure — src/core/bindings/native_disassembler.cc. native_disassembler.cc provides disassembly capabilities which could leak sensitive information about code structure, addresses (bypassing ASLR), and implementation details to unauthorized parties. Fix: Add access control for disassembly operations, implement rate limiting, provide audit logging, and consider restricting to debug builds only.
  • Medium · Dependency on External Package Manager without Lock File Verification — src/core/typescript/package.json, src/core/typescript/pnpm-lock.yaml. The TypeScript build depends on pnpm with esbuild@^0.27.4. While a pnpm-lock.yaml exists, the caret version allows updates. Build reproducibility and supply chain security could be compromised. Fix: Use exact version pinning instead of caret (^), regularly audit and update dependencies, implement dependency verification, and consider using npm ci instead of npm install.
  • Medium · Hardware Breakpoint Implementation — src/core/bindings/native_hw_breakpoint.cc. native_hw_breakpoint.cc provides hardware breakpoint functionality which could be used to bypass security mechanisms, trigger unintended code paths, or cause denial of service. Fix: Implement strict authorization checks for hardware breakpoint operations, add resource limits, provide audit logging, and consider platform-specific security restrictions.
  • Low · Missing Security Documentation — README.md, docs/. The project lacks comprehensive security documentation. The README indicates documentation is still being improved ('待完善'). Security guidelines, threat model, and safe usage patterns are not documented. Fix: Create comprehensive security documentation including threat model, security guarantees, safe usage patterns

LLM-derived; treat as a starting point, not a security audit.


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

Mixed signals · std-microblock/chromatic — RepoPilot