Skip to content

Commit 2a14533

Browse files
committed
Add configurable live-limits and app-server detection
Introduce configurable live limits handling and explicit app-server selection. Adds --live-limits (auto|on|off) and --app-server-bin flags, a LiveLimitsMode config, and AppServerCommand + resolve_app_server_command to detect/launch either `codex app-server` or a standalone app-server (with Windows auto-detection of bundled locations). UI and app state now surface non-error notices vs errors when limits are unavailable, and token metrics show total/out-of-cache pairs. Update usage snapshot to track cached input tokens, adjust related rendering/formatting, and add docs (AGENTS.md, README) and changelog entry; minor test updates and ergonomics/refactors included. Version bumped to 0.3.6. Revert "Add configurable live-limits and app-server detection" This reverts commit eb81244. Reapply "Add configurable live-limits and app-server detection" This reverts commit 83cd1fd. Delete file
1 parent 6954d50 commit 2a14533

10 files changed

Lines changed: 477 additions & 48 deletions

File tree

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@
22

33
All notable changes to this project are documented in this file.
44

5+
## 0.3.6 - 2026-06-05
6+
7+
- Added `--live-limits auto|on|off` so app-only installs can run without a live-limits spawn error.
8+
- Added `--app-server-bin` for standalone Codex App Server executables.
9+
- Added Windows auto-detection for common Codex App bundled App Server locations.
10+
- Project activity token headers now show total/out-of-cache token pairs.
11+
512
## 0.3.4 - 2026-04-24
613

714
- Fixed inflated usage totals from forked/subagent session logs by ignoring replayed parent-session token history while preserving new post-fork usage.

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "comon"
3-
version = "0.3.5"
3+
version = "0.3.6"
44
edition = "2021"
55
license = "Apache-2.0"
66

README.md

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Single-binary, cross-platform TUI for:
66

77
- Local Codex usage stats (last 7/30 days, chart, top models) by scanning `CODEX_HOME/sessions`.
88
- Local session-history browser grouped by project path, with session titles and prompt previews.
9-
- Live account limits/credits by spawning `codex app-server` and calling `account/rateLimits/read`.
9+
- Live account limits/credits by spawning Codex App Server and calling `account/rateLimits/read` when an App Server executable is available.
1010

1111
See `CHANGELOG.md` for release history.
1212

@@ -38,7 +38,7 @@ See `CHANGELOG.md` for release history.
3838

3939
- Rust toolchain (stable) installed.
4040
- C/C++ compiler toolchain available (needed to build bundled SQLite through `rusqlite`).
41-
- Codex CLI installed and available as `codex` on your `PATH` (required for live limits/credits).
41+
- Codex CLI installed as `codex` on your `PATH`, or a discoverable/explicit Codex App Server executable (required only for live limits/credits).
4242
- Usage stats still work without Codex CLI (they only need the session logs on disk).
4343
- For portable Linux builds (`--musl`), `rustup` and musl target toolchain support are required.
4444

@@ -52,7 +52,7 @@ Use `--project <path>` (or `--workspace <path>`) to filter usage stats to a spec
5252

5353
If `--project` points to a non-git directory, `comon` falls back to **All workspaces**.
5454

55-
`--cwd` controls where `codex app-server` is launched and does not change usage scope.
55+
`--cwd` controls where Codex App Server is launched and does not change usage scope.
5656

5757
```bash
5858
# If installed (recommended):
@@ -73,8 +73,10 @@ Common flags:
7373
- `-r` / `--read`: start on the Session history screen
7474
- `--sessions-dir <path>`: override the Codex sessions directory used by the Session history screen
7575
- `--print-sessions-dir`: print effective sessions directory and exit
76-
- `--codex-bin <path>`: override Codex CLI binary (default: `codex`)
77-
- `--cwd <path>`: directory to launch `codex app-server` in (default: current directory; does not change usage scope)
76+
- `--codex-bin <path>`: override Codex CLI binary (spawned as `<path> app-server`)
77+
- `--app-server-bin <path>`: override a standalone Codex App Server executable (spawned directly)
78+
- `--live-limits <auto|on|off>`: `auto` tries App Server if found, `on` requires it, `off` disables live limits (default: `auto`)
79+
- `--cwd <path>`: directory to launch Codex App Server in (default: current directory; does not change usage scope)
7880
- `--project <path>` / `--workspace <path>`: filter usage stats to a specific project/workspace (also becomes default `--cwd` if `--cwd` not set)
7981
- `--usage-days <n>`: days to scan for usage (clamped 1..=90; default from config)
8082
- `--refresh-usage-secs <n>`: usage refresh interval in seconds (default from config)
@@ -119,6 +121,19 @@ Example:
119121
comon --codex-home "C:\\Users\\You\\.codex" --cwd "C:\\Repos\\some-git-repo"
120122
```
121123

124+
Codex App-only Windows installs:
125+
126+
```bash
127+
# Usage/session history only; avoids App Server probing.
128+
comon --live-limits off
129+
130+
# If auto-detection misses the bundled CLI-style binary:
131+
comon --codex-bin "C:\\Path\\To\\Codex\\codex.exe"
132+
133+
# If the app ships a standalone App Server binary:
134+
comon --app-server-bin "C:\\Path\\To\\Codex\\app-server.exe"
135+
```
136+
122137
Large-log recovery/tuning example:
123138

124139
```bash
@@ -311,7 +326,7 @@ CI also runs this check on each push and pull request via `.github/workflows/asc
311326
## Notes
312327

313328
- Usage stats are derived from Codex session JSONL logs. If you have no session data yet, values will be empty.
314-
- Limits/credits require `codex app-server` to start successfully (auth, environment, and a usable working directory).
329+
- Limits/credits require Codex App Server to start successfully (auth, environment, and a usable working directory). CoMon auto-detects `codex` on `PATH` and common Windows Codex App bundle locations; use `--codex-bin` or `--app-server-bin` when needed.
315330
- comon stores local app state in `~/.comon/state.json` by default (or `$COMON_HOME`, or `--comon-home`).
316331
- comon stores scan cache in `~/.comon/comon.db` to avoid rereading unchanged session files.
317332
- Large session logs are parsed incrementally with persisted parser offsets in `comon.db`; unchanged files are reused from cache.

src/app/mod.rs

Lines changed: 57 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ use tokio::sync::{mpsc, watch};
1515
#[derive(Debug, Clone)]
1616
pub struct Config {
1717
pub codex_bin: Option<String>,
18+
pub app_server_bin: Option<std::path::PathBuf>,
19+
pub live_limits_mode: LiveLimitsMode,
1820
pub comon_home: std::path::PathBuf,
1921
pub codex_home: std::path::PathBuf,
2022
pub read_sessions_dir: std::path::PathBuf,
@@ -28,6 +30,13 @@ pub struct Config {
2830
pub rebuild_cache_on_start: bool,
2931
}
3032

33+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
34+
pub enum LiveLimitsMode {
35+
Auto,
36+
On,
37+
Off,
38+
}
39+
3140
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
3241
pub(crate) enum ChartOrientation {
3342
Vertical,
@@ -48,7 +57,7 @@ enum UsageCommand {
4857
enum AppEvent {
4958
UsageUpdated(Result<LocalUsageSnapshot>),
5059
LimitsUpdated(Result<AccountRateLimits>),
51-
LimitsUnavailable(String),
60+
LimitsUnavailable { message: String, is_error: bool },
5261
}
5362

5463
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
@@ -92,6 +101,7 @@ pub(crate) struct AppState {
92101
pub(crate) limits: Option<AccountRateLimits>,
93102
pub(crate) limits_updated_at: Option<Instant>,
94103
pub(crate) limits_error: Option<String>,
104+
pub(crate) limits_notice: Option<String>,
95105
pub(crate) limits_enabled: bool,
96106
pub(crate) read_sessions_dir: PathBuf,
97107
pub(crate) read_browser: crate::read::tui::BrowserState,
@@ -274,16 +284,45 @@ async fn run_inner(
274284
{
275285
let evt_tx = evt_tx.clone();
276286
let codex_bin = config.codex_bin.clone();
287+
let app_server_bin = config.app_server_bin.clone();
288+
let live_limits_mode = config.live_limits_mode;
277289
let cwd = config.cwd.clone();
278290
let refresh = Duration::from_secs(config.refresh_limits_secs);
279291
let mut limits_refresh_rx = limits_refresh_rx;
280292
let mut shutdown_rx = shutdown_rx.clone();
281293
tokio::spawn(async move {
282-
let rpc = match CodexRpc::spawn(codex_bin, cwd).await {
294+
if live_limits_mode == LiveLimitsMode::Off {
295+
let _ = evt_tx
296+
.send(AppEvent::LimitsUnavailable {
297+
message: "Live limits disabled (--live-limits off).".to_string(),
298+
is_error: false,
299+
})
300+
.await;
301+
return;
302+
}
303+
304+
let Some(app_server) =
305+
crate::codex_rpc::resolve_app_server_command(codex_bin, app_server_bin)
306+
else {
307+
let _ = evt_tx
308+
.send(AppEvent::LimitsUnavailable {
309+
message: missing_app_server_message().to_string(),
310+
is_error: live_limits_mode == LiveLimitsMode::On,
311+
})
312+
.await;
313+
return;
314+
};
315+
let app_server_is_explicit = app_server.is_explicit();
316+
317+
let rpc = match CodexRpc::spawn(app_server, cwd).await {
283318
Ok(rpc) => rpc,
284319
Err(err) => {
285320
let _ = evt_tx
286-
.send(AppEvent::LimitsUnavailable(err.to_string()))
321+
.send(AppEvent::LimitsUnavailable {
322+
message: err.to_string(),
323+
is_error: live_limits_mode == LiveLimitsMode::On
324+
|| app_server_is_explicit,
325+
})
287326
.await;
288327
return;
289328
}
@@ -371,6 +410,7 @@ async fn run_inner(
371410
limits: None,
372411
limits_updated_at: None,
373412
limits_error: None,
413+
limits_notice: None,
374414
limits_enabled: true,
375415
read_sessions_dir: config.read_sessions_dir.clone(),
376416
read_browser,
@@ -705,16 +745,24 @@ fn handle_app_event(state: &mut AppState, evt: AppEvent) -> bool {
705745
}
706746
true
707747
}
708-
AppEvent::LimitsUnavailable(msg) => {
748+
AppEvent::LimitsUnavailable { message, is_error } => {
709749
state.limits_enabled = false;
710-
state.limits_error = Some(msg);
750+
if is_error {
751+
state.limits_error = Some(message);
752+
state.limits_notice = None;
753+
} else {
754+
state.limits_error = None;
755+
state.limits_notice = Some(message);
756+
}
711757
true
712758
}
713759
AppEvent::LimitsUpdated(res) => {
714760
match res {
715761
Ok(limits) => {
762+
state.limits_enabled = true;
716763
state.limits = Some(limits);
717764
state.limits_error = None;
765+
state.limits_notice = None;
718766
state.limits_updated_at = Some(Instant::now());
719767
}
720768
Err(err) => {
@@ -726,6 +774,10 @@ fn handle_app_event(state: &mut AppState, evt: AppEvent) -> bool {
726774
}
727775
}
728776

777+
fn missing_app_server_message() -> &'static str {
778+
"Codex App Server not found; usage/history still work. Install Codex CLI or pass --codex-bin/--app-server-bin."
779+
}
780+
729781
fn load_persisted_ui_state(
730782
comon_home: &Path,
731783
workspace_hint: Option<&Path>,

0 commit comments

Comments
 (0)