Files
admin b723e2bd7d Reorganize: Move all skills to skills/ folder
- Created skills/ directory
- Moved 272 skills to skills/ subfolder
- Kept agents/ at root level
- Kept installation scripts and docs at root level

Repository structure:
- skills/           - All 272 skills from skills.sh
- agents/           - Agent definitions
- *.sh, *.ps1       - Installation scripts
- README.md, etc.   - Documentation

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-23 18:05:17 +00:00

85 lines
2.8 KiB
TypeScript

import { describe, expect, test } from 'bun:test';
async function runGeminiHook(
input: object,
): Promise<{ stdout: string; stderr: string; exitCode: number }> {
const proc = Bun.spawn(['bun', 'src/bin/cc-safety-net.ts', '-gc'], {
stdin: 'pipe',
stdout: 'pipe',
stderr: 'pipe',
});
proc.stdin.write(JSON.stringify(input));
proc.stdin.end();
const stdoutPromise = new Response(proc.stdout).text();
const stderrPromise = new Response(proc.stderr).text();
const [stdout, stderr] = await Promise.all([stdoutPromise, stderrPromise]);
const exitCode = await proc.exited;
return { stdout: stdout.trim(), stderr: stderr.trim(), exitCode };
}
describe('Gemini CLI hook', () => {
describe('input parsing', () => {
test('blocks rm -rf via run_shell_command', async () => {
const input = {
hook_event_name: 'BeforeTool',
tool_name: 'run_shell_command',
tool_input: { command: 'rm -rf /' },
};
const { stdout, exitCode } = await runGeminiHook(input);
expect(exitCode).toBe(0);
const output = JSON.parse(stdout);
expect(output.decision).toBe('deny');
expect(output.reason).toContain('rm -rf');
});
test('allows safe commands (no output)', async () => {
const input = {
hook_event_name: 'BeforeTool',
tool_name: 'run_shell_command',
tool_input: { command: 'ls -la' },
};
const { stdout, exitCode } = await runGeminiHook(input);
expect(exitCode).toBe(0);
expect(stdout).toBe(''); // No output means allowed
});
test('ignores non-BeforeTool events', async () => {
const input = {
hook_event_name: 'AfterTool',
tool_name: 'run_shell_command',
tool_input: { command: 'rm -rf /' },
};
const { stdout, exitCode } = await runGeminiHook(input);
expect(exitCode).toBe(0);
expect(stdout).toBe(''); // Ignored, not blocked
});
test('ignores non-shell tools', async () => {
const input = {
hook_event_name: 'BeforeTool',
tool_name: 'write_file',
tool_input: { path: '/etc/passwd' },
};
const { stdout, exitCode } = await runGeminiHook(input);
expect(exitCode).toBe(0);
expect(stdout).toBe(''); // Ignored, not blocked
});
});
describe('output format', () => {
test('outputs Gemini format with decision: deny', async () => {
const input = {
hook_event_name: 'BeforeTool',
tool_name: 'run_shell_command',
tool_input: { command: 'git reset --hard' },
};
const { stdout, exitCode } = await runGeminiHook(input);
expect(exitCode).toBe(0);
const output = JSON.parse(stdout);
expect(output).toHaveProperty('decision', 'deny');
expect(output).toHaveProperty('reason');
expect(output.reason).toContain('git reset --hard');
});
});
});