deliberate 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,230 @@
1
+ /**
2
+ * Pattern Matcher - Layer 1 of the classifier
3
+ * Deterministic regex-based detection that cannot be prompt-injected.
4
+ * This is the authoritative layer - if a pattern matches, the result is final.
5
+ */
6
+
7
+ // Known dangerous command patterns
8
+ // NOTE: Patterns are checked in order. More specific patterns should come first.
9
+ // canOverride: false = hard block (catastrophic), true = warn but allow user override
10
+ const DANGEROUS_PATTERNS = [
11
+ // File system destruction - CATASTROPHIC (no override)
12
+ { pattern: /\brm\s+-rf\s+\/\s*$/, risk: 'DANGEROUS', reason: 'Recursive deletion of root filesystem', canOverride: false },
13
+ { pattern: /\brm\s+-rf\s+~\/?\s*$/, risk: 'DANGEROUS', reason: 'Recursive deletion of home directory', canOverride: false },
14
+ { pattern: /\brm\s+-rf\s+\/\*/, risk: 'DANGEROUS', reason: 'Recursive deletion of root filesystem', canOverride: false },
15
+ { pattern: /\brm\s+-rf\s+~\/\*\s*$/, risk: 'DANGEROUS', reason: 'Recursive deletion of entire home directory', canOverride: false },
16
+ // File system destruction - DANGEROUS but overridable (specific paths/files)
17
+ { pattern: /\brm\s+-rf\s+/, risk: 'DANGEROUS', reason: 'Force recursive deletion', canOverride: true },
18
+ { pattern: /\brm\s+(-[rf]+\s+)*[\/~]/, risk: 'DANGEROUS', reason: 'File deletion from root or home', canOverride: true },
19
+ { pattern: /\bmkfs\b/, risk: 'DANGEROUS', reason: 'Filesystem formatting' },
20
+ { pattern: /\bdd\s+if=.*of=\/dev\//, risk: 'DANGEROUS', reason: 'Direct disk write' },
21
+
22
+ // Privilege escalation
23
+ { pattern: /\bsudo\s+/, risk: 'MODERATE', reason: 'Elevated privileges requested' },
24
+ { pattern: /\bsu\s+-?\s*$/, risk: 'MODERATE', reason: 'Switch to root user' },
25
+ { pattern: /\bchmod\s+777\b/, risk: 'DANGEROUS', reason: 'World-writable permissions' },
26
+ { pattern: /\bchmod\s+\+s\b/, risk: 'DANGEROUS', reason: 'SetUID/SetGID bit' },
27
+ { pattern: /\bchown\s+root\b/, risk: 'MODERATE', reason: 'Changing ownership to root' },
28
+
29
+ // Network exfiltration
30
+ { pattern: /\bcurl\s+.*\|\s*(ba)?sh/, risk: 'DANGEROUS', reason: 'Remote code execution via curl pipe' },
31
+ { pattern: /\bwget\s+.*\|\s*(ba)?sh/, risk: 'DANGEROUS', reason: 'Remote code execution via wget pipe' },
32
+ { pattern: /\bcurl\s+.*(-d|--data).*\$\(/, risk: 'DANGEROUS', reason: 'Data exfiltration via curl' },
33
+ { pattern: /\bnc\s+-e\s+\/bin\/(ba)?sh/, risk: 'DANGEROUS', reason: 'Reverse shell' },
34
+
35
+ // Credential access
36
+ { pattern: /\bcat\s+.*\.(pem|key|passwd|shadow)/, risk: 'DANGEROUS', reason: 'Reading sensitive credentials' },
37
+ { pattern: /\/\.ssh\/id_rsa/, risk: 'DANGEROUS', reason: 'Accessing SSH private key' },
38
+ { pattern: /\/\.aws\/credentials/, risk: 'DANGEROUS', reason: 'Accessing AWS credentials' },
39
+ { pattern: /\/\.env\b/, risk: 'MODERATE', reason: 'Accessing environment secrets' },
40
+
41
+ // Token and key file access (cat, less, more, head, tail, etc.)
42
+ { pattern: /\b(cat|less|more|head|tail|bat|view)\s+.*token/i, risk: 'DANGEROUS', reason: 'Reading token file' },
43
+ { pattern: /\b(cat|less|more|head|tail|bat|view)\s+.*secret/i, risk: 'DANGEROUS', reason: 'Reading secrets file' },
44
+ { pattern: /\b(cat|less|more|head|tail|bat|view)\s+.*api[_-]?key/i, risk: 'DANGEROUS', reason: 'Reading API key file' },
45
+ { pattern: /\b(cat|less|more|head|tail|bat|view)\s+.*\.key\b/, risk: 'DANGEROUS', reason: 'Reading key file' },
46
+ { pattern: /\b(cat|less|more|head|tail|bat|view)\s+.*credential/i, risk: 'DANGEROUS', reason: 'Reading credentials file' },
47
+ { pattern: /\b(cat|less|more|head|tail|bat|view)\s+.*password/i, risk: 'DANGEROUS', reason: 'Reading password file' },
48
+ { pattern: /\b(cat|less|more|head|tail|bat|view)\s+.*\.pem\b/, risk: 'DANGEROUS', reason: 'Reading PEM certificate/key' },
49
+ { pattern: /\b(cat|less|more|head|tail|bat|view)\s+.*private/i, risk: 'DANGEROUS', reason: 'Reading private key file' },
50
+ { pattern: /\b(cat|less|more|head|tail|bat|view)\s+.*oauth/i, risk: 'DANGEROUS', reason: 'Reading OAuth token file' },
51
+ { pattern: /\b(cat|less|more|head|tail|bat|view)\s+.*bearer/i, risk: 'DANGEROUS', reason: 'Reading bearer token file' },
52
+
53
+ // Process/system manipulation
54
+ { pattern: /\bkill\s+-9\s+(-1|1)\b/, risk: 'DANGEROUS', reason: 'Killing all processes' },
55
+ { pattern: /\bkillall\b/, risk: 'MODERATE', reason: 'Killing processes by name' },
56
+ { pattern: /:()\{\s*:\|:&\s*\};:/, risk: 'DANGEROUS', reason: 'Fork bomb detected' },
57
+
58
+ // Database destruction
59
+ { pattern: /\bDROP\s+(DATABASE|TABLE)\b/i, risk: 'DANGEROUS', reason: 'Database/table deletion' },
60
+ { pattern: /\bDELETE\s+FROM\s+\w+\s*(;|$)/i, risk: 'DANGEROUS', reason: 'Unconditional DELETE' },
61
+ { pattern: /\bTRUNCATE\s+TABLE\b/i, risk: 'DANGEROUS', reason: 'Table truncation' },
62
+
63
+ // Cloud infrastructure - AWS
64
+ { pattern: /\baws\s+.*\s+delete\b/, risk: 'DANGEROUS', reason: 'AWS resource deletion' },
65
+ { pattern: /\baws\s+s3\s+rm\b/, risk: 'DANGEROUS', reason: 'S3 object/bucket deletion' },
66
+ { pattern: /\baws\s+s3\s+sync\b/, risk: 'MODERATE', reason: 'S3 data sync (potential exfiltration)' },
67
+ { pattern: /\baws\s+ec2\s+terminate-instances\b/, risk: 'DANGEROUS', reason: 'EC2 instance termination' },
68
+ { pattern: /\baws\s+.*--cidr\s+0\.0\.0\.0\/0/, risk: 'DANGEROUS', reason: 'Opening to all IPs (0.0.0.0/0)' },
69
+ { pattern: /\baws\s+secretsmanager\s+get-secret-value\b/, risk: 'MODERATE', reason: 'Reading secrets' },
70
+ { pattern: /\baws\s+ssm\s+get-parameter.*--with-decryption\b/, risk: 'MODERATE', reason: 'Reading encrypted parameters' },
71
+ { pattern: /\baws\s+iam\s+(create-user|create-access-key|attach-.*-policy)\b/, risk: 'DANGEROUS', reason: 'IAM privilege escalation' },
72
+ { pattern: /\baws\s+s3api\s+put-bucket-policy\b/, risk: 'DANGEROUS', reason: 'Modifying bucket permissions' },
73
+ { pattern: /\baws\s+lambda\s+update-function-code\b/, risk: 'MODERATE', reason: 'Lambda code deployment' },
74
+
75
+ // Cloud infrastructure - Terraform/K8s
76
+ { pattern: /\bterraform\s+destroy\b/, risk: 'DANGEROUS', reason: 'Infrastructure destruction' },
77
+ { pattern: /\bkubectl\s+delete\s+(namespace|ns)\b/, risk: 'DANGEROUS', reason: 'Kubernetes namespace deletion' },
78
+ { pattern: /\bkubectl\s+exec\b/, risk: 'MODERATE', reason: 'Kubernetes pod shell access' },
79
+
80
+ // Docker container escapes
81
+ { pattern: /\bdocker\s+run\s+.*-v\s+\/[^:]*:/, risk: 'DANGEROUS', reason: 'Docker host filesystem mount' },
82
+ { pattern: /\bdocker\s+run\s+.*--privileged/, risk: 'DANGEROUS', reason: 'Docker privileged mode' },
83
+
84
+ // Reverse shells (expanded)
85
+ { pattern: /\/dev\/tcp\//, risk: 'DANGEROUS', reason: 'Bash /dev/tcp reverse shell' },
86
+ { pattern: /\bncat\s+-e\s+/, risk: 'DANGEROUS', reason: 'Ncat reverse shell' },
87
+ { pattern: /socket.*connect.*dup2.*subprocess/s, risk: 'DANGEROUS', reason: 'Python reverse shell pattern' },
88
+
89
+ // Remote code execution (expanded)
90
+ { pattern: /\bbash\s+-c\s+.*\$\(curl/, risk: 'DANGEROUS', reason: 'Curl subshell execution' },
91
+ { pattern: /\bbash\s+-c\s+.*\$\(wget/, risk: 'DANGEROUS', reason: 'Wget subshell execution' },
92
+
93
+ // Obfuscation
94
+ { pattern: /base64\s+(-d|--decode).*\|\s*(ba)?sh/, risk: 'DANGEROUS', reason: 'Base64 decoded shell execution' },
95
+ { pattern: /\bxxd\s+-r.*\|\s*(ba)?sh/, risk: 'DANGEROUS', reason: 'Hex decoded shell execution' },
96
+
97
+ // Data exfiltration
98
+ { pattern: /\benv\b.*\|\s*curl/, risk: 'DANGEROUS', reason: 'Environment variable exfiltration' },
99
+ { pattern: /\bscp\s+.*\.ssh/, risk: 'DANGEROUS', reason: 'SSH key exfiltration' },
100
+ { pattern: /\bscp\s+.*\.(pem|key|crt)/, risk: 'DANGEROUS', reason: 'Certificate/key exfiltration' },
101
+
102
+ // Git credential manipulation
103
+ { pattern: /\bgit\s+config\s+.*credential/, risk: 'MODERATE', reason: 'Git credential configuration' },
104
+ ];
105
+
106
+ // Known safe command patterns (skip LLM analysis)
107
+ const SAFE_PATTERNS = [
108
+ { pattern: /^\s*ls(\s+-[alh]+)*\s*$/, reason: 'List directory contents' },
109
+ { pattern: /^\s*pwd\s*$/, reason: 'Print working directory' },
110
+ { pattern: /^\s*echo\s+[^|;&`$]+$/, reason: 'Echo text (simple, no pipes/subshells)' },
111
+ { pattern: /^\s*cat\s+[^|;&]+\.(txt|md|json|ya?ml|js|ts|py)(\s|$)/, reason: 'View text file' },
112
+ { pattern: /^\s*head\s+/, reason: 'View file head' },
113
+ { pattern: /^\s*tail\s+/, reason: 'View file tail' },
114
+ { pattern: /^\s*wc\s+/, reason: 'Word count' },
115
+ { pattern: /^\s*which\s+/, reason: 'Locate command' },
116
+ { pattern: /^\s*whoami\s*$/, reason: 'Current user' },
117
+ { pattern: /^\s*date\s*$/, reason: 'Current date' },
118
+ { pattern: /^\s*git\s+(status|log|diff|branch|show)\b/, reason: 'Git read operation' },
119
+ { pattern: /^\s*npm\s+(list|outdated|--version)\b/, reason: 'NPM info command' },
120
+ { pattern: /^\s*node\s+--version\s*$/, reason: 'Node version check' },
121
+ { pattern: /^\s*python3?\s+--version\s*$/, reason: 'Python version check' },
122
+ ];
123
+
124
+ // File patterns for Write/Edit analysis
125
+ const DANGEROUS_FILE_PATTERNS = [
126
+ { pattern: /\.(pem|key|crt|pfx)$/, risk: 'DANGEROUS', reason: 'Certificate/key file' },
127
+ { pattern: /^\.env/, risk: 'MODERATE', reason: 'Environment configuration' },
128
+ { pattern: /credentials|secrets?|password/i, risk: 'MODERATE', reason: 'Potential secrets file' },
129
+ { pattern: /\/etc\//, risk: 'DANGEROUS', reason: 'System configuration' },
130
+ { pattern: /\/usr\/bin\/|\/usr\/local\/bin\//, risk: 'DANGEROUS', reason: 'System binary location' },
131
+ { pattern: /\.bashrc|\.zshrc|\.profile/, risk: 'MODERATE', reason: 'Shell configuration' },
132
+ { pattern: /crontab|\.cron/, risk: 'MODERATE', reason: 'Scheduled task configuration' },
133
+ ];
134
+
135
+ // Content patterns for Write/Edit analysis
136
+ const DANGEROUS_CONTENT_PATTERNS = [
137
+ { pattern: /eval\s*\(.*\$/, risk: 'DANGEROUS', reason: 'Dynamic code execution' },
138
+ { pattern: /exec\s*\(/, risk: 'MODERATE', reason: 'Process execution' },
139
+ { pattern: /subprocess\.(run|call|Popen)/, risk: 'MODERATE', reason: 'Subprocess execution' },
140
+ { pattern: /os\.system\s*\(/, risk: 'MODERATE', reason: 'System command execution' },
141
+ { pattern: /child_process/, risk: 'MODERATE', reason: 'Child process spawning' },
142
+ { pattern: /dangerouslySetInnerHTML/, risk: 'MODERATE', reason: 'XSS-prone React pattern' },
143
+ { pattern: /innerHTML\s*=/, risk: 'MODERATE', reason: 'Potential XSS vector' },
144
+ { pattern: /SELECT\s+.*\+\s*['"]?\s*\+/, risk: 'DANGEROUS', reason: 'SQL injection pattern' },
145
+ { pattern: /password\s*[:=]\s*['"][^'"]+['"]/, risk: 'DANGEROUS', reason: 'Hardcoded password' },
146
+ { pattern: /api[_-]?key\s*[:=]\s*['"][^'"]+['"]/, risk: 'DANGEROUS', reason: 'Hardcoded API key' },
147
+ { pattern: /BEGIN\s+(RSA|DSA|EC|OPENSSH)\s+PRIVATE\s+KEY/, risk: 'DANGEROUS', reason: 'Private key in code' },
148
+ ];
149
+
150
+ export class PatternMatcher {
151
+ /**
152
+ * Check a command against known patterns
153
+ * @param {string} command - The command to check
154
+ * @returns {{ matched: boolean, risk?: string, reason?: string, source: string }}
155
+ */
156
+ checkCommand(command) {
157
+ // Check dangerous patterns first (order matters - more specific patterns first)
158
+ for (const { pattern, risk, reason, canOverride } of DANGEROUS_PATTERNS) {
159
+ if (pattern.test(command)) {
160
+ return {
161
+ matched: true,
162
+ risk,
163
+ reason,
164
+ source: 'pattern',
165
+ canOverride: canOverride !== undefined ? canOverride : false // Default to false if not specified
166
+ };
167
+ }
168
+ }
169
+
170
+ // Check safe patterns
171
+ for (const { pattern, reason } of SAFE_PATTERNS) {
172
+ if (pattern.test(command)) {
173
+ return {
174
+ matched: true,
175
+ risk: 'SAFE',
176
+ reason,
177
+ source: 'pattern',
178
+ canOverride: false
179
+ };
180
+ }
181
+ }
182
+
183
+ // No pattern match - needs classifier
184
+ return { matched: false, source: 'pattern' };
185
+ }
186
+
187
+ /**
188
+ * Check a file path against known patterns
189
+ * @param {string} filePath - The file path to check
190
+ * @returns {{ matched: boolean, risk?: string, reason?: string, source: string }}
191
+ */
192
+ checkFilePath(filePath) {
193
+ for (const { pattern, risk, reason } of DANGEROUS_FILE_PATTERNS) {
194
+ if (pattern.test(filePath)) {
195
+ return {
196
+ matched: true,
197
+ risk,
198
+ reason,
199
+ source: 'pattern',
200
+ canOverride: false
201
+ };
202
+ }
203
+ }
204
+
205
+ return { matched: false, source: 'pattern' };
206
+ }
207
+
208
+ /**
209
+ * Check file content against known patterns
210
+ * @param {string} content - The file content to check
211
+ * @returns {{ matched: boolean, risk?: string, reason?: string, source: string }}
212
+ */
213
+ checkContent(content) {
214
+ for (const { pattern, risk, reason } of DANGEROUS_CONTENT_PATTERNS) {
215
+ if (pattern.test(content)) {
216
+ return {
217
+ matched: true,
218
+ risk,
219
+ reason,
220
+ source: 'pattern',
221
+ canOverride: false
222
+ };
223
+ }
224
+ }
225
+
226
+ return { matched: false, source: 'pattern' };
227
+ }
228
+ }
229
+
230
+ export default PatternMatcher;
package/src/config.js ADDED
@@ -0,0 +1,207 @@
1
+ /**
2
+ * Configuration management for Deliberate Claude Code
3
+ * Stores user preferences in ~/.deliberate/config.json
4
+ */
5
+
6
+ import fs from 'fs';
7
+ import path from 'path';
8
+ import os from 'os';
9
+
10
+ // Cross-platform home directory
11
+ const HOME_DIR = os.homedir();
12
+ const DELIBERATE_DIR = path.join(HOME_DIR, '.deliberate');
13
+ const CONFIG_FILE = path.join(DELIBERATE_DIR, 'config.json');
14
+
15
+ // Default configuration
16
+ const DEFAULT_CONFIG = {
17
+ llm: {
18
+ provider: null, // 'claude-subscription', 'anthropic', 'ollama', or null
19
+ apiKey: null, // For 'anthropic' provider
20
+ baseUrl: null, // Custom URL (e.g., Ollama endpoint)
21
+ model: null // Model to use
22
+ },
23
+ classifier: {
24
+ serverPort: 8765,
25
+ enabled: true
26
+ },
27
+ blocking: {
28
+ enabled: false, // When true, auto-block high-confidence DANGEROUS operations
29
+ confidenceThreshold: 0.85 // Block if DANGEROUS + confidence > this threshold
30
+ },
31
+ deduplication: {
32
+ enabled: true // When true, don't show same warning twice per session
33
+ }
34
+ };
35
+
36
+ // Provider configurations
37
+ export const LLM_PROVIDERS = {
38
+ 'claude-subscription': {
39
+ name: 'Claude Pro/Max Subscription',
40
+ description: 'Use your Claude Pro or Max subscription (recommended)',
41
+ baseUrl: 'https://api.anthropic.com/v1/messages',
42
+ model: 'claude-sonnet-4-20250514',
43
+ requiresApiKey: false, // Uses OAuth token
44
+ usesOAuth: true
45
+ },
46
+ anthropic: {
47
+ name: 'Anthropic API Key',
48
+ description: 'Use your Anthropic API key directly (pay-per-token)',
49
+ baseUrl: 'https://api.anthropic.com/v1/messages',
50
+ model: 'claude-3-5-haiku-20241022',
51
+ requiresApiKey: true
52
+ },
53
+ ollama: {
54
+ name: 'Ollama (local)',
55
+ description: 'Use a local Ollama model (free, private)',
56
+ baseUrl: 'http://localhost:11434/api/generate',
57
+ model: 'llama3.2',
58
+ requiresApiKey: false
59
+ }
60
+ };
61
+
62
+ /**
63
+ * Ensure the .deliberate directory exists
64
+ */
65
+ function ensureDir() {
66
+ if (!fs.existsSync(DELIBERATE_DIR)) {
67
+ fs.mkdirSync(DELIBERATE_DIR, { recursive: true });
68
+ }
69
+ }
70
+
71
+ /**
72
+ * Load configuration from disk
73
+ * @returns {Object} Configuration object
74
+ */
75
+ export function loadConfig() {
76
+ try {
77
+ if (fs.existsSync(CONFIG_FILE)) {
78
+ const content = fs.readFileSync(CONFIG_FILE, 'utf-8');
79
+ return { ...DEFAULT_CONFIG, ...JSON.parse(content) };
80
+ }
81
+ } catch (error) {
82
+ console.warn('Warning: Could not load config, using defaults');
83
+ }
84
+ return { ...DEFAULT_CONFIG };
85
+ }
86
+
87
+ /**
88
+ * Save configuration to disk
89
+ * @param {Object} config - Configuration object
90
+ */
91
+ export function saveConfig(config) {
92
+ ensureDir();
93
+ fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2));
94
+ }
95
+
96
+ /**
97
+ * Get LLM configuration for hooks
98
+ * Returns environment-variable-friendly format
99
+ * @returns {Object} LLM config with provider, url, key, model
100
+ */
101
+ export function getLLMConfig() {
102
+ const config = loadConfig();
103
+ const llm = config.llm;
104
+
105
+ if (!llm.provider) {
106
+ return null;
107
+ }
108
+
109
+ const providerConfig = LLM_PROVIDERS[llm.provider];
110
+ if (!providerConfig) {
111
+ return null;
112
+ }
113
+
114
+ return {
115
+ provider: llm.provider,
116
+ baseUrl: llm.baseUrl || providerConfig.baseUrl,
117
+ apiKey: llm.apiKey,
118
+ model: llm.model || providerConfig.model
119
+ };
120
+ }
121
+
122
+ /**
123
+ * Set LLM provider configuration
124
+ * @param {string} provider - Provider name
125
+ * @param {Object} options - Additional options (apiKey, baseUrl, model)
126
+ */
127
+ export function setLLMProvider(provider, options = {}) {
128
+ const config = loadConfig();
129
+
130
+ if (!LLM_PROVIDERS[provider]) {
131
+ throw new Error(`Unknown provider: ${provider}`);
132
+ }
133
+
134
+ const providerConfig = LLM_PROVIDERS[provider];
135
+
136
+ config.llm = {
137
+ provider,
138
+ apiKey: options.apiKey || null,
139
+ baseUrl: options.baseUrl || providerConfig.baseUrl,
140
+ model: options.model || providerConfig.model
141
+ };
142
+
143
+ saveConfig(config);
144
+ return config.llm;
145
+ }
146
+
147
+ /**
148
+ * Check if LLM is configured
149
+ * @returns {boolean}
150
+ */
151
+ export function isLLMConfigured() {
152
+ const config = loadConfig();
153
+ return !!config.llm.provider;
154
+ }
155
+
156
+ /**
157
+ * Get the config directory path
158
+ * @returns {string}
159
+ */
160
+ export function getConfigDir() {
161
+ return DELIBERATE_DIR;
162
+ }
163
+
164
+ /**
165
+ * Get the config file path
166
+ * @returns {string}
167
+ */
168
+ export function getConfigFile() {
169
+ return CONFIG_FILE;
170
+ }
171
+
172
+ /**
173
+ * Get blocking configuration
174
+ * @returns {Object} { enabled: boolean, confidenceThreshold: number }
175
+ */
176
+ export function getBlockingConfig() {
177
+ const config = loadConfig();
178
+ return config.blocking || DEFAULT_CONFIG.blocking;
179
+ }
180
+
181
+ /**
182
+ * Set blocking configuration
183
+ * @param {boolean} enabled - Whether auto-blocking is enabled
184
+ * @param {number} confidenceThreshold - Threshold for auto-blocking (0-1)
185
+ */
186
+ export function setBlockingConfig(enabled, confidenceThreshold = 0.85) {
187
+ const config = loadConfig();
188
+ config.blocking = {
189
+ enabled: !!enabled,
190
+ confidenceThreshold: Math.max(0, Math.min(1, confidenceThreshold))
191
+ };
192
+ saveConfig(config);
193
+ return config.blocking;
194
+ }
195
+
196
+ export default {
197
+ loadConfig,
198
+ saveConfig,
199
+ getLLMConfig,
200
+ setLLMProvider,
201
+ isLLMConfigured,
202
+ getConfigDir,
203
+ getConfigFile,
204
+ getBlockingConfig,
205
+ setBlockingConfig,
206
+ LLM_PROVIDERS
207
+ };
package/src/index.js ADDED
@@ -0,0 +1,23 @@
1
+ /**
2
+ * @deliberate/claude-code
3
+ * Security-focused command and file change explanations for Claude Code
4
+ *
5
+ * Main exports for programmatic use
6
+ */
7
+
8
+ // Classifier exports
9
+ export {
10
+ classify,
11
+ quickCheck,
12
+ getStatus,
13
+ preloadModel,
14
+ initialize,
15
+ PatternMatcher,
16
+ ModelClassifier
17
+ } from './classifier/index.js';
18
+
19
+ // Server exports
20
+ export { startServer } from './server.js';
21
+
22
+ // Installer exports
23
+ export { install } from './install.js';