Console Resource Panel: Design Exploration
Status: Design exploration for Console resource panel (Phase 2, Agent Orchestration Program) — not yet implemented.
Problem
The operator console renders a fixed view: workspace list, agent picker, mounts. It doesn't show what's happening on the machine. When five agents are running and one is consuming 14 GiB of RAM, the operator finds out by watching their machine swap, not by looking at the console.
Without this panel, the declarative resource limits work is invisible — operators can't see what the limits are doing. Direct visibility into per-agent CPU/RAM usage closes the feedback loop: operator sets memory_max = 16 GiB, watches the agent crawl up to 14 GiB, makes an informed decision about whether to raise the limit or kill the agent. A host-level summary (total CPU/RAM used, free, by jackin❯ vs system) tells the operator at a glance whether they have headroom for another agent.
Inspiration in multicode
Sources:
- No dedicated README section (implementation-only feature)
- Source —
lib/src/services/resource_usage_service.rs(per-workspace + machine sampling) - Source —
tui/src/render.rs(panel rendering)
multicode samples three sources every 2 seconds: /proc/stat for total CPU usage delta, /proc/meminfo for RAM, and du -sBc (or platform equivalent) for workspace disk usage. Per-workspace samples come from cgroup files inside the systemd unit: cpuacct.usage_nsec (delta over the 2s window → percent), memory.current (current bytes), and MemoryOomCount from systemd properties.
The TUI displays these as columns: machine CPU%, machine RAM, per-workspace CPU%, per-workspace RAM. RAM cells turn yellow when near the configured memory_max. OOM kills and file-descriptor pressure are highlighted explicitly.
Recommended shape
Two distinct concerns plumbed through the same console panel:
- Per-agent usage — live CPU% and RAM bytes per running container, plus configured limit (from declarative resource limits) for context.
- Machine summary — total host CPU%, total host RAM used/free, total disk space used by
~/.jackin/data/.
Per-agent sampling
Use the Docker stats API (docker stats --no-stream, or a new typed stats endpoint added to the DockerApi trait in crates/jackin-core/src/docker.rs — no such endpoint exists yet; today's trait covers container/network/image lifecycle only, not stats). Sample every 2 seconds while the console is open; pause sampling when the panel is collapsed.
Fields per agent:
cpu_percent: f32(relative to one host core)memory_bytes: u64(current RSS-equivalent)memory_limit_bytes: u64?(from declared limit; renders "no limit" when absent)memory_near_limit: bool(derived from configured limit and current usage)oom_kill_count: u64(sticky until container restart)nofile_limit: u64?andopen_file_descriptors: u64?when the backend can report them
Machine sampling
Cross-platform — the sysinfo crate is already a workspace dependency (used today for OTLP process-metric sampling in crates/jackin-diagnostics/src/observability.rs), so reuse it for CPU/RAM here rather than adding a second dependency. For the data-dir disk usage, walk ~/.jackin/data/ once on console open and after instance lifecycle changes such as load, hardline recovery, clean exit, or purge; also show free disk for the filesystem containing the jackin❯ data directory. Do not poll disk usage on every render.
Console rendering
A new optional panel (toggled with a keystroke, e.g. t for "telemetry") that splits the bottom of the console into two regions: machine summary on the left, per-agent table on the right. When collapsed, the panel is absent and sampling pauses. The per-agent table should include a status column sourced from the now-shipped agent runtime status authority.
Scope sketched for a V1
- Per-agent CPU%, RAM, RAM-vs-limit, OOM count, and file-descriptor limit when available — sampled via Docker stats or backend-specific APIs.
- Machine summary: total CPU%, total RAM, data-dir disk usage, and free disk.
- 2-second sample interval while panel is open; paused when closed.
- Console keystroke toggles the panel; defaults to closed.
- Sample failures (Docker unreachable, container gone) degrade silently — show "?" cells without surfacing an error dialog.
Deferred by design
- Network I/O bytes per agent. Useful but lower-priority.
- Disk I/O per agent. Same.
- Historical graphs (sparklines, rolling 5-minute window). Defer until persistent storage layer ships and jackin❯ can keep a rolling sample buffer.
- Alert thresholds ("notify me when an agent exceeds 90% of limit"). Defer; operators can watch the cell color in V1.
- CSV/Prometheus export. Defer.
Open design questions
- Sampling backend abstraction. Sample-via-Docker today; sample-via-cgroup-files when selectable backends lands. Which module owns the abstraction? Candidate: the runtime backend trait owns it, mirroring how each backend already owns mount translation.
- Always-on vs on-demand sampling. multicode samples constantly even when the panel isn't visible, because the data feeds usage aggregation. jackin❯ V1 doesn't need that yet — pause-when-closed looks like the right call. Revisit when Token & Cost Telemetry needs a continuous series.
- Keystroke choice.
tfor telemetry,rfor resources,mfor metrics — pick once and document. Defer to a console UX review.
Related files
- New module (e.g.
src/console/panels/resources.rs) — panel rendering + sampling loop, does not exist yet crates/jackin/src/console/tui.rs— keybinding wiringcrates/jackin-runtime/src/runtime/launch.rs— plausible home for a sampling adapter trait, moving into per-backend modules over time