Skip to content

Commit f041370

Browse files
author
codejunkie99
committed
feat: show data layer terminal dashboard by default
1 parent 3a7aa45 commit f041370

11 files changed

Lines changed: 331 additions & 13 deletions

File tree

.agent/skills/_index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ requires human approval for production.
3030
## data-layer
3131
Cross-harness activity monitoring and dashboard exports.
3232
Triggers: "data layer", "dashboard", "agent analytics", "resource usage",
33-
"cron monitoring", "daily report", "tokens"
33+
"cron monitoring", "daily report", "tokens", "terminal dashboard"
3434
Constraints: local-only by default; no screenshot delivery without explicit user
3535
approval; do not commit private `.agent/data-layer/` exports.
3636

.agent/skills/_manifest.jsonl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@
33
{"name":"git-proxy","version":"2026-01-01","triggers":["commit","push","branch","merge","rebase","pull request","PR"],"tools":["bash"],"preconditions":[".git exists"],"constraints":["never force push to main","never force push to protected branches","run tests before push"],"category":"operations"}
44
{"name":"debug-investigator","version":"2026-01-01","triggers":["debug","why is this failing","investigate","stack trace","bug"],"tools":["bash","memory_reflect"],"preconditions":[],"constraints":["reproduce before fixing","fix root cause, not symptoms"],"category":"engineering"}
55
{"name":"deploy-checklist","version":"2026-01-01","triggers":["deploy","ship","release","go live"],"tools":["bash"],"preconditions":[],"constraints":["all tests passing","no unresolved TODOs in diff","requires human approval for production"],"category":"operations"}
6-
{"name":"data-layer","version":"2026-04-25","triggers":["data layer","dashboard","agent analytics","resource usage","cron monitoring","daily report","tokens"],"tools":["bash","git"],"preconditions":[".agent exists"],"constraints":["local-only by default","no screenshot delivery without explicit user approval","do not commit private .agent/data-layer exports"],"category":"operations"}
6+
{"name":"data-layer","version":"2026-04-25","triggers":["data layer","dashboard","agent analytics","resource usage","cron monitoring","daily report","tokens","terminal dashboard","TUI"],"tools":["bash","git"],"preconditions":[".agent exists"],"constraints":["local-only by default","no screenshot delivery without explicit user approval","do not commit private .agent/data-layer exports"],"category":"operations"}
77
{"name":"data-flywheel","version":"2026-04-25","triggers":["data flywheel","trace to train","training traces","context cards","eval cases","approved runs","vertical intelligence"],"tools":["bash","git"],"preconditions":[".agent exists"],"constraints":["local-only by default","human-approved runs only","redaction required before trainable","do not train models"],"category":"operations"}
88
{"name":"design-md","version":"2026-04-26","triggers":["DESIGN.md","design.md","Google Stitch","Stitch","design tokens","design system","visual design"],"tools":["bash","memory_reflect"],"preconditions":["DESIGN.md exists at project root"],"constraints":["prefer DESIGN.md tokens over invented values","do not modify DESIGN.md unless the user explicitly asks","preserve unknown sections when an edit IS authorised","validate when tooling is available"],"category":"design"}

.agent/skills/data-layer/SKILL.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ The goal is local business intelligence for the whole agent suite:
2525
- workflow success/error rates
2626
- KPI summary rows for cron cadence, run volume, reliability, active agents,
2727
workflow breadth, token usage, and estimated cost
28+
- terminal dashboard visible directly in the user's coding tool
2829
- screenshot-ready daily resource reports
2930

3031
## Hard Rules
@@ -59,6 +60,9 @@ Run:
5960
python3 .agent/tools/data_layer_export.py --window 30d --bucket day
6061
```
6162

63+
The command prints a compact terminal dashboard by default, then writes the
64+
full browser dashboard and data files.
65+
6266
Use `--bucket hour`, `--bucket day`, `--bucket week`, or `--bucket month` for
6367
different chart grains.
6468

@@ -81,6 +85,7 @@ Key outputs:
8185
- `dashboard-summary.json`
8286
- `dashboard-report.json`
8387
- `dashboard.html`
88+
- `dashboard.tui.txt`
8489
- `daily-report.md`
8590

8691
## Categories

.agent/tools/data_layer_export.py

Lines changed: 85 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
"""Local data layer export for the portable agentic-stack brain.
33
44
Reads shared `.agent/` memory plus optional local data-layer inputs and writes
5-
dashboard-ready JSONL, JSON, CSV, and a dependency-free HTML dashboard.
5+
dashboard-ready JSONL, JSON, CSV, a dependency-free HTML dashboard, and a
6+
terminal dashboard.
67
78
No network calls, no external dependencies, no telemetry.
89
"""
@@ -760,6 +761,7 @@ def build_dashboard_report(args: argparse.Namespace, summary: dict[str, Any]) ->
760761
"timezone": args.timezone,
761762
"generated_at": summary["generated_at"],
762763
"dashboard_html": "dashboard.html",
764+
"terminal_dashboard": "dashboard.tui.txt",
763765
"daily_report_md": "daily-report.md",
764766
"screenshot_target": "dashboard.html",
765767
"charts": [
@@ -812,6 +814,85 @@ def write_daily_report(path: Path, summary: dict[str, Any]) -> None:
812814
)
813815

814816

817+
def compact_value(value: Any, prefix: str = "", suffix: str = "") -> str:
818+
n = safe_num(value)
819+
if n is None:
820+
return "n/a"
821+
if abs(n) >= 1000000:
822+
text = f"{n / 1000000:.1f}M"
823+
elif abs(n) >= 1000:
824+
text = f"{n / 1000:.1f}k"
825+
elif n == int(n):
826+
text = str(int(n))
827+
else:
828+
text = f"{n:.2f}".rstrip("0").rstrip(".")
829+
return f"{prefix}{text}{suffix}"
830+
831+
832+
def plain_bar(value: Any, max_value: float, width: int = 18) -> str:
833+
n = safe_num(value) or 0
834+
filled = 0 if max_value <= 0 else int(round(n / max_value * width))
835+
filled = max(0, min(width, filled))
836+
return "#" * filled + "-" * (width - filled)
837+
838+
839+
def top_table(rows: list[dict[str, Any]], label_field: str, value_field: str, secondary_value_field: str = "", limit: int = 5) -> list[str]:
840+
if not rows:
841+
return [" no data yet"]
842+
top = rows[:limit]
843+
values = [
844+
(safe_num(row.get(value_field)) or 0) + (safe_num(row.get(secondary_value_field)) or 0)
845+
for row in top
846+
]
847+
max_value = max(values + [1])
848+
lines = []
849+
for row, value in zip(top, values):
850+
label = str(row.get(label_field) or "unknown")[:22].ljust(22)
851+
lines.append(f" {label} [{plain_bar(value, max_value)}] {compact_value(value)}")
852+
return lines
853+
854+
855+
def render_terminal_dashboard(out_dir: Path) -> str:
856+
summary = json.loads((out_dir / "dashboard-summary.json").read_text(encoding="utf-8"))
857+
activity = json.loads((out_dir / "activity-series.json").read_text(encoding="utf-8"))
858+
categories = json.loads((out_dir / "category-summary.json").read_text(encoding="utf-8"))
859+
harnesses = json.loads((out_dir / "harness-summary.json").read_text(encoding="utf-8"))
860+
workflows = json.loads((out_dir / "workflow-summary.json").read_text(encoding="utf-8"))
861+
862+
resources = summary["resources"]
863+
counts = summary["counts"]
864+
latest_activity = activity[-1] if activity else {}
865+
lines = [
866+
"agentic-stack Data Layer - Terminal Dashboard",
867+
f"project={summary['project']} window={summary['window']} bucket={summary['bucket']} generated={summary['generated_at']}",
868+
"",
869+
"Resource Overview",
870+
f" Agent events : {compact_value(counts['agent_events'])}",
871+
f" Cron runs : {compact_value(counts['cron_runs'])}",
872+
f" Harnesses : {compact_value(counts['harnesses'])}",
873+
f" Active agents: {compact_value(counts['active_agents'])}",
874+
f" Tokens est. : {compact_value(resources['tokens_total_estimate'])}",
875+
f" Cost est. : {compact_value(resources['cost_estimate_usd'], prefix='$')}",
876+
"",
877+
"Latest Bucket",
878+
f" {latest_activity.get('bucket_start', 'no activity')} events={compact_value(latest_activity.get('agent_events'))} cron={compact_value(latest_activity.get('cron_runs'))} tokens={compact_value(latest_activity.get('tokens_total_estimate'))}",
879+
"",
880+
"Top Harnesses",
881+
*top_table(harnesses, "harness", "agent_events", "cron_runs"),
882+
"",
883+
"Top Workflows",
884+
*top_table(workflows, "workflow", "agent_events", "cron_runs"),
885+
"",
886+
"Top Categories",
887+
*top_table(categories, "category", "agent_events", "cron_runs"),
888+
"",
889+
f"Open in browser: {out_dir / 'dashboard.html'}",
890+
f"Terminal copy : {out_dir / 'dashboard.tui.txt'}",
891+
"Privacy : local-only; screenshots require explicit user approval",
892+
]
893+
return "\n".join(lines) + "\n"
894+
895+
815896
def export(args: argparse.Namespace) -> Path:
816897
agent_root = Path(args.agent_root).resolve()
817898
data_dir = agent_root / "data-layer"
@@ -892,6 +973,7 @@ def export(args: argparse.Namespace) -> Path:
892973
write_json(out_dir / "dashboard-report.json", dashboard_report)
893974
write_dashboard(out_dir / "dashboard.html", summary, activity, categories, harnesses, workflows, cron_runs, cron_timeline, kpis)
894975
write_daily_report(out_dir / "daily-report.md", summary)
976+
(out_dir / "dashboard.tui.txt").write_text(render_terminal_dashboard(out_dir), encoding="utf-8")
895977
return out_dir
896978

897979

@@ -912,6 +994,8 @@ def main() -> int:
912994
out_dir = export(args)
913995
print(f"agentic-stack data layer export: {out_dir}")
914996
print(f"dashboard_html={out_dir / 'dashboard.html'}")
997+
print()
998+
print(render_terminal_dashboard(out_dir), end="")
915999
return 0
9161000

9171001

CHANGELOG.md

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,39 @@ All notable changes to this project.
55
The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
66
and the project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [0.11.1] — 2026-04-26
9+
10+
Patch release. Makes the data-layer dashboard visible directly in coding-tool
11+
terminals and adds a visual SVG explainer for the data-layer flow.
12+
13+
### Added
14+
- **Terminal dashboard by default.** The existing
15+
`python3 .agent/tools/data_layer_export.py --window 30d --bucket day`
16+
command now prints a compact TUI-style dashboard after writing exports. It
17+
shows resource numbers, latest bucket activity, top harnesses, top workflows,
18+
top categories, and artifact paths without requiring a browser.
19+
- **`dashboard.tui.txt`.** The same terminal dashboard is saved next to
20+
`dashboard.html`, CSV/JSON exports, and `daily-report.md` for agents and
21+
users who want to inspect or attach a plain-text report.
22+
- **`docs/data-layer.svg`.** README and `docs/data-layer.md` now include a
23+
visual of the local data-layer flow: input streams, exporter, browser
24+
dashboard, terminal dashboard, CSV/JSON, and approved handoff.
25+
26+
### Changed
27+
- `dashboard-report.json` now advertises the terminal dashboard artifact.
28+
- Data-layer docs no longer require a separate command to see the terminal
29+
view; the normal export command prints it.
30+
31+
### Migration
32+
No migration required. Existing data-layer commands still work; they now print
33+
the terminal dashboard in addition to the previous status lines.
34+
35+
### Release
36+
- Tag `v0.11.1` cut from master.
37+
- GitHub release: <https://github.com/codejunkie99/agentic-stack/releases/tag/v0.11.1>
38+
- `Formula/agentic-stack.rb` bumped to v0.11.1 in a follow-up commit after
39+
the tag tarball existed and its sha256 could be computed.
40+
841
## [0.11.0] — 2026-04-26
942

1043
Minor release. Adds two local-first data capabilities: a cross-harness
@@ -46,8 +79,7 @@ private and regenerated; both are gitignored.
4679
### Release
4780
- Tag `v0.11.0` cut from master.
4881
- GitHub release: <https://github.com/codejunkie99/agentic-stack/releases/tag/v0.11.0>
49-
- `Formula/agentic-stack.rb` bumped to v0.11.0 in a follow-up commit after
50-
the tag tarball existed and its sha256 could be computed.
82+
- Superseded by v0.11.1 before the Homebrew formula bump.
5183

5284
### Credits
5385
- PR #25 and PR #26 by @danielfoch.

README.md

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ agents from one place: harness activity, cron runs, active agents, token/cost
99
estimates, KPI summaries, user-defined resource categories, and
1010
screenshot-ready daily dashboards.
1111

12+
<p align="center">
13+
<img src="docs/data-layer.svg" alt="agentic-stack data layer dashboard flow" width="880"/>
14+
</p>
15+
1216
And it can turn approved, redacted runs into local flywheel artifacts:
1317
trace records, context cards, eval cases, training-ready JSONL, and readiness
1418
metrics without training a model or sending telemetry.
@@ -21,10 +25,30 @@ metrics without training a model or sending telemetry.
2125
<img src="docs/diagram.svg" alt="agentic-stack architecture" width="880"/>
2226
</p>
2327

24-
### New in v0.11.0 — data layer + data flywheel
28+
### New in v0.11.1 — terminal data dashboard
29+
30+
Patch release. The data layer now shows a terminal dashboard by default, so
31+
people can inspect agent activity inside the coding tool they are already
32+
using, without opening a browser or learning another command.
33+
34+
- **Terminal dashboard by default.** The existing
35+
`python3 .agent/tools/data_layer_export.py --window 30d --bucket day`
36+
command now prints a compact TUI-style report with resource numbers, latest
37+
bucket activity, top harnesses, top workflows, top categories, and links to
38+
the generated artifacts.
39+
- **Saved text dashboard.** The same terminal view is written to
40+
`dashboard.tui.txt` beside `dashboard.html`, CSV, JSON, and
41+
`daily-report.md`.
42+
- **Data-layer SVG.** README and data-layer docs now include a visual of the
43+
local flow: input streams -> exporter -> browser dashboard, terminal
44+
dashboard, CSV/JSON, and approved handoff.
2545

26-
Minor release. Adds two local-first data capabilities for teams running
27-
multiple agent harnesses against the same `.agent/` brain.
46+
See [CHANGELOG.md](CHANGELOG.md) for the full list.
47+
48+
### v0.11.0 — data layer + data flywheel
49+
50+
Added two local-first data capabilities for teams running multiple agent
51+
harnesses against the same `.agent/` brain.
2852

2953
- **`data-layer` seed skill.** Generate local dashboard exports across Claude
3054
Code, Hermes, OpenClaw, Codex, Cursor, OpenCode, and custom loops:
@@ -35,8 +59,6 @@ multiple agent harnesses against the same `.agent/` brain.
3559
metrics. It is local-only and model-agnostic; it prepares artifacts but
3660
does not train models or call external APIs.
3761

38-
See [CHANGELOG.md](CHANGELOG.md) for the full list.
39-
4062
### v0.10.0 — design-md skill + Python 3.9 fix
4163

4264
Added the `design-md` seed skill for root `DESIGN.md` / Google Stitch
@@ -414,8 +436,9 @@ python3 .agent/tools/data_layer_export.py --window 30d --bucket day
414436
```
415437

416438
Outputs land in `.agent/data-layer/exports/<date>/`, including
417-
`dashboard.html` and `daily-report.md`. Optional local inputs let you add
418-
scheduled runs and categories:
439+
`dashboard.html`, `dashboard.tui.txt`, and `daily-report.md`. The command also
440+
prints the compact terminal dashboard directly inside your coding tool. Optional
441+
local inputs let you add scheduled runs and categories:
419442

420443
```text
421444
.agent/data-layer/cron-runs.jsonl

docs/data-layer.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ The data layer gives the portable `.agent/` brain a local dashboard for the
44
entire suite of agents: Claude Code, Hermes, OpenClaw, Codex, Cursor, OpenCode,
55
Windsurf, Pi, Antigravity, and custom loops.
66

7+
<p align="center">
8+
<img src="data-layer.svg" alt="agentic-stack data layer dashboard flow" width="880"/>
9+
</p>
10+
711
It is a companion to the GStack Data Layer idea, adapted for agentic-stack's
812
core promise: one shared memory-and-skills layer across many harnesses.
913

@@ -89,13 +93,23 @@ Outputs:
8993
dashboard-summary.json
9094
dashboard-report.json
9195
dashboard.html
96+
dashboard.tui.txt
9297
daily-report.md
9398
```
9499

95100
`dashboard.html` is dependency-free and screenshot-ready. It renders resource
96101
overview, activity, token usage, cron frequency, task categories, harness mix,
97102
workflow outcomes, a Gantt-style cron panel, and cron timeline tables.
98103

104+
The same command prints a compact terminal dashboard after export:
105+
106+
```bash
107+
python3 .agent/tools/data_layer_export.py --window 30d --bucket day
108+
```
109+
110+
This is useful inside coding tools where the agent and user share a terminal.
111+
The same text view is also saved as `dashboard.tui.txt`.
112+
99113
## KPI Coverage
100114

101115
The first exporter focuses on universal agent-operations KPIs that apply across

0 commit comments

Comments
 (0)