agent-recon 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.
Files changed (44) hide show
  1. package/.claude/hooks/send-event-wsl.py +339 -0
  2. package/.claude/hooks/send-event.py +334 -0
  3. package/CHANGELOG.md +66 -0
  4. package/CONTRIBUTING.md +70 -0
  5. package/EULA.md +223 -0
  6. package/INSTALL.md +193 -0
  7. package/LICENSE +287 -0
  8. package/LICENSE-COMMERCIAL +241 -0
  9. package/PRIVACY.md +115 -0
  10. package/README.md +182 -0
  11. package/SECURITY.md +63 -0
  12. package/TERMS.md +233 -0
  13. package/install-service.ps1 +302 -0
  14. package/installer/cli.js +177 -0
  15. package/installer/detect.js +355 -0
  16. package/installer/install.js +195 -0
  17. package/installer/manifest.js +140 -0
  18. package/installer/package.json +12 -0
  19. package/installer/steps/api-keys.js +59 -0
  20. package/installer/steps/directory.js +41 -0
  21. package/installer/steps/env-report.js +48 -0
  22. package/installer/steps/hooks.js +149 -0
  23. package/installer/steps/service.js +159 -0
  24. package/installer/steps/tls.js +104 -0
  25. package/installer/steps/verify.js +117 -0
  26. package/installer/steps/welcome.js +46 -0
  27. package/installer/ui.js +133 -0
  28. package/installer/uninstall.js +233 -0
  29. package/installer/upgrade.js +289 -0
  30. package/package.json +58 -0
  31. package/public/index.html +13953 -0
  32. package/server/fixtures/allowlist-profiles.json +185 -0
  33. package/server/package.json +34 -0
  34. package/server/platform.js +270 -0
  35. package/server/rules/gitleaks.toml +3214 -0
  36. package/server/rules/security.yara +579 -0
  37. package/server/start.js +178 -0
  38. package/service/agent-recon.service +30 -0
  39. package/service/com.agent-recon.server.plist +56 -0
  40. package/setup-linux.sh +259 -0
  41. package/setup-macos.sh +264 -0
  42. package/setup-wsl.sh +248 -0
  43. package/setup.ps1 +171 -0
  44. package/start-agent-recon.bat +4 -0
@@ -0,0 +1,302 @@
1
+ #Requires -Version 5.1
2
+ <#
3
+ .SYNOPSIS
4
+ Install / uninstall / query the Agent Recon Windows Service.
5
+
6
+ .DESCRIPTION
7
+ Uses NSSM (Non-Sucking Service Manager) to wrap the Node.js process as a
8
+ proper Windows Service that responds to service-control messages. NSSM must
9
+ be installed first (e.g. `choco install nssm` or download from https://nssm.cc).
10
+
11
+ The service runs: node <repo>\server\start.js
12
+ Working directory: <repo>\server
13
+ Service name: AgentRecon
14
+
15
+ .PARAMETER Uninstall
16
+ Remove the AgentRecon service.
17
+
18
+ .PARAMETER Status
19
+ Show current service status and configuration.
20
+
21
+ .EXAMPLE
22
+ # Install (run as Administrator)
23
+ .\install-service.ps1
24
+
25
+ # Check status
26
+ .\install-service.ps1 -Status
27
+
28
+ # Remove
29
+ .\install-service.ps1 -Uninstall
30
+ #>
31
+
32
+ [CmdletBinding(DefaultParameterSetName = 'Install')]
33
+ param(
34
+ [Parameter(ParameterSetName = 'Uninstall')]
35
+ [switch]$Uninstall,
36
+
37
+ [Parameter(ParameterSetName = 'Status')]
38
+ [switch]$Status
39
+ )
40
+
41
+ $ErrorActionPreference = 'Stop'
42
+
43
+ # -- Constants ----------------------------------------------------------------
44
+ $ServiceName = 'AgentRecon'
45
+ $DisplayName = 'Agent Recon - Claude Code Observability'
46
+ $Description = 'Real-time observability dashboard for Claude Code sessions'
47
+ $RepoRoot = $PSScriptRoot
48
+ $ServerDir = Join-Path $RepoRoot 'server'
49
+ $StartScript = Join-Path $ServerDir 'start.js'
50
+
51
+ # -- Helpers ------------------------------------------------------------------
52
+
53
+ function Write-Info { param([string]$Msg) Write-Host " [INFO] $Msg" -ForegroundColor Cyan }
54
+ function Write-Ok { param([string]$Msg) Write-Host " [OK] $Msg" -ForegroundColor Green }
55
+ function Write-Warn { param([string]$Msg) Write-Host " [WARN] $Msg" -ForegroundColor Yellow }
56
+ function Write-Err { param([string]$Msg) Write-Host " [FAIL] $Msg" -ForegroundColor Red }
57
+
58
+ function Assert-Admin {
59
+ $identity = [Security.Principal.WindowsIdentity]::GetCurrent()
60
+ $principal = New-Object Security.Principal.WindowsPrincipal($identity)
61
+ if (-not $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
62
+ Write-Warn 'Not running as Administrator. Relaunching elevated...'
63
+ $argList = '-ExecutionPolicy Bypass -File "' + $PSCommandPath + '"'
64
+ if ($Uninstall) { $argList += ' -Uninstall' }
65
+ if ($Status) { $argList += ' -Status' }
66
+ Start-Process powershell.exe -ArgumentList $argList -Verb RunAs
67
+ exit 0
68
+ }
69
+ }
70
+
71
+ function Find-Nssm {
72
+ $nssm = Get-Command nssm -ErrorAction SilentlyContinue
73
+ if ($nssm) { return $nssm.Source }
74
+
75
+ # Common Chocolatey path
76
+ $chocoPath = Join-Path $env:ProgramData 'chocolatey\bin\nssm.exe'
77
+ if (Test-Path $chocoPath) { return $chocoPath }
78
+
79
+ return $null
80
+ }
81
+
82
+ function Find-Node {
83
+ $node = Get-Command node -ErrorAction SilentlyContinue
84
+ if (-not $node) {
85
+ Write-Err 'Node.js not found on PATH. Install Node.js 22+ and try again.'
86
+ exit 1
87
+ }
88
+ $ver = (& $node.Source --version 2>&1).ToString().Trim()
89
+ Write-Info "Node.js: $($node.Source) ($ver)"
90
+ return $node.Source
91
+ }
92
+
93
+ # -- Status -------------------------------------------------------------------
94
+
95
+ if ($Status) {
96
+ Write-Host ''
97
+ Write-Host "Agent Recon Service Status" -ForegroundColor Cyan
98
+ Write-Host ('-' * 40) -ForegroundColor Cyan
99
+
100
+ $svc = Get-Service -Name $ServiceName -ErrorAction SilentlyContinue
101
+ if (-not $svc) {
102
+ Write-Warn "Service '$ServiceName' is not installed."
103
+ Write-Host ''
104
+ exit 0
105
+ }
106
+
107
+ Write-Info "Name: $($svc.Name)"
108
+ Write-Info "Display Name: $($svc.DisplayName)"
109
+ Write-Info "Status: $($svc.Status)"
110
+ Write-Info "Start Type: $($svc.StartType)"
111
+
112
+ $nssmExe = Find-Nssm
113
+ if ($nssmExe) {
114
+ try {
115
+ $appPath = (& $nssmExe get $ServiceName Application 2>&1).ToString().Trim()
116
+ $appDir = (& $nssmExe get $ServiceName AppDirectory 2>&1).ToString().Trim()
117
+ $appArgs = (& $nssmExe get $ServiceName AppParameters 2>&1).ToString().Trim()
118
+ Write-Info "Application: $appPath"
119
+ Write-Info "Arguments: $appArgs"
120
+ Write-Info "Working Dir: $appDir"
121
+ } catch { }
122
+
123
+ try {
124
+ $stdoutLog = (& $nssmExe get $ServiceName AppStdout 2>&1).ToString().Trim()
125
+ $stderrLog = (& $nssmExe get $ServiceName AppStderr 2>&1).ToString().Trim()
126
+ if ($stdoutLog) { Write-Info "Stdout Log: $stdoutLog" }
127
+ if ($stderrLog) { Write-Info "Stderr Log: $stderrLog" }
128
+ } catch { }
129
+ }
130
+
131
+ Write-Host ''
132
+ Write-Host 'Quick commands:' -ForegroundColor Cyan
133
+ Write-Host " Start: Start-Service $ServiceName"
134
+ Write-Host " Stop: Stop-Service $ServiceName"
135
+ Write-Host " Restart: Restart-Service $ServiceName"
136
+ Write-Host ''
137
+ exit 0
138
+ }
139
+
140
+ # -- Require admin for install / uninstall ------------------------------------
141
+ Assert-Admin
142
+
143
+ # -- Uninstall ----------------------------------------------------------------
144
+
145
+ if ($Uninstall) {
146
+ Write-Host ''
147
+ Write-Host "Removing Agent Recon Service" -ForegroundColor Cyan
148
+ Write-Host ('-' * 40) -ForegroundColor Cyan
149
+
150
+ $svc = Get-Service -Name $ServiceName -ErrorAction SilentlyContinue
151
+ if (-not $svc) {
152
+ Write-Warn "Service '$ServiceName' is not installed. Nothing to remove."
153
+ Write-Host ''
154
+ exit 0
155
+ }
156
+
157
+ # Stop the service if running
158
+ if ($svc.Status -eq 'Running') {
159
+ Write-Info 'Stopping service...'
160
+ Stop-Service -Name $ServiceName -Force
161
+ Start-Sleep -Seconds 2
162
+ Write-Ok 'Service stopped.'
163
+ }
164
+
165
+ $nssmExe = Find-Nssm
166
+ if ($nssmExe) {
167
+ Write-Info 'Removing service via NSSM...'
168
+ & $nssmExe remove $ServiceName confirm
169
+ } else {
170
+ Write-Info 'Removing service via sc.exe...'
171
+ & sc.exe delete $ServiceName
172
+ }
173
+
174
+ # Verify removal
175
+ $svc = Get-Service -Name $ServiceName -ErrorAction SilentlyContinue
176
+ if ($svc) {
177
+ Write-Err "Service still exists. A reboot may be required to complete removal."
178
+ } else {
179
+ Write-Ok "Service '$ServiceName' removed successfully."
180
+ }
181
+ Write-Host ''
182
+ exit 0
183
+ }
184
+
185
+ # -- Install ------------------------------------------------------------------
186
+
187
+ Write-Host ''
188
+ Write-Host 'Installing Agent Recon as Windows Service' -ForegroundColor Cyan
189
+ Write-Host ('-' * 48) -ForegroundColor Cyan
190
+
191
+ # Check prerequisites
192
+ $NodeExe = Find-Node
193
+
194
+ if (-not (Test-Path $StartScript)) {
195
+ Write-Err "start.js not found at: $StartScript"
196
+ Write-Err 'Run this script from the agent-recon repo root.'
197
+ exit 1
198
+ }
199
+
200
+ # Check for existing service
201
+ $existingSvc = Get-Service -Name $ServiceName -ErrorAction SilentlyContinue
202
+ if ($existingSvc) {
203
+ Write-Warn "Service '$ServiceName' already exists (Status: $($existingSvc.Status))."
204
+ Write-Warn "Run .\install-service.ps1 -Uninstall first, then re-install."
205
+ exit 1
206
+ }
207
+
208
+ # Find NSSM
209
+ $NssmExe = Find-Nssm
210
+
211
+ if (-not $NssmExe) {
212
+ Write-Err 'NSSM (Non-Sucking Service Manager) not found.'
213
+ Write-Host ''
214
+ Write-Host ' Windows services must respond to Service Control Manager (SCM) messages.' -ForegroundColor Yellow
215
+ Write-Host ' Node.js does not do this natively, so a service wrapper is required.' -ForegroundColor Yellow
216
+ Write-Host ''
217
+ Write-Host ' Install NSSM using one of these methods:' -ForegroundColor Cyan
218
+ Write-Host ' choco install nssm # via Chocolatey' -ForegroundColor White
219
+ Write-Host ' scoop install nssm # via Scoop' -ForegroundColor White
220
+ Write-Host ' winget install nssm # via WinGet' -ForegroundColor White
221
+ Write-Host ' https://nssm.cc/download # manual download' -ForegroundColor White
222
+ Write-Host ''
223
+ Write-Host ' After installing NSSM, re-run this script.' -ForegroundColor Cyan
224
+ Write-Host ''
225
+ Write-Host ' Alternative: manual service setup without NSSM' -ForegroundColor Cyan
226
+ Write-Host ' ------------------------------------------------' -ForegroundColor Cyan
227
+ Write-Host ' If you prefer not to install NSSM, you can run Agent Recon at startup' -ForegroundColor Yellow
228
+ Write-Host ' using Task Scheduler instead:' -ForegroundColor Yellow
229
+ Write-Host ''
230
+ Write-Host " schtasks /create /tn `"AgentRecon`" /tr `"'$NodeExe' '$StartScript'`" /sc onlogon /rl highest" -ForegroundColor White
231
+ Write-Host ''
232
+ Write-Host ' Or add a shortcut to: shell:startup' -ForegroundColor White
233
+ Write-Host ''
234
+ exit 1
235
+ }
236
+
237
+ Write-Info "NSSM: $NssmExe"
238
+
239
+ # Create log directory
240
+ $LogDir = Join-Path $RepoRoot 'data' 'logs'
241
+ if (-not (Test-Path $LogDir)) {
242
+ New-Item -ItemType Directory -Path $LogDir -Force | Out-Null
243
+ Write-Ok "Created log directory: $LogDir"
244
+ }
245
+
246
+ $StdoutLog = Join-Path $LogDir 'service-stdout.log'
247
+ $StderrLog = Join-Path $LogDir 'service-stderr.log'
248
+
249
+ # Install the service via NSSM
250
+ Write-Info 'Creating service via NSSM...'
251
+ & $NssmExe install $ServiceName $NodeExe $StartScript
252
+ if ($LASTEXITCODE -ne 0) {
253
+ Write-Err "NSSM install failed (exit code $LASTEXITCODE)."
254
+ exit 1
255
+ }
256
+
257
+ # Configure service properties
258
+ Write-Info 'Configuring service properties...'
259
+
260
+ & $NssmExe set $ServiceName DisplayName $DisplayName
261
+ & $NssmExe set $ServiceName Description $Description
262
+ & $NssmExe set $ServiceName AppDirectory $ServerDir
263
+ & $NssmExe set $ServiceName Start SERVICE_DELAYED_AUTO_START
264
+ & $NssmExe set $ServiceName AppStdout $StdoutLog
265
+ & $NssmExe set $ServiceName AppStderr $StderrLog
266
+ & $NssmExe set $ServiceName AppStdoutCreationDisposition 4 # append
267
+ & $NssmExe set $ServiceName AppStderrCreationDisposition 4 # append
268
+ & $NssmExe set $ServiceName AppRotateFiles 1
269
+ & $NssmExe set $ServiceName AppRotateBytes 5242880 # 5 MB
270
+
271
+ # Set environment: PORT=3131
272
+ & $NssmExe set $ServiceName AppEnvironmentExtra 'PORT=3131'
273
+
274
+ Write-Ok "Service '$ServiceName' installed successfully."
275
+
276
+ # -- Post-install instructions ------------------------------------------------
277
+
278
+ Write-Host ''
279
+ Write-Host '+----------------------------------------------------------+' -ForegroundColor Green
280
+ Write-Host '| Agent Recon Windows Service Installed |' -ForegroundColor Green
281
+ Write-Host '+----------------------------------------------------------+' -ForegroundColor Green
282
+ Write-Host ''
283
+ Write-Host ' Service Name: AgentRecon' -ForegroundColor Cyan
284
+ Write-Host " Node.js: $NodeExe"
285
+ Write-Host " Start Script: $StartScript"
286
+ Write-Host " Working Dir: $ServerDir"
287
+ Write-Host " Stdout Log: $StdoutLog"
288
+ Write-Host " Stderr Log: $StderrLog"
289
+ Write-Host ''
290
+ Write-Host ' Quick commands (run as Administrator):' -ForegroundColor Cyan
291
+ Write-Host ' Start-Service AgentRecon # Start the service'
292
+ Write-Host ' Stop-Service AgentRecon # Stop the service'
293
+ Write-Host ' Restart-Service AgentRecon # Restart'
294
+ Write-Host ' Get-Service AgentRecon # Check status'
295
+ Write-Host ' .\install-service.ps1 -Status # Detailed status'
296
+ Write-Host ' .\install-service.ps1 -Uninstall # Remove service'
297
+ Write-Host ''
298
+ Write-Host ' The service is set to start automatically (delayed) on boot.' -ForegroundColor Yellow
299
+ Write-Host ' To start it now: Start-Service AgentRecon' -ForegroundColor Yellow
300
+ Write-Host ''
301
+ Write-Host ' Dashboard: http://localhost:3131' -ForegroundColor Cyan
302
+ Write-Host ''
@@ -0,0 +1,177 @@
1
+ #!/usr/bin/env node
2
+ // Copyright 2026 PNW Great Loop LLC. All rights reserved.
3
+ // Licensed under the Agent Recon™ Commercial License — see LICENSE-COMMERCIAL.
4
+ 'use strict';
5
+
6
+ /**
7
+ * Agent Recon Installer — CLI Entry Point
8
+ *
9
+ * Usage:
10
+ * node cli.js # guided install (default)
11
+ * node cli.js install # guided install
12
+ * node cli.js install --tls # guided install with mkcert TLS pre-selected
13
+ * node cli.js upgrade # upgrade existing installation
14
+ * node cli.js upgrade --tls # add mkcert TLS to existing install
15
+ * node cli.js uninstall # remove Agent Recon
16
+ * node cli.js detect # print environment report and exit
17
+ * node cli.js tls setup # standalone mkcert TLS setup (server must be running)
18
+ * node cli.js tls status # print current TLS status (server must be running)
19
+ * node cli.js --help | -h # print usage
20
+ * node cli.js --version | -v # print version
21
+ */
22
+
23
+ const path = require('path');
24
+ const ui = require('./ui');
25
+
26
+ // Read version from root package.json (the canonical version source)
27
+ function getVersion() {
28
+ try {
29
+ const pkg = require(path.join(__dirname, '..', 'package.json'));
30
+ return pkg.version || '1.0.0';
31
+ } catch {
32
+ return '1.0.0';
33
+ }
34
+ }
35
+
36
+ function printUsage() {
37
+ const version = getVersion();
38
+ console.log(`
39
+ ${ui.bold('Agent Recon')}${ui.cyan('™')} Installer v${version}
40
+
41
+ ${ui.bold('Usage:')}
42
+ node cli.js [command]
43
+
44
+ ${ui.bold('Commands:')}
45
+ install Guided installation (default)
46
+ upgrade Upgrade an existing installation
47
+ uninstall Remove Agent Recon™
48
+ detect Print environment detection report
49
+ tls setup Configure mkcert TLS (server must be running)
50
+ tls status Show current TLS status (server must be running)
51
+
52
+ ${ui.bold('Options:')}
53
+ --help, -h Show this help message
54
+ --version, -v Show version number
55
+ --force Force operation (skip version check on upgrade)
56
+ --tls Pre-select mkcert TLS during install/upgrade
57
+ `);
58
+ }
59
+
60
+ async function main() {
61
+ const args = process.argv.slice(2);
62
+ const command = args[0] || 'install';
63
+ const force = args.includes('--force');
64
+ const tlsFlag = args.includes('--tls');
65
+
66
+ if (command === '--help' || command === '-h') {
67
+ printUsage();
68
+ return;
69
+ }
70
+
71
+ if (command === '--version' || command === '-v') {
72
+ console.log(getVersion());
73
+ return;
74
+ }
75
+
76
+ // Run environment detection (needed by all commands)
77
+ const { detectEnv } = require('./detect');
78
+ const envReport = await detectEnv();
79
+
80
+ switch (command) {
81
+ case 'detect': {
82
+ ui.banner(getVersion());
83
+ ui.printEnvReport(envReport);
84
+ return;
85
+ }
86
+
87
+ case 'install': {
88
+ // If existing install detected, suggest upgrade instead
89
+ if (envReport.existingInstall && envReport.existingInstall.manifestPath) {
90
+ ui.warn('An existing Agent Recon™ installation was detected.');
91
+ ui.info(`Version: ${envReport.existingInstall.version || 'unknown'}`);
92
+ ui.info(`Location: ${envReport.existingInstall.installDir || 'unknown'}`);
93
+ ui.info('Run "node cli.js upgrade" to upgrade, or "node cli.js install --force" to reinstall.');
94
+ if (!force) return;
95
+ }
96
+ const install = require('./install');
97
+ await install(envReport, { version: getVersion(), force, tls: tlsFlag });
98
+ return;
99
+ }
100
+
101
+ case 'upgrade': {
102
+ const upgrade = require('./upgrade');
103
+ await upgrade(envReport, { version: getVersion(), force, tls: tlsFlag });
104
+ return;
105
+ }
106
+
107
+ case 'tls': {
108
+ const sub = args[1];
109
+ if (sub === 'setup') {
110
+ await _tlsSetup();
111
+ } else if (sub === 'status') {
112
+ await _tlsStatus();
113
+ } else {
114
+ ui.error(`Unknown tls subcommand: ${sub || '(none)'}`);
115
+ ui.info('Usage: node cli.js tls setup | tls status');
116
+ process.exitCode = 1;
117
+ }
118
+ return;
119
+ }
120
+
121
+ case 'uninstall': {
122
+ const uninstall = require('./uninstall');
123
+ await uninstall(envReport);
124
+ return;
125
+ }
126
+
127
+ default:
128
+ ui.error(`Unknown command: ${command}`);
129
+ printUsage();
130
+ process.exitCode = 1;
131
+ }
132
+ }
133
+
134
+ async function _tlsSetup() {
135
+ ui.banner(getVersion());
136
+ ui.info('Configuring mkcert TLS via server API...');
137
+ try {
138
+ const r = await fetch('http://localhost:3131/api/settings', {
139
+ method: 'POST',
140
+ headers: { 'Content-Type': 'application/json' },
141
+ body: JSON.stringify({ key: 'tls_enabled', value: 'true' }),
142
+ });
143
+ if (!r.ok) throw new Error(`HTTP ${r.status}`);
144
+ const r2 = await fetch('http://localhost:3131/api/settings', {
145
+ method: 'POST',
146
+ headers: { 'Content-Type': 'application/json' },
147
+ body: JSON.stringify({ key: 'tls_mode', value: 'mkcert' }),
148
+ });
149
+ if (!r2.ok) throw new Error(`HTTP ${r2.status}`);
150
+ ui.ok('TLS enabled with mkcert mode. Restart the server to activate HTTPS.');
151
+ ui.info('If mkcert is not installed, install it and run: mkcert -install');
152
+ } catch (err) {
153
+ ui.error(`Could not reach server at localhost:3131: ${err.message}`);
154
+ ui.info('Make sure the Agent Recon™ server is running first.');
155
+ }
156
+ }
157
+
158
+ async function _tlsStatus() {
159
+ try {
160
+ const r = await fetch('http://localhost:3131/api/tls-status');
161
+ if (!r.ok) throw new Error(`HTTP ${r.status}`);
162
+ const data = await r.json();
163
+ console.log(`TLS status: ${data.status}`);
164
+ if (data.hint) console.log(`Hint: ${data.hint}`);
165
+ if (data.valid_to) console.log(`Valid until: ${data.valid_to}`);
166
+ if (data.days_remaining != null) console.log(`Days remaining: ${data.days_remaining}`);
167
+ } catch (err) {
168
+ ui.error(`Could not reach server at localhost:3131: ${err.message}`);
169
+ ui.info('Make sure the Agent Recon™ server is running first.');
170
+ }
171
+ }
172
+
173
+ main().catch(err => {
174
+ ui.error(err.message || String(err));
175
+ if (process.env.AGENT_RECON_DEBUG) console.error(err);
176
+ process.exitCode = 1;
177
+ });