Architecture Overview
High-Level Flow
flowchart TB
subgraph Cursor IDE
A[Developer Prompt] --> B[beforeSubmitPrompt]
B -->|allow| C[AI Agent]
B -->|block| D[Block Message]
C --> E[AI Response]
E --> F[afterAgentResponse]
F -->|allow| G[Display Response]
F -->|block| H[Block Message]
end
subgraph AIRS Hooks
B --> I[Config Loader]
I --> J[Scanner]
J --> K[AIRS Client]
K --> L[Circuit Breaker]
L --> M[Prisma AIRS API]
F --> I
F --> N[Code Extractor]
N --> J
end
Module Map
| Module |
Purpose |
src/config.ts |
Load and validate airs-config.json with env var resolution |
src/airs-client.ts |
SDK wrapper with circuit breaker integration |
src/scanner.ts |
Scan orchestration, DLP masking, UX block messages |
src/code-extractor.ts |
Extract code blocks from AI responses |
src/logger.ts |
Structured JSON Lines logging with rotation |
src/circuit-breaker.ts |
Failure tracking, cooldown bypass, automatic recovery |
src/dlp-masking.ts |
Per-service enforcement actions (block/mask/allow) |
src/log-rotation.ts |
Log file rotation at 10MB threshold |
src/types.ts |
TypeScript interfaces for config, Cursor API, AIRS |
src/hooks/before-submit-prompt.ts |
Cursor beforeSubmitPrompt entry point |
src/hooks/after-agent-response.ts |
Cursor afterAgentResponse entry point |
Request Lifecycle
Prompt Scan (beforeSubmitPrompt)
- Cursor pipes
{ prompt, user_email, ... } as JSON to stdin
- Hook loads config, initializes logger
- Scanner sends prompt to AIRS via SDK (
prompt content key)
- Circuit breaker gates the request (bypass if open)
- AIRS returns verdict + detections
- If
enforce mode and verdict is block: output { "continue": false, "user_message": "..." }
- If
observe or verdict is allow: output { "continue": true }
Response Scan (afterAgentResponse)
- Cursor pipes
{ text, ... } as JSON to stdin
- Hook loads config, initializes logger
- Code extractor splits response into natural language + code blocks
- Scanner sends both to AIRS (
response + code_response content keys)
code_response triggers WildFire/ATP malicious code detection
- If blocked: output
{ "permission": "deny" } + exit code 2
- If allowed: output
{ "permission": "allow" }
Build Modes
| Mode |
Command |
Hook Execution |
Startup |
| Production |
node dist/hooks/*.js |
Precompiled JS |
~800ms |
| Development |
npx tsx src/hooks/*.ts |
JIT TypeScript |
~2.5s |
The install-hooks script points at compiled JS by default. See Contributing for the development workflow.