Commit Diff


commit - c8e3c5f06180d15bf331fbefe09eba169f617038
commit + 12ba2f2c78139c78d96c01a668b70e22dfdf9aa2
blob - 65e2267280ea6945baa53e5dcb28b27e683bb5ce
blob + 870280a852c9319b649d4f7366ea6ade73a72f2a
--- README.md
+++ README.md
@@ -219,9 +219,9 @@ temporary file. When the editor exits nonzero, `alpaca
 status.
 
 `alpaca` saves each successful request as a JSON transcript in
-`$XDG_DATA_HOME/alpaca` or `~/.local/share/alpaca`. `alpaca` writes files with mode
-`0600` in a directory with mode `0700`. Each turn sends the whole conversation
-as context.
+`$XDG_DATA_HOME/alpaca` or `~/.local/share/alpaca`. `alpaca` writes files with
+mode `0600` in a directory with mode `0700`. Each turn sends the whole
+conversation as context.
 
 When the editor is `vim` or `neovim`, `alpaca` keeps one editor open for the
 whole conversation instead of reopening it each turn. Writing the buffer sends
@@ -248,8 +248,8 @@ See `man/alpaca-compose.1`.
 window as a bar showing the used share, with a countdown to the next reset.
 Some providers also report a table of per-model counts.
 
-Pick a provider with `-p`. Without it, alpaca reports all providers in one output
-and skips the ones it cannot reach:
+Pick a provider with `-p`. Without it, `alpaca` reports all providers in one
+output and skips the ones it cannot reach:
 
 ```sh
 $ alpaca quota                 # all providers
@@ -292,24 +292,23 @@ account. It needs an Admin API key with the `api.usage
 `platform.openai.com/settings/organization/admin-keys`. A regular project
 key, such as `sk-proj-...`, gets a 403.
 
-DeepInfra bills per token or per second, with no fixed quota. alpaca prints
+DeepInfra bills per token or per second, with no fixed quota. `alpaca` prints
 no window for it. It prints the remaining credit as a note. A negative balance
 is funds ready to spend, and a positive one is money owed.
 
 The Ollama provider reports Ollama Cloud usage. It takes the key from
 `$OLLAMA_API_KEY` and defaults to `https://ollama.com`. You can override this
 with `$OLLAMA_API_ENDPOINT`. It shows the monthly usage pool as the share of
-the plan's credits used, with per-model request counts and any extra spend
-beyond the plan. The endpoint reports no reset time, so no reset is shown.
-Accounts on the old billing get the 5 hour and weekly windows instead, with
-locally computed reset boundaries.
+the plan's credits used, and any extra spend beyond the plan. The endpoint
+reports no reset time, so no reset is shown. Accounts on the old billing get
+the 5 hour and weekly windows instead, with locally computed reset boundaries.
 
 The Codex provider reports your ChatGPT plan usage, not organization spend.
-alpaca reads the OAuth token the Codex CLI stores in `$CODEX_HOME/auth.json`,
+`alpaca` reads the OAuth token the Codex CLI stores in `$CODEX_HOME/auth.json`,
 defaulting to `~/.codex/auth.json`. Sign in once with `codex` and the report
 works. `--apikey` replaces that token. The endpoint serves the Codex CLI and
 the ChatGPT client, so it is not a documented public API and may change
-without notice. alpaca prints the 5 hour and weekly windows with their reset
+without notice. `alpaca` prints the 5 hour and weekly windows with their reset
 times, the plan name, and the credits balance when the plan has one.
 
 The top-level `base_url` configures the chat endpoint only, so `alpaca quota`
@@ -324,7 +323,7 @@ Synthetic, DeepInfra and Ollama also fall back to the 
 nothing more specific names one, because all three double as chat endpoints.
 Anthropic and OpenAI never serve chat, so they ignore the top-level `apikey`
 and always need a key from a table or profile. Without a chosen provider,
-alpaca resolves each provider key on its own, exactly as an explicit `-p`
+`alpaca` resolves each provider key on its own, exactly as an explicit `-p`
 would. It never sends the top-level `apikey` to all providers.
 
 Options:
blob - be87851ab36a15e4c8b18a41e58b8a7981938ae5
blob + 7067c3e1bf36af142b3e44c2c51e72410f9d0cba
--- man/alpaca-compose.1.scd
+++ man/alpaca-compose.1.scd
@@ -26,10 +26,10 @@ output out of the pipeline. If there is no controlling
 inherits the process's streams. Saving an empty buffer sends nothing and ends
 the session with status 0.
 
-Each successful request is saved as a JSON transcript in _$XDG_DATA_HOME/alpaca_,
-or _~/.local/share/alpaca_ when that variable is unset. *alpaca* writes the
-transcripts with mode 0600 in a directory with mode 0700. Each turn sends the
-whole conversation as context.
+Each successful request is saved as a JSON transcript in
+_$XDG_DATA_HOME/alpaca_, or _~/.local/share/alpaca_ when that variable is
+unset. *alpaca* writes the transcripts with mode 0600 in a directory with mode
+0700. Each turn sends the whole conversation as context.
 
 When the editor is *vim* or *neovim*, *alpaca* keeps one editor open for the
 whole conversation instead of reopening it each turn. Writing the buffer
@@ -49,7 +49,8 @@ until the reply arrives and reloads the buffer. Classi
 # Options
 
 *-m*, *--model* _model_
-	The model to use. It defaults to *ALPACA_MODEL*, or *gpt-4o-mini* if that is not set.
+	The model to use. It defaults to *ALPACA_MODEL*, or *gpt-4o-mini* if that
+	is not set.
 
 *-s*, *--system* _msg_
 	The system prompt, sent before the conversation.
@@ -58,7 +59,8 @@ until the reply arrives and reloads the buffer. Classi
 	The sampling temperature.
 
 *-T*, *--timeout* _secs_
-	The request timeout in seconds. It defaults to *ALPACA_TIMEOUT*, or 60 if that is not set.
+	The request timeout in seconds. It defaults to *ALPACA_TIMEOUT*, or 60 if
+	that is not set.
 
 *--reasoning-effort* _effort_
 	One of *low*, *medium*, *high* or *none*.
@@ -87,13 +89,13 @@ until the reply arrives and reloads the buffer. Classi
 
 # Configuration
 
-This command reads its settings from the Alpaca configuration file.
+This command reads its settings from the alpaca configuration file.
 Command-line options and environment variables take priority. See
 *alpaca-config*(5).
 
 # Exit status
 
-An editor that exits non-zero sets the exit status of *alpaca compose*, so
+An editor that exits nonzero sets the exit status of *alpaca compose*, so
 aborting an edit aborts the request. Usage errors exit 2.
 
 # Examples
blob - 682c73da29d5c26d031ce1a3ba47e72f53941cd6
blob + c681e966e24eb9df81f0c4848ad4f472d17b388c
--- man/alpaca-config.5.scd
+++ man/alpaca-config.5.scd
@@ -6,10 +6,10 @@ alpaca-config - configure default options for alpaca
 
 # Description
 
-Alpaca reads shared defaults from _$XDG_CONFIG_HOME/alpaca/config.toml_. If you
-do not set *XDG_CONFIG_HOME*, Alpaca reads _~/.config/alpaca/config.toml_.
+alpaca reads shared defaults from _$XDG_CONFIG_HOME/alpaca/config.toml_. If you
+do not set *XDG_CONFIG_HOME*, alpaca reads _~/.config/alpaca/config.toml_.
 
-The file is optional. Alpaca exits with an error if the file exists but cannot
+The file is optional. alpaca exits with an error if the file exists but cannot
 be read or parsed.
 
 Settings take priority in this order:
blob - 3054cefdd7e70d720bfe12a8f5da5d42dfc7672f
blob + 73d2f1b89863c2428a43fc1e9ec679b4168449f6
--- man/alpaca-quota.1.scd
+++ man/alpaca-quota.1.scd
@@ -67,11 +67,10 @@ all providers.
 *ollama*
 	Ollama Cloud. It takes the key from *OLLAMA_API_KEY*. The base URL is
 	*https://ollama.com*, or *$OLLAMA_API_ENDPOINT* when set. It prints the
-	monthly usage pool as the share of the plan's credits used, a table of
-	per-model request counts, and any extra spend beyond the plan. It shows
-	no reset, because the endpoint reports no reset time. Accounts on the
-	old billing get the 5 hour and weekly windows instead, with locally
-	computed reset boundaries.
+	monthly usage pool as the share of the plan's credits used, and any extra
+	spend beyond the plan. It shows no reset, because the endpoint reports no
+	reset time. Accounts on the old billing get the 5 hour and weekly windows
+	instead, with locally computed reset boundaries.
 
 The *anthropic* endpoint is not a documented public API, so it may change
 without notice. It expects the short-lived OAuth token the Claude Code CLI
@@ -86,7 +85,8 @@ again.
 	cannot reach.
 
 *-T*, *--timeout* _secs_
-	The request timeout in seconds. It defaults to *ALPACA_TIMEOUT*, or 60 if that is not set.
+	The request timeout in seconds. It defaults to *ALPACA_TIMEOUT*, or 60 if
+	that is not set.
 
 *--apikey* _key_
 	The API key or OAuth token, replacing the provider default.
@@ -111,7 +111,7 @@ again.
 
 # Configuration
 
-This command uses *output_format* and *timeout* from the Alpaca configuration
+This command uses *output_format* and *timeout* from the alpaca configuration
 file. Top-level *base_url* configures the chat endpoint, so this command
 never uses it for any provider: each provider already has the correct
 endpoint built in. A table named after a provider, such as *[anthropic]* or
blob - 1c77f2c18a36211a336d9b1aecef268ee748227a
blob + 85f0dcefd1e752e0a7d65127804491b6c96c1502
--- man/alpaca.1.scd
+++ man/alpaca.1.scd
@@ -43,13 +43,15 @@ as in *alpaca -- quota*.
 # Options
 
 *-m*, *--model* _model_
-	The model to use. It defaults to *ALPACA_MODEL*, or *gpt-4o-mini* if that is not set.
+	The model to use. It defaults to *ALPACA_MODEL*, or *gpt-4o-mini* if that
+	is not set.
 
 *-t*, *--temperature* _temp_
 	The sampling temperature.
 
 *-T*, *--timeout* _secs_
-	The request timeout in seconds. It defaults to *ALPACA_TIMEOUT*, or 60 if that is not set.
+	The request timeout in seconds. It defaults to *ALPACA_TIMEOUT*, or 60 if
+	that is not set.
 
 *-s*, *--system* _msg_
 	The system prompt. It is always sent first.
blob - e133bb147b6c894ab6b24ff1746faee228cd1130
blob + 411e416a1df5089621a257b95bdb8789d2ec85a3
--- src/usage/ollama.rs
+++ src/usage/ollama.rs
@@ -126,13 +126,10 @@ fn build(usage: &Usage, now: DateTime<Utc>) -> View {
             rows: sorted(&limits.weekly.models),
         });
     }
+    // The monthly pool is a credit pool, not a request window: its per-model
+    // request counts are not shown.
     if let Some(used) = limits.monthly.usage {
         windows.push(Window::new("monthly", used, None));
-        tables.push(Table {
-            heading: "monthly models".to_string(),
-            unit: "reqs",
-            rows: sorted(&limits.monthly.models),
-        });
     }
     if !usage.activity.models.is_empty() {
         tables.push(Table {
@@ -262,21 +259,9 @@ mod test {
             view.windows[0].resets_in_secs, None,
             "the monthly pool renews on the plan start day, which is not reported"
         );
-        assert_eq!(view.tables.len(), 1);
-        assert_eq!(view.tables[0].heading, "monthly models");
-        assert_eq!(
-            view.tables[0].rows,
-            vec![
-                ModelCount {
-                    name: "kimi-k3".to_string(),
-                    requests: 329
-                },
-                ModelCount {
-                    name: "web search".to_string(),
-                    requests: 4
-                }
-            ],
-            "models are sorted busiest first"
+        assert!(
+            view.tables.is_empty(),
+            "the monthly pool has no per-model table"
         );
         Ok(())
     }
@@ -308,9 +293,9 @@ mod test {
         }"#,
         )?;
 
-        assert_eq!(view.tables[0].heading, "monthly models");
-        assert_eq!(view.tables[1].heading, "activity models");
-        assert_eq!(view.tables[1].rows[0].name, "kimi-k3");
+        assert_eq!(view.tables.len(), 1);
+        assert_eq!(view.tables[0].heading, "activity models");
+        assert_eq!(view.tables[0].rows[0].name, "kimi-k3");
         Ok(())
     }
 
blob - 409a19f4c2734c1d40d110e90edd994f97125775
blob + 43367bb1052185e2fdb34f469619c5a820e8ffe0
--- tests/quota.rs
+++ tests/quota.rs
@@ -660,8 +660,8 @@ fn ollama_quota_reports_the_monthly_pool_of_the_new_bi
         predicate::str::contains("ollama cloud usage")
             .and(predicate::str::contains("monthly"))
             .and(predicate::str::contains("87.6%"))
-            .and(predicate::str::contains("monthly models"))
-            .and(predicate::str::contains("kimi-k3"))
+            .and(predicate::str::contains("monthly models").not())
+            .and(predicate::str::contains("kimi-k3").not())
             .and(predicate::str::contains("extra 0.00000 USD"))
             .and(predicate::str::contains("resets in").not()),
     );