adding-a-command
Creates a new CLI command following the Commander.js pattern in src/commands/. Handles…
Writes Vitest tests following project patterns: __tests__/ directories, vi.mock() for module mocking with vi.hoisted() for test-time factories, global LLM mock from src/test/setup.ts, environment variable save/restore in beforeEach/afterEach, vi.clearAllMocks() lifecycle, and
$ npx -y skills add caliber-ai-org/ai-setup --skill caliber-testing --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/caliber-testingContext preview
The summary Claude sees to decide when to auto-load this skill.
Writes Vitest tests following project patterns: __tests__/ directories, vi.mock() for module mocking with vi.hoisted() for test-time factories, global LLM mock from src/test/setup.ts, environment variable save/restore in beforeEach/afterEach, vi.clearAllMocks() lifecycle, and
name: caliber-testing description: Writes Vitest tests following project patterns: __tests__/ directories, vi.mock() for module mocking with vi.hoisted() for test-time factories, global LLM mock from src/test/setup.ts, environment variable save/restore in beforeEach/afterEach, vi.clearAllMocks() lifecycle, and test file organization. Use when user says 'write tests', 'add test coverage', 'test this', creates *.test.ts files, or when test failures appear in CI. Do NOT use for non-test code or for debugging without writing tests. paths: - src/**/__tests__/*.test.ts
Create `src/[module]/__tests__/[module].test.ts`. The parent source file is `src/[module]/[module].ts`.
**Verify**: The `__tests__` directory exists at the same level as the source file being tested.
At the top of every test file, import from `vitest`:
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';Add additional imports based on what you're testing:
**Verify**: All required test utilities are imported before test definitions.
If testing a module that imports other modules you want to mock:
vi.mock('../config.js', () => ({
loadConfig: vi.fn(),
writeConfigFile: vi.fn(),
}));For complex mocks with test-time factory functions (hoisted):
const { mockLoadConfig } = vi.hoisted(() => ({
mockLoadConfig: vi.fn(),
}));
vi.mock('../config.js', () => ({
loadConfig: () => mockLoadConfig(),
}));For unmocking global setup mocks (e.g., to test llm/index.js itself):
vi.unmock('../index.js');Place all `vi.mock()` and `vi.unmock()` calls BEFORE importing the module under test.
**Verify**: Mock declarations appear before the import of the module being tested.
Group related tests with `describe()`:
describe('functionName', () => {
it('returns X when Y', () => {
// test body
});
});**Verify**: Each `it()` test has a clear, complete assertion.
For tests that modify `process.env` or `process.argv`:
describe('config tests', () => {
const originalEnv = process.env;
const originalArgv = process.argv;
beforeEach(() => {
process.env = { ...originalEnv }; // Copy, not reference
process.argv = [...originalArgv];
delete process.env.SPECIFIC_VAR; // Explicitly remove vars to test absence
});
afterEach(() => {
process.env = originalEnv;
process.argv = originalArgv;
});
it('tests env var behavior', () => {
process.env.MY_VAR = 'test';
// test code
});
});**Verify**: `beforeEach` creates a copy of env/argv; `afterEach` restores originals; unused env vars are explicitly deleted with `delete process.env.VAR`.
For file system tests, create temporary directories and clean them up:
describe('file tree', () => {
const dirs: string[] = [];
afterEach(() => {
for (const d of dirs) {
try { fs.rmSync(d, { recursive: true, force: true }); } catch {}
}
dirs.length = 0;
});
it('processes files', () => {
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'caliber-test-'));
dirs.push(tmp);
// use tmp directory
});
});**Verify**: All temporary directories are pushed to a cleanup array and removed in `afterEach`.
Before each test, clear mock call history to avoid pollution between tests:
beforeEach(() => {
vi.clearAllMocks(); // Reset all mock call counts and return values
});
afterEach(() => {
vi.restoreAllMocks(); // Restore original implementations
vi.resetModules(); // Reset cached module imports (if you reload modules)
});**Verify**: `beforeEach` calls `vi.clearAllMocks()` for providers and `afterEach` calls `vi.restoreAllMocks()`.
Write assertions using `expect()`. Match the patterns from existing tests:
// Simple checks
expect(value).toBe(expected);
expect(array).toContain(item);
expect(fn).toThrow('error message');
// Instance checks
expect(obj).toBeInstanceOf(ClassName);
// Mock checks
expect(mockFn).toHaveBeenCalledTimes(1);
expect(mockFn).toHaveBeenCalledWith(arg);
// File system checks
expect(fs.existsSync(path)).toBe(true);**Verify**: Each test has at least one assertion and uses appropriate `expect()` matchers.
Run tests locally before committing:
pnpm test # Run all tests in watch mode pnpm test:coverage # Check coverage thresholds pnpm test -- src/my/path/__tes
Continuously sync your AI setups with one command. Codebase tailor suited agent skills, MCPs and config files for Claude Code, Cursor, and Codex.
Repo: caliber-ai-org/ai-setup
Creates a new CLI command following the Commander.js pattern in src/commands/. Handles…
Discovers and installs community skills from the public registry. Use when the user mentions…
Adds a new LLM provider implementing LLMProvider interface with call() and stream() methods.…
Saves user instructions as persistent learnings for future sessions. Use when the user says…
Add a new deterministic scoring check in src/scoring/checks/ that evaluates config quality.…
Sets up Caliber for automatic AI agent context sync. Installs pre-commit hooks so CLAUDE.md,…