# Console Resource Panel: Design Exploration (https://jackin.tailrocks.com/reference/research/agent-orchestration/resource-limits/console-resource-panel-design/)



**Status**: Design exploration for [Console resource panel](/roadmap/console-resource-panel/) (Phase 2, [Agent Orchestration Program](/reference/research/agent-orchestration/program-research/)) — not yet implemented.

## Problem [#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](/roadmap/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 [#inspiration-in-multicode]

**Sources**:

* No dedicated README section (implementation-only feature)
* Source — [`lib/src/services/resource_usage_service.rs`](https://github.com/graemerocher/multicode/blob/main/lib/src/services/resource_usage_service.rs) (per-workspace + machine sampling)
* Source — [`tui/src/render.rs`](https://github.com/graemerocher/multicode/blob/main/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 [#recommended-shape]

Two distinct concerns plumbed through the same console panel:

1. **Per-agent usage** — live CPU% and RAM bytes per running container, plus configured limit (from [declarative resource limits](/roadmap/declarative-resource-limits/)) for context.
2. **Machine summary** — total host CPU%, total host RAM used/free, total disk space used by `~/.jackin/data/`.

### Per-agent sampling [#per-agent-sampling]

Use the Docker stats API (`docker stats --no-stream`, or a new typed stats endpoint added to the `DockerApi` trait in <RepoFile path="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?` and `open_file_descriptors: u64?` when the backend can report them

### Machine sampling [#machine-sampling]

Cross-platform — the `sysinfo` crate is already a workspace dependency (used today for OTLP process-metric sampling in <RepoFile path="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 [#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](/roadmap/agent-runtime-status/).

## Scope sketched for a V1 [#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 [#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](/reference/research/agent-orchestration/memory/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 [#open-design-questions]

* **Sampling backend abstraction.** Sample-via-Docker today; sample-via-cgroup-files when [selectable backends](/reference/research/security/sandbox-backends/selectable-sandbox-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](/reference/research/agent-telemetry/token-cost-telemetry/) needs a continuous series.
* **Keystroke choice.** `t` for telemetry, `r` for resources, `m` for metrics — pick once and document. Defer to a console UX review.

## Related files [#related-files]

* New module (e.g. `src/console/panels/resources.rs`) — panel rendering + sampling loop, does not exist yet
* <RepoFile path="crates/jackin/src/console/tui.rs" /> — keybinding wiring
* <RepoFile path="crates/jackin-runtime/src/runtime/launch.rs" /> — plausible home for a sampling adapter trait, moving into per-backend modules over time
