argus-code 0.4.4__tar.gz → 0.5.0__tar.gz
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.
- argus_code-0.5.0/.github/workflows/test.yml +74 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/.gitignore +8 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/AGENTS.md +5 -4
- {argus_code-0.4.4 → argus_code-0.5.0}/ARCHITECTURE.md +29 -15
- {argus_code-0.4.4 → argus_code-0.5.0}/CONTRIBUTING.md +30 -8
- argus_code-0.5.0/PKG-INFO +301 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/PRD.md +7 -0
- argus_code-0.5.0/README.md +249 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/TESTING.md +22 -0
- argus_code-0.5.0/dashboard/AGENTS.md +73 -0
- argus_code-0.5.0/dashboard/e2e/smoke.spec.ts +35 -0
- argus_code-0.5.0/dashboard/index.html +12 -0
- argus_code-0.5.0/dashboard/package-lock.json +4414 -0
- argus_code-0.5.0/dashboard/package.json +44 -0
- argus_code-0.5.0/dashboard/playwright.config.ts +17 -0
- argus_code-0.5.0/dashboard/scripts/size.mjs +19 -0
- argus_code-0.5.0/dashboard/src/App.test.tsx +15 -0
- argus_code-0.5.0/dashboard/src/app/queryClient.ts +5 -0
- argus_code-0.5.0/dashboard/src/app/router.tsx +19 -0
- argus_code-0.5.0/dashboard/src/app/shell/CommandPalette.test.tsx +16 -0
- argus_code-0.5.0/dashboard/src/app/shell/CommandPalette.tsx +52 -0
- argus_code-0.5.0/dashboard/src/app/shell/Shell.tsx +13 -0
- argus_code-0.5.0/dashboard/src/app/shell/Sidebar.test.tsx +21 -0
- argus_code-0.5.0/dashboard/src/app/shell/Sidebar.tsx +74 -0
- argus_code-0.5.0/dashboard/src/app/shell/TopBar.tsx +28 -0
- argus_code-0.5.0/dashboard/src/components/charts/AlertStrip.tsx +22 -0
- argus_code-0.5.0/dashboard/src/components/charts/AreaLine.test.tsx +14 -0
- argus_code-0.5.0/dashboard/src/components/charts/AreaLine.tsx +50 -0
- argus_code-0.5.0/dashboard/src/components/charts/Bars.test.tsx +12 -0
- argus_code-0.5.0/dashboard/src/components/charts/Bars.tsx +28 -0
- argus_code-0.5.0/dashboard/src/components/charts/CalendarHeatmap.test.tsx +8 -0
- argus_code-0.5.0/dashboard/src/components/charts/CalendarHeatmap.tsx +30 -0
- argus_code-0.5.0/dashboard/src/components/charts/ChartTable.tsx +40 -0
- argus_code-0.5.0/dashboard/src/components/charts/GridHeatmap.tsx +27 -0
- argus_code-0.5.0/dashboard/src/components/charts/Legend.tsx +12 -0
- argus_code-0.5.0/dashboard/src/components/charts/Meter.test.tsx +8 -0
- argus_code-0.5.0/dashboard/src/components/charts/Meter.tsx +21 -0
- argus_code-0.5.0/dashboard/src/components/charts/Minimap.test.tsx +17 -0
- argus_code-0.5.0/dashboard/src/components/charts/Minimap.tsx +35 -0
- argus_code-0.5.0/dashboard/src/components/charts/MultiLine.tsx +5 -0
- argus_code-0.5.0/dashboard/src/components/charts/README.md +22 -0
- argus_code-0.5.0/dashboard/src/components/charts/Scatter.tsx +83 -0
- argus_code-0.5.0/dashboard/src/components/charts/Sparkline.tsx +14 -0
- argus_code-0.5.0/dashboard/src/components/charts/StackedColumns.tsx +67 -0
- argus_code-0.5.0/dashboard/src/components/charts/UPlotChart.tsx +36 -0
- argus_code-0.5.0/dashboard/src/components/charts/ramp.ts +3 -0
- argus_code-0.5.0/dashboard/src/components/charts/uplotTheme.ts +14 -0
- argus_code-0.5.0/dashboard/src/components/ui/Button.tsx +18 -0
- argus_code-0.5.0/dashboard/src/components/ui/Chip.tsx +16 -0
- argus_code-0.5.0/dashboard/src/components/ui/CopyId.tsx +28 -0
- argus_code-0.5.0/dashboard/src/components/ui/DataTable.tsx +70 -0
- argus_code-0.5.0/dashboard/src/components/ui/EmptyState.tsx +6 -0
- argus_code-0.5.0/dashboard/src/components/ui/ErrorPanel.tsx +5 -0
- argus_code-0.5.0/dashboard/src/components/ui/Icon.tsx +30 -0
- argus_code-0.5.0/dashboard/src/components/ui/Kbd.tsx +3 -0
- argus_code-0.5.0/dashboard/src/components/ui/Panel.tsx +18 -0
- argus_code-0.5.0/dashboard/src/components/ui/Pill.test.tsx +11 -0
- argus_code-0.5.0/dashboard/src/components/ui/Pill.tsx +24 -0
- argus_code-0.5.0/dashboard/src/components/ui/Seg.test.tsx +10 -0
- argus_code-0.5.0/dashboard/src/components/ui/Seg.tsx +18 -0
- argus_code-0.5.0/dashboard/src/components/ui/Skeleton.tsx +3 -0
- argus_code-0.5.0/dashboard/src/components/ui/Tile.test.tsx +23 -0
- argus_code-0.5.0/dashboard/src/components/ui/Tile.tsx +28 -0
- argus_code-0.5.0/dashboard/src/features/alerts/AlertsPage.tsx +91 -0
- argus_code-0.5.0/dashboard/src/features/budgets/BudgetsPage.tsx +26 -0
- argus_code-0.5.0/dashboard/src/features/models/ModelsPage.tsx +83 -0
- argus_code-0.5.0/dashboard/src/features/overview/AttentionStrip.tsx +40 -0
- argus_code-0.5.0/dashboard/src/features/overview/OverviewPage.tsx +113 -0
- argus_code-0.5.0/dashboard/src/features/overview/TopSessions.tsx +45 -0
- argus_code-0.5.0/dashboard/src/features/overview/useOverviewModel.test.ts +31 -0
- argus_code-0.5.0/dashboard/src/features/overview/useOverviewModel.ts +57 -0
- argus_code-0.5.0/dashboard/src/features/search/SearchPage.tsx +112 -0
- argus_code-0.5.0/dashboard/src/features/search/cleanSnippet.test.ts +11 -0
- argus_code-0.5.0/dashboard/src/features/search/cleanSnippet.ts +24 -0
- argus_code-0.5.0/dashboard/src/features/session/OverviewTab.tsx +61 -0
- argus_code-0.5.0/dashboard/src/features/session/SessionPage.tsx +88 -0
- argus_code-0.5.0/dashboard/src/features/session/SubagentsTab.tsx +183 -0
- argus_code-0.5.0/dashboard/src/features/session/TimelineTab.tsx +139 -0
- argus_code-0.5.0/dashboard/src/features/session/model.test.ts +22 -0
- argus_code-0.5.0/dashboard/src/features/session/model.ts +37 -0
- argus_code-0.5.0/dashboard/src/features/sessions/AnalysisStrip.tsx +67 -0
- argus_code-0.5.0/dashboard/src/features/sessions/SessionsPage.tsx +66 -0
- argus_code-0.5.0/dashboard/src/features/sessions/SessionsTable.tsx +44 -0
- argus_code-0.5.0/dashboard/src/features/sessions/filters.test.ts +15 -0
- argus_code-0.5.0/dashboard/src/features/sessions/filters.ts +19 -0
- argus_code-0.5.0/dashboard/src/features/settings/SettingsPage.tsx +89 -0
- argus_code-0.5.0/dashboard/src/features/tools/ToolsPage.tsx +86 -0
- argus_code-0.5.0/dashboard/src/features/tools/toolsOverTime.test.ts +15 -0
- argus_code-0.5.0/dashboard/src/features/tools/toolsOverTime.ts +29 -0
- argus_code-0.5.0/dashboard/src/features/trends/TrendsPage.tsx +101 -0
- argus_code-0.5.0/dashboard/src/lib/analysis/composition.test.ts +7 -0
- argus_code-0.5.0/dashboard/src/lib/analysis/composition.ts +14 -0
- argus_code-0.5.0/dashboard/src/lib/analysis/cumulative.test.ts +3 -0
- argus_code-0.5.0/dashboard/src/lib/analysis/cumulative.ts +4 -0
- argus_code-0.5.0/dashboard/src/lib/analysis/deltas.test.ts +14 -0
- argus_code-0.5.0/dashboard/src/lib/analysis/deltas.ts +13 -0
- argus_code-0.5.0/dashboard/src/lib/analysis/hourWeekday.test.ts +9 -0
- argus_code-0.5.0/dashboard/src/lib/analysis/hourWeekday.ts +13 -0
- argus_code-0.5.0/dashboard/src/lib/analysis/rollups.test.ts +43 -0
- argus_code-0.5.0/dashboard/src/lib/analysis/rollups.ts +49 -0
- argus_code-0.5.0/dashboard/src/lib/analysis/series.test.ts +25 -0
- argus_code-0.5.0/dashboard/src/lib/analysis/series.ts +32 -0
- argus_code-0.5.0/dashboard/src/lib/analysis/testutil.ts +23 -0
- argus_code-0.5.0/dashboard/src/lib/analysis/trendsMetrics.test.ts +31 -0
- argus_code-0.5.0/dashboard/src/lib/analysis/trendsMetrics.ts +53 -0
- argus_code-0.5.0/dashboard/src/lib/analysis/windows.test.ts +19 -0
- argus_code-0.5.0/dashboard/src/lib/analysis/windows.ts +33 -0
- argus_code-0.5.0/dashboard/src/lib/api/__fixtures__/alerts.json +1 -0
- argus_code-0.5.0/dashboard/src/lib/api/__fixtures__/overview.json +1 -0
- argus_code-0.5.0/dashboard/src/lib/api/__fixtures__/sessions.json +1 -0
- argus_code-0.5.0/dashboard/src/lib/api/__fixtures__/timeline.json +2785 -0
- argus_code-0.5.0/dashboard/src/lib/api/__fixtures__/tools-overview.json +1 -0
- argus_code-0.5.0/dashboard/src/lib/api/__fixtures__/trends.json +1 -0
- argus_code-0.5.0/dashboard/src/lib/api/client.test.ts +26 -0
- argus_code-0.5.0/dashboard/src/lib/api/client.ts +68 -0
- argus_code-0.5.0/dashboard/src/lib/api/hooks.ts +29 -0
- argus_code-0.5.0/dashboard/src/lib/api/schemas.ts +195 -0
- argus_code-0.5.0/dashboard/src/lib/format/format.test.ts +54 -0
- argus_code-0.5.0/dashboard/src/lib/format/format.ts +51 -0
- argus_code-0.5.0/dashboard/src/main.tsx +18 -0
- argus_code-0.5.0/dashboard/src/routeTree.gen.ts +294 -0
- argus_code-0.5.0/dashboard/src/routes/__root.tsx +10 -0
- argus_code-0.5.0/dashboard/src/routes/alerts.tsx +3 -0
- argus_code-0.5.0/dashboard/src/routes/budgets.tsx +3 -0
- argus_code-0.5.0/dashboard/src/routes/index.tsx +3 -0
- argus_code-0.5.0/dashboard/src/routes/models.tsx +3 -0
- argus_code-0.5.0/dashboard/src/routes/prompts.tsx +8 -0
- argus_code-0.5.0/dashboard/src/routes/search.tsx +3 -0
- argus_code-0.5.0/dashboard/src/routes/session.tsx +10 -0
- argus_code-0.5.0/dashboard/src/routes/sessions.$id.tsx +9 -0
- argus_code-0.5.0/dashboard/src/routes/sessions.index.tsx +3 -0
- argus_code-0.5.0/dashboard/src/routes/settings.tsx +3 -0
- argus_code-0.5.0/dashboard/src/routes/tools.tsx +3 -0
- argus_code-0.5.0/dashboard/src/routes/trends.tsx +3 -0
- argus_code-0.5.0/dashboard/src/styles.css +62 -0
- argus_code-0.5.0/dashboard/tsconfig.json +18 -0
- argus_code-0.5.0/dashboard/vite.config.ts +19 -0
- argus_code-0.5.0/dashboard/vitest.config.ts +15 -0
- argus_code-0.5.0/dashboard/vitest.setup.ts +25 -0
- argus_code-0.5.0/dashboard-dist/assets/AlertsPage-Cs8_bu24.js +1 -0
- argus_code-0.5.0/dashboard-dist/assets/AreaLine-VUt7zZPY.js +1 -0
- argus_code-0.5.0/dashboard-dist/assets/AttentionStrip-uulCqq7B.js +1 -0
- argus_code-0.5.0/dashboard-dist/assets/Bars-gdNIlXNl.js +1 -0
- argus_code-0.5.0/dashboard-dist/assets/BudgetsPage-DNk4EMLO.js +1 -0
- argus_code-0.5.0/dashboard-dist/assets/Button-BqHL1YGs.js +1 -0
- argus_code-0.5.0/dashboard-dist/assets/ChartTable-C2SF4hxC.js +1 -0
- argus_code-0.5.0/dashboard-dist/assets/Chip-CSAZEvs5.js +1 -0
- argus_code-0.5.0/dashboard-dist/assets/ErrorPanel-YJvBzoti.js +1 -0
- argus_code-0.5.0/dashboard-dist/assets/ModelsPage-CC5HgXSC.js +1 -0
- argus_code-0.5.0/dashboard-dist/assets/MultiLine-DaOioHM_.js +1 -0
- argus_code-0.5.0/dashboard-dist/assets/OverviewPage-DtYtpPeA.js +1 -0
- argus_code-0.5.0/dashboard-dist/assets/Panel-C0lmkoau.js +1 -0
- argus_code-0.5.0/dashboard-dist/assets/Pill-BaEMC6Uo.js +1 -0
- argus_code-0.5.0/dashboard-dist/assets/SearchPage-DENLda5C.js +1 -0
- argus_code-0.5.0/dashboard-dist/assets/SessionPage-h4KU-Iel.js +2 -0
- argus_code-0.5.0/dashboard-dist/assets/SessionsPage-BQOKS0MJ.js +4 -0
- argus_code-0.5.0/dashboard-dist/assets/SettingsPage-JyOusfCm.js +1 -0
- argus_code-0.5.0/dashboard-dist/assets/StackedColumns-D_Ewnsrg.js +1 -0
- argus_code-0.5.0/dashboard-dist/assets/Tile-kzNeIivi.js +1 -0
- argus_code-0.5.0/dashboard-dist/assets/TimelineTab-D86rkM-N.js +1 -0
- argus_code-0.5.0/dashboard-dist/assets/ToolsPage-DAKkhNxC.js +1 -0
- argus_code-0.5.0/dashboard-dist/assets/TrendsPage-tRubbqz4.js +1 -0
- argus_code-0.5.0/dashboard-dist/assets/cumulative-C3-3HW0n.js +1 -0
- argus_code-0.5.0/dashboard-dist/assets/ibm-plex-mono-latin-400-normal-CvHOgSBP.woff +0 -0
- argus_code-0.5.0/dashboard-dist/assets/ibm-plex-mono-latin-400-normal-DMJ8VG8y.woff2 +0 -0
- argus_code-0.5.0/dashboard-dist/assets/ibm-plex-mono-latin-500-normal-CB9ihrfo.woff +0 -0
- argus_code-0.5.0/dashboard-dist/assets/ibm-plex-mono-latin-500-normal-DSY6xOcd.woff2 +0 -0
- argus_code-0.5.0/dashboard-dist/assets/ibm-plex-sans-latin-400-normal-CDDApCn2.woff2 +0 -0
- argus_code-0.5.0/dashboard-dist/assets/ibm-plex-sans-latin-400-normal-CYLoc0-x.woff +0 -0
- argus_code-0.5.0/dashboard-dist/assets/ibm-plex-sans-latin-500-normal-6ng42L7E.woff2 +0 -0
- argus_code-0.5.0/dashboard-dist/assets/ibm-plex-sans-latin-500-normal-BgVn5rGT.woff +0 -0
- argus_code-0.5.0/dashboard-dist/assets/ibm-plex-sans-latin-600-normal-Cu4Hd6ag.woff +0 -0
- argus_code-0.5.0/dashboard-dist/assets/ibm-plex-sans-latin-600-normal-CuJfVYMP.woff2 +0 -0
- argus_code-0.5.0/dashboard-dist/assets/index-CiLtq5Ja.js +50 -0
- argus_code-0.5.0/dashboard-dist/assets/index-DwJcAbKT.css +1 -0
- argus_code-0.5.0/dashboard-dist/assets/rollups-C1zMwbci.js +1 -0
- argus_code-0.5.0/dashboard-dist/assets/series-BjP-80tt.js +1 -0
- argus_code-0.5.0/dashboard-dist/assets/uplotTheme-D1GxaB_c.css +1 -0
- argus_code-0.5.0/dashboard-dist/assets/uplotTheme-dVdt58Jw.js +3 -0
- argus_code-0.5.0/dashboard-dist/assets/windows-7ctt19Z4.js +1 -0
- argus_code-0.5.0/dashboard-dist/index.html +13 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/pyproject.toml +1 -1
- {argus_code-0.4.4 → argus_code-0.5.0}/python/argus/__init__.py +1 -1
- {argus_code-0.4.4 → argus_code-0.5.0}/python/argus/adapters/AGENTS.md +57 -44
- {argus_code-0.4.4 → argus_code-0.5.0}/python/argus/adapters/claude_code/extract_tool_calls.py +6 -1
- {argus_code-0.4.4 → argus_code-0.5.0}/python/argus/adapters/claude_code/extract_turns.py +9 -1
- {argus_code-0.4.4 → argus_code-0.5.0}/python/argus/collector/AGENTS.md +13 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/python/argus/collector/first_run.py +114 -5
- {argus_code-0.4.4 → argus_code-0.5.0}/python/argus/core/runtime.py +6 -1
- {argus_code-0.4.4 → argus_code-0.5.0}/python/argus/server/AGENTS.md +56 -46
- {argus_code-0.4.4 → argus_code-0.5.0}/python/argus/server/api.py +54 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/python/argus/server/app.py +25 -1
- {argus_code-0.4.4 → argus_code-0.5.0}/python/argus/store/AGENTS.md +4 -1
- {argus_code-0.4.4 → argus_code-0.5.0}/python/argus/store/repository.py +69 -4
- {argus_code-0.4.4 → argus_code-0.5.0}/tests/AGENTS.md +18 -2
- {argus_code-0.4.4 → argus_code-0.5.0}/tests/adapters/claude_code/test_extract_tool_calls.py +12 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/tests/adapters/claude_code/test_extract_turns.py +29 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/tests/collector/test_first_run.py +103 -2
- argus_code-0.5.0/tests/collector/test_first_run_shutdown.py +87 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/tests/collector/test_scheduler.py +10 -3
- {argus_code-0.4.4 → argus_code-0.5.0}/tests/conftest.py +9 -0
- argus_code-0.5.0/tests/dashboard/test_no_raw_html.py +43 -0
- argus_code-0.5.0/tests/server/test_read_cache.py +77 -0
- argus_code-0.5.0/tests/server/test_spa_fallback.py +68 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/tests/store/test_repository.py +55 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/uv.lock +983 -983
- argus_code-0.4.4/PKG-INFO +0 -312
- argus_code-0.4.4/README.md +0 -260
- argus_code-0.4.4/dashboard/AGENTS.md +0 -35
- argus_code-0.4.4/dashboard/astro.config.mjs +0 -9
- argus_code-0.4.4/dashboard/package-lock.json +0 -4787
- argus_code-0.4.4/dashboard/package.json +0 -18
- argus_code-0.4.4/dashboard/public/styles/global.css +0 -307
- argus_code-0.4.4/dashboard/src/layouts/Default.astro +0 -68
- argus_code-0.4.4/dashboard/src/pages/index.astro +0 -129
- argus_code-0.4.4/dashboard/src/pages/models.astro +0 -131
- argus_code-0.4.4/dashboard/src/pages/prompts.astro +0 -407
- argus_code-0.4.4/dashboard/src/pages/session.astro +0 -568
- argus_code-0.4.4/dashboard/src/pages/sessions/index.astro +0 -87
- argus_code-0.4.4/dashboard/src/pages/settings.astro +0 -283
- argus_code-0.4.4/dashboard/src/pages/tools.astro +0 -216
- argus_code-0.4.4/dashboard/src/pages/trends.astro +0 -55
- argus_code-0.4.4/dashboard/src/scripts/alerts.ts +0 -85
- argus_code-0.4.4/dashboard/src/scripts/api.ts +0 -197
- argus_code-0.4.4/dashboard/src/scripts/charts.ts +0 -246
- argus_code-0.4.4/dashboard/src/scripts/format.ts +0 -70
- argus_code-0.4.4/dashboard/src/styles/global.css +0 -307
- argus_code-0.4.4/dashboard/tsconfig.json +0 -4
- argus_code-0.4.4/dashboard-dist/_astro/charts.36uaSAWt.js +0 -1
- argus_code-0.4.4/dashboard-dist/_astro/format.BexCUztC.js +0 -1
- argus_code-0.4.4/dashboard-dist/_astro/index.astro_astro_type_script_index_0_lang.BF0nZzma.js +0 -11
- argus_code-0.4.4/dashboard-dist/_astro/index.astro_astro_type_script_index_0_lang.D-QKQJAF.js +0 -24
- argus_code-0.4.4/dashboard-dist/_astro/installCanvasRenderer.XK5yP7fW.js +0 -18
- argus_code-0.4.4/dashboard-dist/_astro/models.astro_astro_type_script_index_0_lang.0Aczy7Vm.js +0 -13
- argus_code-0.4.4/dashboard-dist/_astro/prompts.astro_astro_type_script_index_0_lang.B1i5N4zM.js +0 -17
- argus_code-0.4.4/dashboard-dist/_astro/session.CGJ-XRoC.css +0 -1
- argus_code-0.4.4/dashboard-dist/_astro/session.astro_astro_type_script_index_0_lang.SRsknMTL.js +0 -126
- argus_code-0.4.4/dashboard-dist/_astro/settings.astro_astro_type_script_index_0_lang.DyHh8NQi.js +0 -24
- argus_code-0.4.4/dashboard-dist/_astro/tools.astro_astro_type_script_index_0_lang.DHTUv2RL.js +0 -12
- argus_code-0.4.4/dashboard-dist/_astro/trends.astro_astro_type_script_index_0_lang.CBtUcxGK.js +0 -5
- argus_code-0.4.4/dashboard-dist/index.html +0 -2
- argus_code-0.4.4/dashboard-dist/models/index.html +0 -1
- argus_code-0.4.4/dashboard-dist/prompts/index.html +0 -18
- argus_code-0.4.4/dashboard-dist/session/index.html +0 -1
- argus_code-0.4.4/dashboard-dist/sessions/index.html +0 -1
- argus_code-0.4.4/dashboard-dist/settings/index.html +0 -8
- argus_code-0.4.4/dashboard-dist/styles/global.css +0 -307
- argus_code-0.4.4/dashboard-dist/tools/index.html +0 -1
- argus_code-0.4.4/dashboard-dist/trends/index.html +0 -1
- argus_code-0.4.4/tests/dashboard/test_chart_tooltip_escaping.py +0 -87
- {argus_code-0.4.4 → argus_code-0.5.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/.github/pull_request_template.md +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/.npmrc +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/CLAUDE.md +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/LICENSE +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/NOTICE +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/SECURITY.md +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/dashboard/.astro/content-assets.mjs +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/dashboard/.astro/content-modules.mjs +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/dashboard/.astro/content.d.ts +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/dashboard/.astro/types.d.ts +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/pricing/2026-05-02.json +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/pricing/2026-06-12.json +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/python/argus/AGENTS.md +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/python/argus/adapters/__init__.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/python/argus/adapters/base.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/python/argus/adapters/claude_code/__init__.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/python/argus/adapters/claude_code/adapter.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/python/argus/adapters/claude_code/discover.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/python/argus/adapters/claude_code/extract_transcript.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/python/argus/adapters/claude_code/history_jsonl.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/python/argus/adapters/claude_code/ingest_file.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/python/argus/adapters/claude_code/model.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/python/argus/adapters/claude_code/schemas.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/python/argus/adapters/registry.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/python/argus/cli.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/python/argus/collector/__init__.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/python/argus/collector/aggregate.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/python/argus/collector/pipeline.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/python/argus/collector/rollup_subagents.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/python/argus/collector/scheduler.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/python/argus/collector/search_backfill.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/python/argus/collector/watcher.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/python/argus/core/__init__.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/python/argus/daemon/__init__.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/python/argus/daemon/logging.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/python/argus/daemon/pidfile.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/python/argus/daemon/process.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/python/argus/daemon/service.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/python/argus/detectors/__init__.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/python/argus/detectors/base.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/python/argus/detectors/registry.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/python/argus/detectors/tool_error_rate_spike.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/python/argus/pricing/__init__.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/python/argus/pricing/compute.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/python/argus/pricing/load.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/python/argus/pricing/refresh.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/python/argus/pricing/types.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/python/argus/scaffold/__init__.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/python/argus/scaffold/scaffolder.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/python/argus/scaffold/snapshot.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/python/argus/scaffold/storage.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/python/argus/schema/__init__.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/python/argus/schema/types.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/python/argus/server/__init__.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/python/argus/store/__init__.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/python/argus/store/db.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/python/argus/store/migrations/__init__.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/python/argus/store/migrations/inline.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/templates/default/.claude/agents/code-reviewer.md +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/templates/default/.claude/agents/security-auditor.md +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/templates/default/.claude/commands/commit.md +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/templates/default/.claude/commands/deploy.md +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/templates/default/.claude/commands/fix-issue.md +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/templates/default/.claude/commands/pr.md +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/templates/default/.claude/commands/review.md +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/templates/default/.claude/rules/api-conventions.md +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/templates/default/.claude/rules/code-style.md +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/templates/default/.claude/rules/testing.md +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/templates/default/.claude/settings.json +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/templates/default/.claude/skills/example/SKILL.md +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/templates/default/CLAUDE.md +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/tests/__init__.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/tests/adapters/__init__.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/tests/adapters/claude_code/__init__.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/tests/adapters/claude_code/test_adapter.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/tests/adapters/claude_code/test_discover.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/tests/adapters/claude_code/test_extract_transcript.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/tests/adapters/claude_code/test_history_jsonl.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/tests/adapters/claude_code/test_ingest_file.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/tests/adapters/claude_code/test_integration.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/tests/adapters/claude_code/test_model.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/tests/adapters/claude_code/test_path_containment.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/tests/adapters/claude_code/test_schemas.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/tests/adapters/test_registry.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/tests/cli/__init__.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/tests/cli/test_indexing_cli.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/tests/collector/__init__.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/tests/collector/test_aggregate.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/tests/collector/test_pipeline.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/tests/collector/test_rollup_subagents.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/tests/collector/test_watcher.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/tests/core/__init__.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/tests/core/test_runtime.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/tests/daemon/__init__.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/tests/daemon/test_logs.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/tests/daemon/test_pidfile.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/tests/daemon/test_process.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/tests/daemon/test_service.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/tests/daemon/test_spawn_safe_path.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/tests/daemon/test_yield.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/tests/dashboard/__init__.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/tests/detectors/__init__.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/tests/detectors/test_registry.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/tests/detectors/test_tool_error_rate_spike.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/tests/pricing/__init__.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/tests/pricing/test_compute.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/tests/pricing/test_load.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/tests/pricing/test_refresh.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/tests/scaffold/__init__.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/tests/scaffold/test_bundled_template.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/tests/scaffold/test_cli_claude.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/tests/scaffold/test_scaffold_containment.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/tests/scaffold/test_scaffolder.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/tests/scaffold/test_snapshot.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/tests/scaffold/test_snapshot_secrets.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/tests/scaffold/test_storage.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/tests/schema/__init__.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/tests/schema/test_types.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/tests/server/__init__.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/tests/server/test_api.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/tests/server/test_api_search.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/tests/server/test_param_bounds.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/tests/server/test_server.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/tests/server/test_week_of.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/tests/store/__init__.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/tests/store/test_db.py +0 -0
- {argus_code-0.4.4 → argus_code-0.5.0}/tests/test_e2e.py +0 -0
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
name: test
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
concurrency:
|
|
9
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
10
|
+
cancel-in-progress: true
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
pytest:
|
|
14
|
+
name: pytest (${{ matrix.os }}, py${{ matrix.python-version }})
|
|
15
|
+
runs-on: ${{ matrix.os }}
|
|
16
|
+
strategy:
|
|
17
|
+
# Don't cancel the whole matrix on one platform's failure — path
|
|
18
|
+
# handling, symlink behaviour and signal delivery all differ per OS,
|
|
19
|
+
# and seeing which combination broke is the point.
|
|
20
|
+
fail-fast: false
|
|
21
|
+
matrix:
|
|
22
|
+
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
23
|
+
python-version: ["3.11", "3.12", "3.13"]
|
|
24
|
+
|
|
25
|
+
steps:
|
|
26
|
+
- uses: actions/checkout@v4
|
|
27
|
+
|
|
28
|
+
- name: Install uv
|
|
29
|
+
uses: astral-sh/setup-uv@v5
|
|
30
|
+
with:
|
|
31
|
+
enable-cache: true
|
|
32
|
+
|
|
33
|
+
- name: Install dependencies
|
|
34
|
+
run: uv sync --dev --python ${{ matrix.python-version }}
|
|
35
|
+
|
|
36
|
+
- name: Run tests
|
|
37
|
+
run: uv run pytest -q
|
|
38
|
+
|
|
39
|
+
dashboard:
|
|
40
|
+
name: dashboard build
|
|
41
|
+
runs-on: ubuntu-latest
|
|
42
|
+
steps:
|
|
43
|
+
- uses: actions/checkout@v4
|
|
44
|
+
|
|
45
|
+
- uses: actions/setup-node@v4
|
|
46
|
+
with:
|
|
47
|
+
node-version: "22"
|
|
48
|
+
cache: npm
|
|
49
|
+
cache-dependency-path: dashboard/package-lock.json
|
|
50
|
+
|
|
51
|
+
- name: Install and build
|
|
52
|
+
working-directory: dashboard
|
|
53
|
+
run: |
|
|
54
|
+
npm ci
|
|
55
|
+
npm run build
|
|
56
|
+
|
|
57
|
+
# The wheel ships dashboard-dist/, not dashboard/dist/. If a source edit
|
|
58
|
+
# is committed without refreshing the shipped copy, users get the old UI
|
|
59
|
+
# — including, historically, an unfixed XSS. Fail loudly on drift.
|
|
60
|
+
#
|
|
61
|
+
# Compare file *names*, not bytes: Astro content-hashes asset filenames,
|
|
62
|
+
# so any real source change renames the asset. Byte comparison would
|
|
63
|
+
# instead trip over line endings, since dashboard-dist/ is tracked (and
|
|
64
|
+
# so checked out CRLF on Windows) while dashboard/dist/ is a fresh LF
|
|
65
|
+
# build — a difference that says nothing about staleness.
|
|
66
|
+
- name: Check dashboard-dist is in sync with dashboard/src
|
|
67
|
+
run: |
|
|
68
|
+
(cd dashboard/dist && find . -type f | sort) > /tmp/built.txt
|
|
69
|
+
(cd dashboard-dist && find . -type f | sort) > /tmp/shipped.txt
|
|
70
|
+
if ! diff -u /tmp/shipped.txt /tmp/built.txt; then
|
|
71
|
+
echo "::error::dashboard-dist/ is stale. Rebuild and commit it — see dashboard/AGENTS.md."
|
|
72
|
+
exit 1
|
|
73
|
+
fi
|
|
74
|
+
echo "dashboard-dist matches the build."
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
|
|
17
17
|
Argus is a **local-first** analytics dashboard for Claude Code (and other coding
|
|
18
18
|
agents). A watcher ingests Claude Code's `.jsonl` session transcripts into a local
|
|
19
|
-
SQLite archive (`~/.argus/argus.db`); a FastAPI server serves a static
|
|
19
|
+
SQLite archive (`~/.argus/argus.db`); a FastAPI server serves a static React
|
|
20
20
|
dashboard at `http://localhost:4242`. No network, no telemetry, no LLM calls
|
|
21
21
|
(except opt-in `argus pricing refresh`). Backend + dashboard ship together in the
|
|
22
22
|
`argus-code` wheel on PyPI.
|
|
@@ -92,8 +92,9 @@ Global engineering rules (binding):
|
|
|
92
92
|
|
|
93
93
|
## Verification
|
|
94
94
|
|
|
95
|
-
- Backend: `uv run pytest` (must be green; ~
|
|
96
|
-
- Dashboard: `cd dashboard && npm run build` (must
|
|
95
|
+
- Backend: `uv run pytest` (must be green; ~480 tests, ~35s on Windows).
|
|
96
|
+
- Dashboard: `cd dashboard && npm test && npm run build && npm run size` (all must
|
|
97
|
+
succeed); `npm run e2e` before a release.
|
|
97
98
|
- Built form smoke test: see `CONTRIBUTING.md` "Running the built form".
|
|
98
99
|
|
|
99
100
|
## User Preferences
|
|
@@ -115,5 +116,5 @@ Global engineering rules (binding):
|
|
|
115
116
|
- `python/argus/adapters/AGENTS.md` — Claude Code adapter and transcript-segment
|
|
116
117
|
extraction; sub-agent file layout.
|
|
117
118
|
- `python/argus/server/AGENTS.md` — FastAPI routes, static serving, clean shutdown.
|
|
118
|
-
- `dashboard/AGENTS.md` —
|
|
119
|
+
- `dashboard/AGENTS.md` — React SPA dashboard and the `dashboard-dist` ship chain.
|
|
119
120
|
- `tests/AGENTS.md` — pytest conventions and platform quirks.
|
|
@@ -26,8 +26,9 @@ No network calls (except optional `argus pricing refresh`). No
|
|
|
26
26
|
telemetry. No LLM calls. Everything stays on your machine.
|
|
27
27
|
|
|
28
28
|
The backend is Python (≥3.11, FastAPI + uvicorn + pydantic + watchdog
|
|
29
|
-
+ stdlib sqlite3 + typer). The dashboard is
|
|
30
|
-
|
|
29
|
+
+ stdlib sqlite3 + typer). The dashboard is a Vite + React SPA (TanStack
|
|
30
|
+
Router/Query/Table, uPlot + SVG charts, Tailwind tokens), statically built.
|
|
31
|
+
Both ship together in the `argus-code` wheel on PyPI.
|
|
31
32
|
|
|
32
33
|
## The data layer
|
|
33
34
|
|
|
@@ -119,12 +120,19 @@ python/argus/server/api.py /api/overview, /api/sessions, /api/tools, …
|
|
|
119
120
|
python/argus/store/repository.py parameterized SQL queries
|
|
120
121
|
│
|
|
121
122
|
▼
|
|
122
|
-
dashboard-dist/ static
|
|
123
|
+
dashboard-dist/ static SPA bundled from dashboard/src/ (Vite + React)
|
|
123
124
|
```
|
|
124
125
|
|
|
125
126
|
The dashboard is **statically built**. No server-side rendering, no
|
|
126
|
-
Node
|
|
127
|
-
|
|
127
|
+
Node at runtime. Pages fetch `/api/...` through a typed, Zod-validated
|
|
128
|
+
client (`dashboard/src/lib/api/`) via TanStack Query and render with uPlot
|
|
129
|
+
(time series, scatter) and hand-rolled SVG (bars, meters, heatmaps, the
|
|
130
|
+
session minimap). Derived analyses (prior-window deltas, per-project
|
|
131
|
+
rollups, weekday x hour, tool calls per day) are pure functions in
|
|
132
|
+
`dashboard/src/lib/analysis/`, computed client-side from existing endpoints;
|
|
133
|
+
each carries a `// candidate-endpoint:` note where a server aggregate would
|
|
134
|
+
scale better. Deep links such as `/sessions/<id>` are served by the
|
|
135
|
+
`index.html` fallback in `server/app.py` and resolved by the client router.
|
|
128
136
|
|
|
129
137
|
## Detection (alerts)
|
|
130
138
|
|
|
@@ -223,10 +231,11 @@ A few patterns to absorb before adding code:
|
|
|
223
231
|
`ON CONFLICT(id) DO UPDATE`. Re-ingesting a file from offset 0 is
|
|
224
232
|
safe — useful for backfilling derived data after a schema change.
|
|
225
233
|
|
|
226
|
-
- **HTML
|
|
227
|
-
JSONL
|
|
228
|
-
`dashboard/
|
|
229
|
-
|
|
234
|
+
- **Never write raw HTML in the dashboard.** React renders every
|
|
235
|
+
JSONL-derived string as a text node; `dangerouslySetInnerHTML` and
|
|
236
|
+
`innerHTML` are forbidden (`tests/dashboard/test_no_raw_html.py`). FTS5
|
|
237
|
+
`<mark>` snippets are split into text runs by
|
|
238
|
+
`dashboard/src/features/search/cleanSnippet.ts`.
|
|
230
239
|
|
|
231
240
|
- **CSRF Origin check.** All non-GET `/api/*` routes verify the
|
|
232
241
|
`Origin` header is loopback. Implemented as FastAPI middleware in
|
|
@@ -266,10 +275,15 @@ python/argus/
|
|
|
266
275
|
|
|
267
276
|
dashboard/
|
|
268
277
|
src/
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
278
|
+
app/ router, query client, shell (sidebar, top bar, Ctrl+K)
|
|
279
|
+
routes/ TanStack file routes (one per page + legacy redirects)
|
|
280
|
+
features/<page>/ page components and page-specific hooks
|
|
281
|
+
components/ui/ Panel, Tile, Pill, Chip, Seg, Button, DataTable, ...
|
|
282
|
+
components/charts/ uPlot wrappers + SVG charts (rules in README.md)
|
|
283
|
+
lib/api/ Zod schemas, typed client, React Query hooks, fixtures
|
|
284
|
+
lib/analysis/ pure derived analyses (unit-tested)
|
|
285
|
+
lib/format/ number / date formatters
|
|
286
|
+
styles.css Tailwind v4 tokens (@theme) + base rules
|
|
273
287
|
dashboard-dist/ built dashboard, shipped in the wheel as data
|
|
274
288
|
|
|
275
289
|
pricing/ bundled LiteLLM price tables (shipped in wheel as data)
|
|
@@ -296,12 +310,12 @@ tests/ pytest suite, mirrors python/argus/ layout
|
|
|
296
310
|
|
|
297
311
|
| Want to… | Touch these |
|
|
298
312
|
|---|---|
|
|
299
|
-
| Add a new dashboard page | `dashboard/src/
|
|
313
|
+
| Add a new dashboard page | `dashboard/src/routes/<name>.tsx` + `dashboard/src/features/<name>/<Name>Page.tsx`, add it to `GROUPS` in `dashboard/src/app/shell/Sidebar.tsx` and `PAGES` in `CommandPalette.tsx` |
|
|
300
314
|
| Add a new API endpoint | `python/argus/server/api.py`, add a `repo.<method_name>()` in `python/argus/store/repository.py` |
|
|
301
315
|
| Add a new SQL table or column | New `MIGRATION_N+1` in `python/argus/store/migrations/inline.py`, bump schema check in `db.py`, add `repo` method, add pydantic model in `python/argus/schema/types.py` |
|
|
302
316
|
| Parse a new JSONL field | `python/argus/adapters/claude_code/schemas.py` (pydantic), wire into `pipeline.py` |
|
|
303
317
|
| Tweak cost computation | `python/argus/pricing/compute.py`, then re-ingest to recompute via a backfill |
|
|
304
|
-
| Add a new chart | `dashboard/src/
|
|
318
|
+
| Add a new chart | `dashboard/src/components/charts/` (read its `README.md` first; series colours in `uplotTheme.ts`) |
|
|
305
319
|
| Add a new adapter (Codex, OpenClaw, Hermes, …) | New folder `python/argus/adapters/<agent>/` + `@register class` in `adapter.py`. No edits to CLI / watcher / pipeline / server. |
|
|
306
320
|
| Add an alert detector | New file in `python/argus/detectors/` with a `@register` class whose pure `detect()` returns `Finding`s, plus the side-effect import in `detectors/__init__.py`. The scheduler picks it up automatically. |
|
|
307
321
|
| Change the bundled scaffold template | Edit files under `templates/default/`; they're force-included into the wheel. New top-level dirs need a `force-include` entry in `pyproject.toml`. |
|
|
@@ -15,7 +15,7 @@ first** — it's a 5-minute tour of how the pieces fit together.
|
|
|
15
15
|
git clone https://github.com/KrishBhimani/argus-code.git
|
|
16
16
|
cd argus-code
|
|
17
17
|
uv sync # creates .venv and installs deps + dev tools
|
|
18
|
-
uv run pytest # ~
|
|
18
|
+
uv run pytest # ~380 tests, ~30s
|
|
19
19
|
uv run argus start # fast iteration loop — runs directly from source
|
|
20
20
|
```
|
|
21
21
|
|
|
@@ -24,6 +24,18 @@ Change a file, restart, see the result.
|
|
|
24
24
|
|
|
25
25
|
If you don't have `uv` yet: <https://docs.astral.sh/uv/getting-started/installation/>.
|
|
26
26
|
|
|
27
|
+
## Dashboard dev loop
|
|
28
|
+
|
|
29
|
+
```sh
|
|
30
|
+
uv run argus start # backend on :4242
|
|
31
|
+
cd dashboard && npm install && npm run dev # Vite on :5173, proxies /api to :4242
|
|
32
|
+
npm test && npm run build && npm run size # before committing
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
The dashboard is a Vite + React SPA; see `dashboard/AGENTS.md` for the ship
|
|
36
|
+
chain (`dashboard-dist/` must be refreshed and committed with every source
|
|
37
|
+
change) and `npm run e2e` for the Playwright smoke test.
|
|
38
|
+
|
|
27
39
|
## Running the built form
|
|
28
40
|
|
|
29
41
|
CI builds and tests on every push. To smoke-test the built wheel
|
|
@@ -32,11 +44,15 @@ locally exactly as a user would:
|
|
|
32
44
|
```sh
|
|
33
45
|
cd dashboard && npm ci && npm run build && cd ..
|
|
34
46
|
cp -r dashboard/dist dashboard-dist # bundle the dashboard
|
|
35
|
-
uv build
|
|
36
|
-
uv tool install ./dist/
|
|
47
|
+
rm -rf dist && uv build # wheel + sdist in dist/
|
|
48
|
+
uv tool install ./dist/argus_code-*.whl # install globally
|
|
37
49
|
argus start
|
|
38
50
|
```
|
|
39
51
|
|
|
52
|
+
The distribution is `argus-code` on PyPI (the `argus_code-*.whl` above); the
|
|
53
|
+
command it installs is `argus`. Clear `dist/` first or a stale wheel from an
|
|
54
|
+
earlier version can be picked up by the glob.
|
|
55
|
+
|
|
40
56
|
## Tests
|
|
41
57
|
|
|
42
58
|
```sh
|
|
@@ -54,11 +70,17 @@ for the full catalog.
|
|
|
54
70
|
|
|
55
71
|
## CI
|
|
56
72
|
|
|
57
|
-
`.github/workflows/test.yml` runs on every push and PR:
|
|
58
|
-
|
|
59
|
-
- **Test matrix:** Ubuntu, macOS, Windows × Python 3.11, 3.12, 3.13
|
|
60
|
-
-
|
|
61
|
-
|
|
73
|
+
`.github/workflows/test.yml` runs on every push to `main` and every PR:
|
|
74
|
+
|
|
75
|
+
- **Test matrix:** Ubuntu, macOS, Windows × Python 3.11, 3.12, 3.13 (9 jobs,
|
|
76
|
+
`fail-fast: false` so you can see which platform broke).
|
|
77
|
+
- **Dashboard build:** `npm ci && npm run build`, then a check that the
|
|
78
|
+
tracked `dashboard-dist/` matches what the build produces. A source edit
|
|
79
|
+
committed without refreshing the shipped copy means users run the old UI —
|
|
80
|
+
that has historically shipped an unfixed XSS, so the check is a hard fail.
|
|
81
|
+
It compares file *names*, which Vite content-hashes, rather than bytes
|
|
82
|
+
(`dashboard-dist/` is tracked and so checked out CRLF on Windows, while a
|
|
83
|
+
fresh build is LF — a difference that says nothing about staleness).
|
|
62
84
|
|
|
63
85
|
The Windows runner is non-negotiable — path normalisation, WAL `-shm`
|
|
64
86
|
cleanup, and short-name path quirks are all platform-sensitive.
|
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: argus-code
|
|
3
|
+
Version: 0.5.0
|
|
4
|
+
Summary: Local-first dashboard for Claude Code cost, token, tool-usage, and full-text search analytics
|
|
5
|
+
Project-URL: Homepage, https://github.com/KrishBhimani/argus-code
|
|
6
|
+
Project-URL: Repository, https://github.com/KrishBhimani/argus-code.git
|
|
7
|
+
Project-URL: Issues, https://github.com/KrishBhimani/argus-code/issues
|
|
8
|
+
Author: Krish Bhimani
|
|
9
|
+
License: MIT License
|
|
10
|
+
|
|
11
|
+
Copyright (c) 2026 Krish Bhimani
|
|
12
|
+
|
|
13
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
14
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
15
|
+
in the Software without restriction, including without limitation the rights
|
|
16
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
17
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
18
|
+
furnished to do so, subject to the following conditions:
|
|
19
|
+
|
|
20
|
+
The above copyright notice and this permission notice shall be included in all
|
|
21
|
+
copies or substantial portions of the Software.
|
|
22
|
+
|
|
23
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
24
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
25
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
26
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
27
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
28
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
29
|
+
SOFTWARE.
|
|
30
|
+
License-File: LICENSE
|
|
31
|
+
License-File: NOTICE
|
|
32
|
+
Keywords: ai-tools,analytics,anthropic,claude,claude-code,cli,cost,dashboard,llm,local-first,tokens,usage
|
|
33
|
+
Classifier: Development Status :: 4 - Beta
|
|
34
|
+
Classifier: Environment :: Console
|
|
35
|
+
Classifier: Environment :: Web Environment
|
|
36
|
+
Classifier: Intended Audience :: Developers
|
|
37
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
38
|
+
Classifier: Operating System :: MacOS
|
|
39
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
40
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
41
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
42
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
43
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
44
|
+
Requires-Python: >=3.11
|
|
45
|
+
Requires-Dist: fastapi>=0.115
|
|
46
|
+
Requires-Dist: httpx>=0.27
|
|
47
|
+
Requires-Dist: pydantic>=2.9
|
|
48
|
+
Requires-Dist: typer>=0.12
|
|
49
|
+
Requires-Dist: uvicorn[standard]>=0.32
|
|
50
|
+
Requires-Dist: watchdog>=5.0
|
|
51
|
+
Description-Content-Type: text/markdown
|
|
52
|
+
|
|
53
|
+
# Argus
|
|
54
|
+
|
|
55
|
+
**The observability console for Claude Code — local-first, permanent, and honest about cost.**
|
|
56
|
+
|
|
57
|
+
[](https://pypi.org/project/argus-code/)
|
|
58
|
+
[](#requirements)
|
|
59
|
+
[](./LICENSE)
|
|
60
|
+
|
|
61
|
+
Claude Code writes a detailed transcript of every session to `~/.claude/` — every turn,
|
|
62
|
+
every token, every tool call, every sub-agent it spawned — and then **deletes it after
|
|
63
|
+
30 days**. Argus tails those files into a SQLite archive on your machine, prices each
|
|
64
|
+
turn from a bundled table, and serves a dashboard at `http://localhost:4242` that
|
|
65
|
+
answers the questions the transcripts never do:
|
|
66
|
+
|
|
67
|
+
- *How much am I actually spending, and is it going up?*
|
|
68
|
+
- *Which sessions were expensive — and which turn made them so?*
|
|
69
|
+
- *Where do my tools fail, and when did that start?*
|
|
70
|
+
- *What did that sub-agent get told, and what did it do?*
|
|
71
|
+
- *When do I actually work, and on what?*
|
|
72
|
+
|
|
73
|
+
Nothing leaves your computer. No telemetry, no API calls, no embeddings — SQLite and
|
|
74
|
+
a static web app, bound to `127.0.0.1`.
|
|
75
|
+
|
|
76
|
+
```sh
|
|
77
|
+
pipx install argus-code # or: uv tool install argus-code
|
|
78
|
+
argus start
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Your browser opens once the first pass finishes (5–10 s for a typical install). From
|
|
82
|
+
then on, every session you run is ingested live.
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Why it exists
|
|
87
|
+
|
|
88
|
+
Tools like `ccusage` read what's on disk *right now*. Claude Code rotates its own
|
|
89
|
+
logs (`cleanupPeriodDays`, default 30), so "right now" is a sliding month. Once
|
|
90
|
+
Argus has ingested a session into `~/.argus/argus.db` the row stays forever — a few
|
|
91
|
+
months in, Argus remembers sessions Claude has already forgotten. **It accumulates.**
|
|
92
|
+
|
|
93
|
+
And because it keeps the *structure* of each session (turns, tool calls, sub-agents,
|
|
94
|
+
cache hits), it can do forensics, not just totals.
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## What you get
|
|
99
|
+
|
|
100
|
+
The dashboard is organised by the job you came to do.
|
|
101
|
+
|
|
102
|
+
### Monitor
|
|
103
|
+
|
|
104
|
+
| Page | What it answers |
|
|
105
|
+
|---|---|
|
|
106
|
+
| **Overview** | Four tiles — tokens, estimated cost, sessions, tool error rate — each with its **change vs. the previous window**. A "Needs attention" strip that is always visible (it says *all clear* when there's nothing). Tokens per day, stackable by model. A 90-day activity heatmap and a **weekday × hour** map of when you start sessions. Top sessions in the window. |
|
|
107
|
+
| **Alerts** | The inbox for detector findings, with unseen / all / severity filters and a 30-day strip. Today's detector flags any tool whose error rate doubled against its 4-week baseline; more arrive with Budgets. |
|
|
108
|
+
|
|
109
|
+
### Analyze
|
|
110
|
+
|
|
111
|
+
| Page | What it answers |
|
|
112
|
+
|---|---|
|
|
113
|
+
| **Sessions** | A virtualised, sortable grid of every session with inline token bars. Above it, a **duration × tokens scatter** (log–log, coloured by model) that makes outliers obvious, or a per-project rollup. Filter by text, project, model, window. |
|
|
114
|
+
| **Session detail** | Tiles, then a **session-shape minimap** — one bar per turn, cache reads beneath fresh tokens, failing turns in red; click a bar to jump. A cumulative-cost line. A compact timeline where every row expands into its tool calls, their sizes, status and output, and error text inline. Resumed sessions are stitched into one chronological thread. |
|
|
115
|
+
| **Sub-agents** | For sessions that delegated: a sticky list with an at-a-glance strip (tokens per agent, red where one failed), filter and sort, and ↑↓ stepping. Each agent's **task as given**, tools, shape and full timeline, inline. |
|
|
116
|
+
| **Tools** | Leaderboard with error segments, **tool calls per day** (columns / area / table), MCP servers, sub-agent invocations by type. |
|
|
117
|
+
| **Models** | Tokens and cost per model, **$ per million tokens** as you actually experienced it, and each model's share over time. |
|
|
118
|
+
| **Trends** | Built around **rates, not totals**: this period vs last, a run-rate projection, tokens per session, cache-read share, unit cost — plus the by-model lines, cumulative total and a full breakdown table. |
|
|
119
|
+
|
|
120
|
+
### Search *(opt-in)*
|
|
121
|
+
|
|
122
|
+
Full-text search over every prompt you've typed **and** every assistant reply,
|
|
123
|
+
thinking block and tool output. SQLite FTS5 — sub-millisecond, lexical,
|
|
124
|
+
deterministic, offline. Off by default; see [Privacy](#privacy--security).
|
|
125
|
+
|
|
126
|
+
### Govern
|
|
127
|
+
|
|
128
|
+
**Settings** (indexing toggle, pricing version, export, parse errors) today;
|
|
129
|
+
**Budgets** — monthly ceilings with threshold alerts — is the next slot.
|
|
130
|
+
|
|
131
|
+
Every chart follows a few house rules: one axis per chart, a legend whenever there's
|
|
132
|
+
more than one series, status colours always paired with an icon and a label, and a
|
|
133
|
+
table view behind every chart. Tokens are exact; costs are estimates, and the UI says so.
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## CLI
|
|
138
|
+
|
|
139
|
+
```sh
|
|
140
|
+
argus # top-level command group
|
|
141
|
+
├─ start [--port 4242] [--host 127.0.0.1] [--data-dir <path>]
|
|
142
|
+
│ # watcher + ingester + dashboard server
|
|
143
|
+
├─ pricing
|
|
144
|
+
│ └─ refresh # pull latest model prices from LiteLLM
|
|
145
|
+
├─ indexing # (was `search` — still works, hidden alias)
|
|
146
|
+
│ ├─ status # is transcript indexing on?
|
|
147
|
+
│ ├─ enable # turn it on (next start backfills)
|
|
148
|
+
│ ├─ disable # turn it off, keep data
|
|
149
|
+
│ └─ clear # wipe all indexed segments + disable
|
|
150
|
+
├─ claude # scaffold & manage .claude/ setups
|
|
151
|
+
│ ├─ init [path] [--template <name>] [--force]
|
|
152
|
+
│ │ # stamp CLAUDE.md + .claude/ into a project
|
|
153
|
+
│ └─ template
|
|
154
|
+
│ ├─ list # list templates (bundled + user)
|
|
155
|
+
│ └─ create <name> [--path <dir>] [--all]
|
|
156
|
+
│ # save a project's .claude/ as a template
|
|
157
|
+
├─ daemon # argusd — background ingestion + detectors
|
|
158
|
+
│ ├─ start # start argusd detached, write PID file
|
|
159
|
+
│ ├─ stop # stop argusd gracefully
|
|
160
|
+
│ ├─ restart # stop then start
|
|
161
|
+
│ ├─ status # running? PID + uptime
|
|
162
|
+
│ └─ logs [-n N] [-f] # tail ~/.argus/argusd.log
|
|
163
|
+
└─ wipe # delete ~/.argus/ entirely
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
`--help` works at every level.
|
|
167
|
+
|
|
168
|
+
### `argus daemon` — keep ingesting when the dashboard is closed
|
|
169
|
+
|
|
170
|
+
By default the watcher and detector scheduler run *inside* `argus start`; close it
|
|
171
|
+
and ingestion stops. **argusd** moves that work into a long-running background
|
|
172
|
+
process. It does not serve the dashboard — port 4242 is still only bound by
|
|
173
|
+
`argus start`.
|
|
174
|
+
|
|
175
|
+
```sh
|
|
176
|
+
argus daemon start # run argusd in the background (survives closing the terminal)
|
|
177
|
+
argus daemon status # PID + uptime
|
|
178
|
+
argus daemon logs -f # follow the log
|
|
179
|
+
argus daemon stop
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
**Coexistence.** When argusd is running, `argus start` sees its PID file and becomes a
|
|
183
|
+
read-only viewer of the database the daemon keeps fresh (the sidebar footer says
|
|
184
|
+
*argusd daemon*). When it isn't, `argus start` ingests in-process exactly as before.
|
|
185
|
+
|
|
186
|
+
**Living with it.** Idle cost is negligible: the watcher is event-driven and the
|
|
187
|
+
scheduler wakes every 10 minutes — expect ~40–70 MB RAM and no idle CPU. Logs rotate
|
|
188
|
+
at ~1 MB × 3 in `~/.argus/argusd.log`. Things to know:
|
|
189
|
+
|
|
190
|
+
- **Restart after upgrading** (`argus daemon restart`) — a running daemon holds the old code.
|
|
191
|
+
- **No auto-restart yet.** A crashed daemon stays down until you start it again; the stale PID file is cleaned up. OS-native autostart (`argus install`) is a follow-up.
|
|
192
|
+
- **If argusd dies while a read-only dashboard is open**, the footer keeps saying *argusd* and ingestion pauses until you restart the dashboard, which then resumes in-process.
|
|
193
|
+
- **Windows `stop` is a hard kill** — safe (no critical in-memory state), but no `argusd stopped.` line lands in the log.
|
|
194
|
+
- **Toggling search:** the dashboard's *Enable indexing* button indexes immediately; the CLI `argus indexing enable` flips the flag and backfills on the next `argus start` / `argus daemon restart`.
|
|
195
|
+
|
|
196
|
+
### `argus claude` — scaffold good agent config
|
|
197
|
+
|
|
198
|
+
Set things up well *before* you run, not just observe afterwards. `init` copies a
|
|
199
|
+
template into a project: `CLAUDE.md` to the root, everything else into `.claude/`.
|
|
200
|
+
Existing files are skipped (`--force` overwrites — except `CLAUDE.md`, which is never
|
|
201
|
+
overwritten). The bundled `default` template ships a sensible `settings.json`, agents,
|
|
202
|
+
commands, rules and a placeholder skill. Save your own project's setup with
|
|
203
|
+
`template create`; user templates live in `~/.argus/templates/` and win over bundled ones.
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
## Privacy & security
|
|
208
|
+
|
|
209
|
+
Argus is built for one person on one machine, and the defaults say so.
|
|
210
|
+
|
|
211
|
+
- **Binds to `127.0.0.1` only.** Nothing on your LAN, Wi-Fi or VPN can reach it. `--host 0.0.0.0` exists, and prints a loud warning.
|
|
212
|
+
- **No external requests, ever** — except `argus pricing refresh`, a manual command that fetches one JSON file from LiteLLM's GitHub. No telemetry, no analytics, no LLM calls.
|
|
213
|
+
- **Transcript indexing is opt-in.** Cost and token analytics need no text content. Full-text search over prompts and transcripts requires an explicit opt-in (Settings or `argus indexing enable`), and opting out means the API returns nothing even if data is on disk.
|
|
214
|
+
- **Cross-origin writes are rejected.** State-changing endpoints check the `Origin` header against Argus's own origin — exactly — so neither a random tab nor another localhost app can flip your settings.
|
|
215
|
+
- **A loopback `Host` header is required.** This defeats DNS rebinding, where a site you visit repoints its domain at `127.0.0.1` to read your history. Anything else gets a 421 (skipped only when you deliberately bind `0.0.0.0`).
|
|
216
|
+
- **Transcript text never becomes HTML.** The dashboard renders every transcript-derived string as text; a test forbids raw-HTML sinks in the source.
|
|
217
|
+
- **No embeddings, no model weights.** Search is a plain inverted index.
|
|
218
|
+
|
|
219
|
+
Your data is one file, `~/.argus/argus.db`. `argus wipe` deletes it; so does `rm`.
|
|
220
|
+
Vulnerability reports: [SECURITY.md](./SECURITY.md).
|
|
221
|
+
|
|
222
|
+
---
|
|
223
|
+
|
|
224
|
+
## How it works
|
|
225
|
+
|
|
226
|
+
1. **Ingest.** A `watchdog` observer tails `~/.claude/projects/<project>/<session>.jsonl`. Lines are validated with `pydantic`, de-duplicated by `message.id`, and normalised into session / turn rows in SQLite (WAL mode). Resumed sessions and sub-agent files are folded into their parent.
|
|
227
|
+
2. **Cost.** Per-turn cost comes from a bundled `pricing/<version>.json` sourced from [LiteLLM](https://github.com/BerriAI/litellm). Tokens are exact; costs are estimates.
|
|
228
|
+
3. **Tools.** Each `tool_use` block becomes a `tool_calls` row; errors come from the matching `tool_result`. MCP servers are parsed from `mcp__<server>__<tool>`; the `Agent` tool's `subagent_type` is kept so delegation is visible.
|
|
229
|
+
4. **Search (opt-in).** Two FTS5 tables: one over `~/.claude/history.jsonl` (every prompt, ~150 KB for a heavy user), one over assistant text, thinking, user content and tool output (~30–60 MB for hundreds of sessions). Indexed incrementally during the normal ingest tick.
|
|
230
|
+
5. **Detection.** A scheduler thread runs registered *detectors* every 10 minutes. Each reads the DB and returns findings; the scheduler upserts them into `alerts` with a seen / resolved lifecycle, so an issue that recovers and recurs fires again instead of staying silent.
|
|
231
|
+
6. **Dashboard.** A Vite + React single-page app (uPlot and hand-drawn SVG charts), statically built and served by the FastAPI app. Analyses that aren't in the API yet — prior-window deltas, tokens per session, cache-read share, calls per day — are derived client-side from the existing endpoints. No Node at runtime, no network beyond `/api/*`.
|
|
232
|
+
7. **One runtime, two hosts.** The watcher, scheduler and first-pass ingest live in a single `CoreRuntime` that both `argus start` and `argusd` construct, so they can never double-ingest.
|
|
233
|
+
|
|
234
|
+
Want the deeper tour? [ARCHITECTURE.md](./ARCHITECTURE.md).
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## Configuration
|
|
239
|
+
|
|
240
|
+
| Where | Knob |
|
|
241
|
+
|---|---|
|
|
242
|
+
| `argus start --port <n>` | Port (default 4242). |
|
|
243
|
+
| `argus start --host <h>` | Bind host (default `127.0.0.1`; `0.0.0.0` for LAN exposure). |
|
|
244
|
+
| `argus start --data-dir <path>` | Override `~/.argus/`. |
|
|
245
|
+
| `pricing/*.json` | Bundled price tables; refresh with `argus pricing refresh`. |
|
|
246
|
+
|
|
247
|
+
### Keep more history in Claude Code itself
|
|
248
|
+
|
|
249
|
+
Claude Code deletes session files after 30 days by default. Raise it in
|
|
250
|
+
`~/.claude/settings.json` (minimum 1; it can't be disabled):
|
|
251
|
+
|
|
252
|
+
```json
|
|
253
|
+
{ "cleanupPeriodDays": 365 }
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
Argus keeps its own copy regardless — this only widens what Claude itself retains.
|
|
257
|
+
|
|
258
|
+
## Requirements
|
|
259
|
+
|
|
260
|
+
- **Python ≥ 3.11** with an FTS5-enabled `sqlite3` (the standard CPython builds for macOS, Linux and Windows all are; Argus checks at startup and says so clearly if not).
|
|
261
|
+
- A `~/.claude/` directory with real session JSONL — i.e. you've used Claude Code at least once.
|
|
262
|
+
|
|
263
|
+
---
|
|
264
|
+
|
|
265
|
+
## Development
|
|
266
|
+
|
|
267
|
+
```sh
|
|
268
|
+
git clone https://github.com/KrishBhimani/argus-code.git
|
|
269
|
+
cd argus-code
|
|
270
|
+
uv sync # install deps + create venv
|
|
271
|
+
uv run pytest # ~490 tests, ~35 s
|
|
272
|
+
uv run argus start # runs directly from source
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
Dashboard work happens in `dashboard/` (Vite + React): `npm install && npm run dev`
|
|
276
|
+
proxies `/api` to a running `argus start`; `npm test`, `npm run build`, `npm run size`
|
|
277
|
+
and `npm run e2e` are the gates. The built copy in `dashboard-dist/` ships inside the
|
|
278
|
+
wheel, so end users never touch `npm`. See [CONTRIBUTING.md](./CONTRIBUTING.md).
|
|
279
|
+
|
|
280
|
+
```
|
|
281
|
+
python/argus/ Python ingest, store, server, CLI
|
|
282
|
+
adapters/ Claude Code JSONL parsers + adapter registry
|
|
283
|
+
store/ SQLite schema + migrations + repo
|
|
284
|
+
server/ FastAPI app + /api routes
|
|
285
|
+
collector/ watcher + pipeline + first-run + search backfill + alert scheduler
|
|
286
|
+
core/ CoreRuntime — shared watcher+scheduler+ingest lifecycle
|
|
287
|
+
daemon/ argusd: pidfile, foreground service, process control, logging
|
|
288
|
+
detectors/ alert detectors (pure reads) + @register registry
|
|
289
|
+
scaffold/ `argus claude` template storage / init / snapshot
|
|
290
|
+
pricing/ LiteLLM-derived price table + cost compute
|
|
291
|
+
schema/ pydantic data models
|
|
292
|
+
dashboard/ React SPA source (Vite)
|
|
293
|
+
dashboard-dist/ Vite build output (shipped in wheel as data)
|
|
294
|
+
pricing/ Bundled pricing JSON (shipped in wheel as data)
|
|
295
|
+
templates/ Bundled .claude/ scaffolding templates (shipped in wheel as data)
|
|
296
|
+
tests/ pytest suite, mirrors python/argus/ layout
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
## License
|
|
300
|
+
|
|
301
|
+
MIT — see [LICENSE](./LICENSE).
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
> **Historical document.** This is the original planning PRD, kept for the
|
|
2
|
+
> design rationale. It predates several decisions that went the other way and
|
|
3
|
+
> is **not** an accurate description of what shipped. Notably: distribution is
|
|
4
|
+
> PyPI (`pip install argus-code`), not npm; the only supported agent is Claude
|
|
5
|
+
> Code, not Claude Code + Codex. For what Argus actually does today, read
|
|
6
|
+
> [README.md](./README.md) and [ARCHITECTURE.md](./ARCHITECTURE.md).
|
|
7
|
+
|
|
1
8
|
# Argus — Product Requirements Document (v0.2, MVP)
|
|
2
9
|
|
|
3
10
|
> v0.2 supersedes v0.1 (working name "AgentLens"). Schemas verified against on-disk logs. Tech stack and data model locked. Most v0.1 open questions are resolved; remaining ones are flagged in §10.
|