vitest-dev / vitest-dev/vitest
Agent detection disables colors in user code via shared tinyrainbow singleton
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 17.1k
- Forks
- 2k
- Avg merge
- 1d 22h
- Merged PRs (30d)
- 94
Description
Describe the bug
Vitest 4.1.2 calls disableDefaultColors() from tinyrainbow 3.1.0 when std-env's isAgent is true (e.g. running inside Claude Code, Cursor, etc.):
// vitest/dist/chunks/cac.DRKYQDPl.js
import { isAgent } from 'std-env';
import { disableDefaultColors } from 'tinyrainbow';
if (isAgent) disableDefaultColors();
disableDefaultColors() mutates tinyrainbow's shared default export singleton via Object.assign(), turning all color functions into identity functions. This affects not just Vitest's own output, but also user code under test that imports tinyrainbow — because both Vitest and user code resolve to the same singleton instance.
This means any test that asserts on ANSI-colored output (e.g. testing a CLI formatter that uses tinyrainbow) silently breaks when run inside an AI agent environment.
Reproduction
- Create a module that uses tinyrainbow:
import color from "tinyrainbow";
export const warn = (msg: string) => `${color.yellow("⚠")} ${msg}`;
- Write a test asserting colored output:
it("should produce yellow warning symbol", () => {
expect(warn("oops")).toContain("\x1b[33m⚠\x1b[39m");
});
- Run with
CLAUDECODE=1(or any env that makesstd-envdetect an agent):
CLAUDECODE=1 vitest run
The test fails because color.yellow becomes an identity function.
Expected behavior: Vitest's agent detection should only affect Vitest's own reporter output, not mutate shared state that user code depends on.
Possible solutions:
- Use
createColors()for Vitest's internal rendering instead of mutating the default singleton - Scope the disable to Vitest's reporter layer rather than the global default
System Info
System:
OS: Windows 11 10.0.26100
CPU: (32) x64 AMD Ryzen 9 9950X3D 16-Core Processor
Memory: 37.30 GB / 93.64 GB
Binaries:
Node: 25.8.2 - C:\Users\Christopher\.local\share\mise\installs\node\25.8.2\node.EXE
npm: 11.11.1 - C:\Users\Christopher\.local\share\mise\installs\node\25.8.2\npm.CMD
pnpm: 10.33.0 - C:\Users\Christopher\.local\share\mise\installs\npm-corepack\0.34.6\pnpm.CMD
bun: 1.3.11 - C:\Users\Christopher\.local\share\mise\installs\bun\1.3.11\bin\bun.EXE
Deno: 2.7.10 - C:\Users\Christopher\.local\share\mise\installs\deno\2.7.10\bin\deno.EXE
Browsers:
Edge: Chromium (140.0.3485.54)
Firefox: 149.0 - C:\Program Files\Mozilla Firefox\firefox.exe
npmPackages:
@vitest/coverage-v8: catalog:test => 4.1.2
@vitest/eslint-plugin: catalog:lint => 1.6.13
vitest: catalog:test => 4.1.2
Used Package Manager
pnpm
Validations
- Follow our Code of Conduct
- Read the Contributing Guidelines.
- Read the docs.
- Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.
- Check that this is a concrete bug. For Q&A open a GitHub Discussion or join our Discord Chat Server.
- The provided reproduction is a minimal reproducible example of the bug.
Generated with Claude Code
Verified manually by me!
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by tracing the agent check and disableDefaultColors() call in vitest/dist/chunks/cac.DRKYQDPl.js, then inspect how Vitest reporter rendering obtains its colors. Reproduce with CLAUDECODE=1 and a user module importing tinyrainbow. Done means Vitest output can disable its own colors without changing the colored output asserted by user code.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- testing-qa
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100