From 485786035a60fdf8bd287aae49cfb2222441566b Mon Sep 17 00:00:00 2001 From: Maxime Date: Sat, 18 Apr 2026 12:12:14 -0700 Subject: [PATCH 1/3] docs(ai-sessions): document `limacharlie ai session attach` and `ai start-session` overrides Adds a dedicated CLI reference page for AI Sessions and cross-links from the surrounding pages: - New `docs/9-ai-sessions/cli.md` covering `ai session list/get/history/terminate`, `ai session attach` (flags, interactive controls, 403 fallback, output format with colour-coded message table), and `ai start-session` with its full override flag set (model, max-turns, max-budget-usd, task-budget-tokens, ttl-seconds, one-shot, permission-mode, allowed/denied-tools, plugin, env, anthropic-key, lc-api-key, lc-uid). - mkdocs.yml nav: add the new Command Line Interface entry under AI Sessions. - user-sessions.md: add a tip box pointing to the CLI attach command alongside the existing WebSocket example. - dr-sessions.md: note at the end of Example 5 that the same `ai_agent` Hive record can be reused as a CLI template via `ai start-session`. - 6-developer-guide/sdk-overview.md: add an AI Sessions section under Commands with the common invocations and a cross-link to the new page. Cross-links: * python-limacharlie: https://github.com/refractionPOINT/python-limacharlie/pull/278 * lc-ai: (see matching PR) Co-Authored-By: Claude Opus 4.7 (1M context) --- docs/6-developer-guide/sdk-overview.md | 24 +++ docs/9-ai-sessions/cli.md | 258 +++++++++++++++++++++++++ docs/9-ai-sessions/dr-sessions.md | 3 + docs/9-ai-sessions/user-sessions.md | 3 + mkdocs.yml | 1 + 5 files changed, 289 insertions(+) create mode 100644 docs/9-ai-sessions/cli.md diff --git a/docs/6-developer-guide/sdk-overview.md b/docs/6-developer-guide/sdk-overview.md index 502f8b1af..41ff299f0 100644 --- a/docs/6-developer-guide/sdk-overview.md +++ b/docs/6-developer-guide/sdk-overview.md @@ -205,3 +205,27 @@ user3@example.com ```bash limacharlie user add --file users_to_add.txt ``` + +### AI Sessions + +Create, inspect, and attach to [AI Sessions](../9-ai-sessions/index.md) directly from the terminal. The `ai_agent` Hive record named by `--definition` is treated as a reusable template; any matching `--option` replaces the corresponding field for that run (scalars and lists replace; `--env` merges). + +```bash +# Start a session from an ai_agent template, overriding budget and model. +limacharlie ai start-session --definition my-agent \ + --model claude-sonnet-4-6 --max-budget-usd 2.50 + +# List running sessions. +limacharlie ai session list --status running + +# Attach to a running session and stream messages live. +limacharlie ai session attach --id + +# Attach with interactive chat. +limacharlie ai session attach --id --interactive + +# Terminate a session. +limacharlie ai session terminate --id +``` + +See [AI Sessions — Command Line Interface](../9-ai-sessions/cli.md) for the full command reference, override semantics, and stream output formatting. diff --git a/docs/9-ai-sessions/cli.md b/docs/9-ai-sessions/cli.md new file mode 100644 index 000000000..d16e28f99 --- /dev/null +++ b/docs/9-ai-sessions/cli.md @@ -0,0 +1,258 @@ +# Command Line Interface + +The [LimaCharlie Python SDK](../6-developer-guide/sdks/python-sdk.md) ships a `limacharlie ai` command group that covers the full AI Sessions lifecycle from the terminal: creating sessions from an `ai_agent` Hive template with per-run overrides, listing and inspecting sessions, attaching to a live session over WebSocket, and terminating. + +These commands are available in the `cli-v2` release line of the CLI and talk to the same endpoints documented on the [API Reference](api-reference.md) page. Authentication reuses your existing LimaCharlie credentials — no separate AI Sessions token is required. + +!!! note + The CLI is complementary to the [web console](user-sessions.md) and the [TypeScript SDK](sdk.md). Anything you can do from the console (other than file upload/download, which is not yet wired into the CLI) you can do from the CLI. + +## Installation + +```bash +pip install limacharlie +``` + +Then authenticate as described in the [CLI overview](../6-developer-guide/sdk-overview.md#authentication). + +## `limacharlie ai session list` + +List AI sessions for the current organization. + +```bash +limacharlie ai session list +limacharlie ai session list --status running +limacharlie ai session list --status ended --limit 10 +``` + +Options: + +| Flag | Description | +|---|---| +| `--status` | Filter by status: `running`, `starting`, `ended`. | +| `--limit` | Maximum results per page (1 – 200, default 50). | +| `--cursor` | Pagination cursor from a previous response. | + +The `initial_prompt` field is truncated in the list view. Use `ai session get --id --full-prompt` to see the full prompt. + +## `limacharlie ai session get` + +Fetch a single session's metadata (status, model, token usage, cost, trigger info, end reason). + +```bash +limacharlie ai session get --id +limacharlie ai session get --id --full-prompt +``` + +## `limacharlie ai session history` + +Retrieve the full conversation log of a session (user prompts, assistant responses, tool calls, tool results). + +```bash +limacharlie ai session history --id +limacharlie ai session history --id --raw +``` + +Internal system bootstrap messages (credential diagnostics, `claude_md_loaded`, MCP config debug, etc.) are filtered out by default. Pass `--raw` to include them. + +## `limacharlie ai session terminate` + +Terminate a running session. Requires the `ai_agent.set` permission. + +```bash +limacharlie ai session terminate --id +``` + +## `limacharlie ai session attach` + +Open a WebSocket to a running session and stream its messages live. With `--interactive` the terminal becomes a chat: stdin lines are sent to the agent as prompts and approval requests are surfaced as y/n prompts. + +```bash +# Tail a running session (pretty output). +limacharlie ai session attach --id + +# Interactive chat with the agent. +limacharlie ai session attach --id --interactive + +# Read-only view of an org session you did not start. +limacharlie ai session attach --id --read-only + +# Raw JSON frames, one per line — pipe-friendly. +limacharlie ai session attach --id --raw | jq . +``` + +### Flags + +| Flag | Description | +|---|---| +| `--id` | **Required.** Session ID to attach to. | +| `--interactive`, `-i` | Send stdin lines as prompts; surface approval/question messages interactively. | +| `--read-only` | Use the org-scoped read-only WebSocket (`/v1/org/sessions/{id}/ws`). Requires `ai_agent.get` on the session's owning org. Send operations are blocked client-side. | +| `--no-history` | Don't render the history block on connect; just show new messages. | +| `--raw` | Print each WebSocket frame as a single JSON line instead of colour-coded formatting. | + +### Endpoint selection and fallback + +Two WebSocket endpoints exist on the AI Sessions service: + +- `/v1/sessions/{id}/ws` — owner-interactive. The authenticated user must own the session; write messages (prompts, approvals, interrupts) are accepted. +- `/v1/org/sessions/{id}/ws` — org-scoped, read-only. Requires `ai_agent.get` on the session's owning org. No write messages accepted. + +By default the CLI connects to the owner endpoint. If the server returns 403 (the session belongs to another user), the CLI transparently falls back to the org-scoped read-only endpoint and prints a notice. Pass `--read-only` to connect directly to the org endpoint and skip the 403 round trip. + +### Interactive controls + +When `--interactive` is set: + +- **Typed line + Enter** → sent as a `prompt` message. +- `/interrupt` → sends a WebSocket `interrupt` message, cancelling the agent's current turn. +- `/quit` → closes the WebSocket and exits. +- **Ctrl+C** → clean disconnect. +- **Tool approval requests** → interactive `Approve? [y/n/session]` prompt. Choosing `session` auto-approves matching invocations for the rest of the session. +- **`ask_user_question` messages** → if the question has options, you get a numbered menu; otherwise a free-text prompt. + +### Output format + +Notices (connection status, read-only fallback, errors) go to **stderr**; session messages go to **stdout**. When stdout is a TTY, messages are colour-coded by type: + +| Type | Colour | Form | +|---|---|---| +| `user` | green bold | `user:` + indented text | +| `assistant` | cyan bold | `assistant:` + indented text | +| `tool_use` | yellow | `tool_use NAME (id): {input}` | +| `tool_result` | dim yellow | `tool_result (id):` + content (truncated at 4 KB) | +| `system` | dim | `system[subtype]: ...` | +| `result` | blue | `result: ` | +| `error` | red bold (stderr) | `error [code]: message` | +| `session_end` | red bold | `session ended: ` — stream then exits | +| `tool_approval_request` (non-interactive) | yellow bold | `approval requested for NAME: {input}` | +| `ask_user_question` (non-interactive) | magenta bold | `question: ` | + +With `--raw` each frame is a single JSON object per line, making it easy to post-process: + +```bash +limacharlie ai session attach --id $SID --raw \ + | jq -c 'select(.type=="tool_use") | .payload' +``` + +## `limacharlie ai start-session` + +Start a new AI session by reusing an `ai_agent` Hive record as a **template** and overriding individual fields for this run. + +The Hive record named by `--definition` supplies the default session configuration: prompt, model, credentials (as `hive://secret/` references), tool permissions, MCP servers, environment, budgets, and so on. Any `--option` flag listed below replaces the matching field from the template; everything else is used as-is. + +This lets you reuse one `ai_agent` definition as a starting point and vary only the parts you need per-run — swap the prompt, cap the budget, change the model, add an environment variable, restrict tools — without maintaining a copy of the definition per variant. + +### Override semantics + +- **Scalars and lists** — replace the template value when the flag is passed. Omitted flags leave the template intact. +- **Environment** — merges the template's `environment` with `--env KEY=VALUE` flags. On key collision the CLI value wins. +- **MCP servers** — always come from the template (not overridable from the CLI). +- **`hive://secret/` references** — valid in any override value, not just in the template. They are resolved before the request is sent, so secrets never appear in `argv`. + +### Examples + +Start a session from a definition with no overrides: + +```bash +limacharlie ai start-session --definition my-security-analyst +``` + +Reuse the template but swap the prompt and tag the session for auditing: + +```bash +limacharlie ai start-session --definition my-agent \ + --prompt "Investigate this specific alert" \ + --name "Alert investigation" +``` + +Cap budget and pick a specific model on top of the template: + +```bash +limacharlie ai start-session --definition my-agent \ + --model claude-sonnet-4-6 \ + --max-budget-usd 2.50 +``` + +Add an env var (merged with the template's environment): + +```bash +limacharlie ai start-session --definition my-agent \ + --env SLACK_WEBHOOK=hive://secret/slack-webhook +``` + +Restrict tools and force `one_shot` off for this run only: + +```bash +limacharlie ai start-session --definition my-agent \ + --allowed-tools Read,Grep --denied-tools Bash,Write --no-one-shot +``` + +Pipe the result into `jq` to grab the new session ID and attach to it: + +```bash +SID=$(limacharlie ai start-session --definition my-agent \ + --output json | jq -r '.session_id') +limacharlie ai session attach --id "$SID" --interactive +``` + +### Flags + +**Session metadata** + +| Flag | Description | +|---|---| +| `--definition` | **Required.** Name of the `ai_agent` Hive record to use as template. | +| `--prompt` | Replace the prompt from the definition. | +| `--name` | Replace the session name. | +| `--idempotent-key` | Deduplication key — if an active session for this key exists, it is returned instead of creating a new one. | +| `--data` | JSON dictionary appended to the prompt as YAML event data (for standalone runs that have no D&R event). | + +**Profile fields** — scalars and lists replace the template value when provided: + +| Flag | Maps to `ProfileContent` field | +|---|---| +| `--model` | `model` | +| `--max-turns` | `max_turns` | +| `--max-budget-usd` | `max_budget_usd` | +| `--task-budget-tokens` | `task_budget_tokens` | +| `--ttl-seconds` | `ttl_seconds` | +| `--one-shot` / `--no-one-shot` | `one_shot` | +| `--permission-mode` | `permission_mode` (`acceptEdits`, `plan`, `bypassPermissions`) | +| `--allowed-tools` | `allowed_tools` (comma-separated) | +| `--denied-tools` | `denied_tools` (comma-separated) | +| `--plugin` (repeatable) | `plugins` | + +**Environment** — merged with the template's environment (override wins on key collisions): + +| Flag | Description | +|---|---| +| `--env KEY=VALUE` (repeatable) | Environment variable for the session. `VALUE` may be a literal or `hive://secret/`. | + +**Credentials** — replace the corresponding `*_secret` field on the template: + +| Flag | Description | +|---|---| +| `--anthropic-key` | Literal Anthropic API key or `hive://secret/`. | +| `--lc-api-key` | Literal LimaCharlie API key or `hive://secret/`. | +| `--lc-uid` | Literal User ID or `hive://secret/`. | + +### Output + +The command prints the server's session-creation response. With `--output json`: + +```json +{ + "session_id": "abc-123", + "status": "starting", + "created_at": "2026-04-17T18:05:02Z" +} +``` + +Use the returned `session_id` with `ai session attach`, `ai session get`, or `ai session terminate`. + +## Related pages + +- [User Sessions](user-sessions.md) — concepts, session states, profiles, the web UI. +- [D&R-Driven Sessions](dr-sessions.md) — triggering the same `ai_agent` records automatically from Detection & Response rules. +- [API Reference](api-reference.md) — the REST and WebSocket endpoints the CLI wraps. diff --git a/docs/9-ai-sessions/dr-sessions.md b/docs/9-ai-sessions/dr-sessions.md index 8587e1a7c..ca5dd573e 100644 --- a/docs/9-ai-sessions/dr-sessions.md +++ b/docs/9-ai-sessions/dr-sessions.md @@ -466,6 +466,9 @@ respond: This approach keeps D&R rules clean and lets you update the agent's behavior (prompt, model, tools, etc.) in one place without modifying every rule that uses it. The `debounce_key` can be overridden at the action level even in definition mode. +!!! tip "Reuse the same definition from the CLI" + The same `ai_agent` Hive record can be used as a template from the CLI with `limacharlie ai start-session --definition `. Individual fields (prompt, model, budget, tool list, environment, credentials) can be overridden per run, so one definition doubles as both a D&R-driven agent and an ad-hoc CLI template. See [Command Line Interface](cli.md#limacharlie-ai-start-session) for the full list of override flags. + #### AI Agent Record Fields | Field | Type | Required | Description | diff --git a/docs/9-ai-sessions/user-sessions.md b/docs/9-ai-sessions/user-sessions.md index ed3352937..a8eacac7f 100644 --- a/docs/9-ai-sessions/user-sessions.md +++ b/docs/9-ai-sessions/user-sessions.md @@ -104,6 +104,9 @@ ws.send(JSON.stringify({ })); ``` +!!! tip "Attach from the terminal" + The LimaCharlie CLI can also attach to a running session, stream its messages, and send prompts interactively. See [Command Line Interface](cli.md#limacharlie-ai-session-attach) for `limacharlie ai session attach --id --interactive`. + ## Session Profiles Profiles let you save and reuse session configurations. You can have up to 10 profiles, with one designated as the default. diff --git a/mkdocs.yml b/mkdocs.yml index 004ee27a8..f612d0d30 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -516,6 +516,7 @@ nav: - Overview: 9-ai-sessions/index.md - D&R-Driven Sessions: 9-ai-sessions/dr-sessions.md - User Sessions: 9-ai-sessions/user-sessions.md + - Command Line Interface: 9-ai-sessions/cli.md - Alternative Providers: 9-ai-sessions/alternative-providers.md - API Reference: 9-ai-sessions/api-reference.md - TypeScript SDK: 9-ai-sessions/sdk.md From 7447648ef0e4e2fa4a38a69b192ff7fa36fbdce1 Mon Sep 17 00:00:00 2001 From: Maxime Date: Sat, 18 Apr 2026 17:32:01 -0700 Subject: [PATCH 2/3] docs(ai-sessions): document `ai chat`, `ai chats`, `ai auth claude`; fix WS paths Three sets of changes to docs/9-ai-sessions/cli.md and the surrounding pages, matching the additions in refractionPOINT/python-limacharlie#278: * New "Two session ownership models" section near the top of cli.md spelling out the org-vs-user split, since the CLI now has parallel command groups for each (`ai start-session` + `ai session` for org-owned; `ai chat` + `ai chats` for user-owned). * New `ai auth claude {status,login,set-key,logout}`, `ai chat`, and `ai chats {list,get,history,terminate}` sections covering the user-owned interactive chat path. Clarifies that `ai chat` requires a per-user Claude credential (set via `auth claude`) and that `ai chats` is the lifecycle counterpart to `ai session` for user-owned sessions, with sessions of one ownership model being invisible to the other group's commands. * WebSocket URL paths corrected from the legacy `/v1/sessions/{id}/ws` and `/v1/org/sessions/{id}/ws` forms (which are unreachable through the GCP load balancer and return 404) to the new `/v1/ws/sessions/{id}` and `/v1/ws/org/sessions/{id}` forms the LB actually routes to the interaction-proxy. Plus knock-on edits: - "Endpoint selection and fallback" gains a tip box explaining that `--interactive` only sends prompts for user-owned sessions; org sessions transparently fall back to read-only by design. - The start-and-attach example under `ai start-session` no longer passes `--interactive`, since that flag is moot for the org-owned session it just created. - user-sessions.md tip retargeted from `ai session attach --interactive` to `ai chat` (the natural CLI entry point now). - sdk-overview.md AI Sessions section restructured to show both ownership paths side by side with the credential setup step. Cross-links: * python-limacharlie: https://github.com/refractionPOINT/python-limacharlie/pull/278 Co-Authored-By: Claude Opus 4.7 (1M context) --- docs/6-developer-guide/sdk-overview.md | 26 ++--- docs/9-ai-sessions/cli.md | 131 +++++++++++++++++++++++-- docs/9-ai-sessions/user-sessions.md | 4 +- 3 files changed, 141 insertions(+), 20 deletions(-) diff --git a/docs/6-developer-guide/sdk-overview.md b/docs/6-developer-guide/sdk-overview.md index 41ff299f0..8bc365fc9 100644 --- a/docs/6-developer-guide/sdk-overview.md +++ b/docs/6-developer-guide/sdk-overview.md @@ -208,24 +208,26 @@ limacharlie user add --file users_to_add.txt ### AI Sessions -Create, inspect, and attach to [AI Sessions](../9-ai-sessions/index.md) directly from the terminal. The `ai_agent` Hive record named by `--definition` is treated as a reusable template; any matching `--option` replaces the corresponding field for that run (scalars and lists replace; `--env` merges). +Create, inspect, and attach to [AI Sessions](../9-ai-sessions/index.md) directly from the terminal. The CLI exposes both ownership models the backend supports — **org-owned** sessions (started from an `ai_agent` Hive template, billed against the org's stored Anthropic key) and **user-owned** sessions (started fresh, billed against your personal Claude credential). ```bash -# Start a session from an ai_agent template, overriding budget and model. +# --- Org-owned: run an ai_agent Hive record as a template, with overrides. +# (--option flags replace template scalars/lists; --env merges.) limacharlie ai start-session --definition my-agent \ --model claude-sonnet-4-6 --max-budget-usd 2.50 -# List running sessions. -limacharlie ai session list --status running - -# Attach to a running session and stream messages live. -limacharlie ai session attach --id +limacharlie ai session list --status running # list org sessions +limacharlie ai session attach --id # tail the live stream +limacharlie ai session terminate --id -# Attach with interactive chat. -limacharlie ai session attach --id --interactive +# --- User-owned: chat from the terminal under your own Claude credential. +limacharlie ai auth claude login # one-time: store credential +limacharlie ai chat "what sensors pinged in the last hour?" -# Terminate a session. -limacharlie ai session terminate --id +limacharlie ai chats list --status running # list your chat sessions +limacharlie ai chats terminate --id ``` -See [AI Sessions — Command Line Interface](../9-ai-sessions/cli.md) for the full command reference, override semantics, and stream output formatting. +The `ai session attach --interactive` command works for either kind of session: it sends prompts when you own the session (user-owned), and falls back to read-only with a notice when the session is org-owned (the backend exposes only a read-only WebSocket for those by design). + +See [AI Sessions — Command Line Interface](../9-ai-sessions/cli.md) for the full command reference, override semantics, the org-vs-user split, and stream output formatting. diff --git a/docs/9-ai-sessions/cli.md b/docs/9-ai-sessions/cli.md index d16e28f99..8d91ed1dd 100644 --- a/docs/9-ai-sessions/cli.md +++ b/docs/9-ai-sessions/cli.md @@ -15,6 +15,20 @@ pip install limacharlie Then authenticate as described in the [CLI overview](../6-developer-guide/sdk-overview.md#authentication). +## Two session ownership models + +The AI Sessions backend exposes two distinct kinds of session, each with its own creation command, lifecycle group, and WebSocket auth model. They are independent: a session created in one model is not visible from the other model's commands. + +| | **Org-owned session** | **User-owned session** | +|---|---|---| +| Started by | `ai start-session --definition ` (or a DR rule) | `ai chat [PROMPT]` | +| Owner | The organization (`OwnerOID`) | The authenticated user (`OwnerUID`) | +| Anthropic credential | `anthropic_secret` from the `ai_agent` Hive record | The user's stored credential, set up via [`ai auth claude`](#limacharlie-ai-auth-claude) | +| Lifecycle commands | [`ai session list/get/history/terminate`](#limacharlie-ai-session-list) | [`ai chats list/get/history/terminate`](#limacharlie-ai-chats) | +| `ai session attach` mode | Read-only by design — the org WS endpoint is the only one available, so `--interactive` auto-falls back to read-only | Owner-interactive — `--interactive` actually sends prompts | + +Use **org sessions** for automation: scheduled runs, DR-rule triggers, ad-hoc invocations of an `ai_agent` Hive record. Use **user sessions** for an interactive Claude chat in your terminal that bills against your own Claude credential. + ## `limacharlie ai session list` List AI sessions for the current organization. @@ -87,7 +101,7 @@ limacharlie ai session attach --id --raw | jq . |---|---| | `--id` | **Required.** Session ID to attach to. | | `--interactive`, `-i` | Send stdin lines as prompts; surface approval/question messages interactively. | -| `--read-only` | Use the org-scoped read-only WebSocket (`/v1/org/sessions/{id}/ws`). Requires `ai_agent.get` on the session's owning org. Send operations are blocked client-side. | +| `--read-only` | Use the org-scoped read-only WebSocket (`/v1/ws/org/sessions/{id}`). Requires `ai_agent.get` on the session's owning org. Send operations are blocked client-side. | | `--no-history` | Don't render the history block on connect; just show new messages. | | `--raw` | Print each WebSocket frame as a single JSON line instead of colour-coded formatting. | @@ -95,10 +109,13 @@ limacharlie ai session attach --id --raw | jq . Two WebSocket endpoints exist on the AI Sessions service: -- `/v1/sessions/{id}/ws` — owner-interactive. The authenticated user must own the session; write messages (prompts, approvals, interrupts) are accepted. -- `/v1/org/sessions/{id}/ws` — org-scoped, read-only. Requires `ai_agent.get` on the session's owning org. No write messages accepted. +- `/v1/ws/sessions/{id}` — owner-interactive. The authenticated user must own the session; write messages (prompts, approvals, interrupts) are accepted. +- `/v1/ws/org/sessions/{id}` — org-scoped, read-only. Requires `ai_agent.get` on the session's owning org. No write messages accepted. + +By default the CLI connects to the owner endpoint. If the server returns 403 (the session is owned by your organization rather than by you personally — for example any session created via `ai start-session`), the CLI transparently falls back to the org-scoped read-only endpoint and prints a notice. Pass `--read-only` to connect directly to the org endpoint and skip the 403 round trip. -By default the CLI connects to the owner endpoint. If the server returns 403 (the session belongs to another user), the CLI transparently falls back to the org-scoped read-only endpoint and prints a notice. Pass `--read-only` to connect directly to the org endpoint and skip the 403 round trip. +!!! tip "When `--interactive` actually accepts your input" + `ai session attach --interactive` only sends prompts when the owner endpoint accepts you. That happens for **user-owned** sessions (created via [`ai chat`](#limacharlie-ai-chat) or the web UI under your identity). For **org-owned** sessions (created via `ai start-session` and any DR-rule-triggered run), the org endpoint is the only path the backend exposes, and it is read-only by design — the CLI auto-falls back and prints a notice. Use [`ai chat`](#limacharlie-ai-chat) when you want a real terminal chat. ### Interactive controls @@ -188,12 +205,12 @@ limacharlie ai start-session --definition my-agent \ --allowed-tools Read,Grep --denied-tools Bash,Write --no-one-shot ``` -Pipe the result into `jq` to grab the new session ID and attach to it: +Pipe the result into `jq` to grab the new session ID and attach to it (read-only — these are org-owned sessions; for an interactive terminal chat use [`ai chat`](#limacharlie-ai-chat) instead): ```bash SID=$(limacharlie ai start-session --definition my-agent \ --output json | jq -r '.session_id') -limacharlie ai session attach --id "$SID" --interactive +limacharlie ai session attach --id "$SID" ``` ### Flags @@ -251,6 +268,108 @@ The command prints the server's session-creation response. With `--output json`: Use the returned `session_id` with `ai session attach`, `ai session get`, or `ai session terminate`. +## `limacharlie ai auth claude` + +Manage the per-user Anthropic credential that backs [`ai chat`](#limacharlie-ai-chat). Org-owned sessions started via `ai start-session` ignore these and use the `anthropic_secret` field from the `ai_agent` Hive record instead — there is no need to run `auth claude` for those. + +The credential is stored server-side and bound to the authenticated UID. It can be either a Claude Max OAuth token (browser flow) or a raw Anthropic API key. + +```bash +limacharlie ai auth claude status +limacharlie ai auth claude login +limacharlie ai auth claude set-key --key "$ANTHROPIC_API_KEY" +limacharlie ai auth claude set-key --key hive://secret/anthropic-key +echo "$ANTHROPIC_API_KEY" | limacharlie ai auth claude set-key --key-from-stdin +limacharlie ai auth claude logout +``` + +### Subcommands + +| Command | Description | +|---|---| +| `status` | Returns `has_credentials`, `credential_type` (`oauth_token` or `apikey`), and `created_at`. | +| `login` | Runs the browser OAuth flow: starts a server-side OAuth session, polls until Claude returns the URL, prints it to the terminal, and prompts for the authorization code. | +| `set-key` | Stores a raw Anthropic API key. Accepts `--key ` (literal or `hive://secret/`) or `--key-from-stdin` for piping. The two are mutually exclusive. | +| `logout` | Deletes the stored credential. | + +Errors: + +- *"No Claude credentials registered for this user"* — `ai chat` raises this when `status.has_credentials` is `false`. Run `auth claude login` or `auth claude set-key` and retry. +- The browser OAuth flow has a 5-minute server-side TTL; if you take longer than that to paste the code back, restart with `auth claude login`. + +## `limacharlie ai chat` + +Start a fresh **user-owned** AI session and drop into an interactive WebSocket chat. The session is owned by the authenticated user, billed against the credential stored via [`ai auth claude`](#limacharlie-ai-auth-claude), and attaches over the owner endpoint so prompts can flow both directions. + +The opening prompt comes from the optional `PROMPT` argument; further turns come from interactive stdin once the session is attached. Stdin is **not** consumed as the opening prompt — supply that via the argument so multi-line piping is not silently glued into one message. + +```bash +# Start a chat with an opening prompt. +limacharlie ai chat "What sensors pinged in the last hour?" + +# Start a chat with overrides — caps and a specific model. +limacharlie ai chat --model claude-sonnet-4-6 --max-budget-usd 0.50 + +# Start a chat with no opening prompt; first message comes from stdin in the +# interactive loop that runs after attach. +limacharlie ai chat +``` + +`ai chat` runs three steps before handing the terminal to the chat loop: + +1. Calls [`ai auth claude status`](#limacharlie-ai-auth-claude) and exits non-zero with instructions if no credential is stored. +2. Calls `POST /v1/register` (idempotent — safe to run on every invocation). +3. Calls `POST /v1/sessions` with the override flags below, then attaches via [`ai session attach`](#limacharlie-ai-session-attach) in interactive mode. + +### Flags + +| Flag | Description | +|---|---| +| *(positional)* `PROMPT` | Optional opening prompt sent as the first message after attach. | +| `--name` | Session name (display only). | +| `--model` | Anthropic model (e.g. `claude-sonnet-4-6`). | +| `--max-turns` | Maximum agent turns before auto-stop. | +| `--max-budget-usd` | Hard USD cost cap for the session. | +| `--task-budget-tokens` | Per-task token budget. | +| `--permission-mode` | `acceptEdits`, `plan`, or `bypassPermissions`. | +| `--allowed-tools` | Comma-separated list of allowed tool names. | +| `--denied-tools` | Comma-separated list of denied tool names. | +| `--plugin` (repeatable) | Plugin names to enable. | +| `--idempotent-key` | Deduplication key for session creation. | + +The flag set is intentionally narrower than [`ai start-session`](#limacharlie-ai-start-session): there is no `--definition` (chat sessions are blank, not template-derived), no environment merge, and no credential-override flags (`--anthropic-key` / `--lc-api-key` / `--lc-uid`) since the session uses the per-user credential set via `auth claude` and runs without an attached LC service identity. + +### Interactive controls + +Identical to [`ai session attach --interactive`](#interactive-controls): stdin lines become prompts, `/interrupt` cancels the agent's current turn, `/quit` detaches, Ctrl+C disconnects. Tool approval requests and `ask_user_question` messages are surfaced as in-line prompts. + +### Re-attaching to an in-progress chat + +`ai chat` always creates a new session. To reconnect to one you already started, use [`ai session attach --interactive --id `](#limacharlie-ai-session-attach) — it works against user-owned sessions just like the in-process attach loop, since you own them and the owner endpoint accepts you. + +## `limacharlie ai chats` + +Lifecycle management for user-owned sessions — the counterpart to the [`ai session`](#limacharlie-ai-session-list) group. Same subcommand shape (`list`, `get`, `history`, `terminate`), routed to the user-scoped REST endpoints (`/v1/sessions/*`) instead of the org-scoped ones (`/v1/org/sessions/*`). + +```bash +limacharlie ai chats list +limacharlie ai chats list --status running +limacharlie ai chats get --id +limacharlie ai chats get --id --full-prompt +limacharlie ai chats history --id +limacharlie ai chats history --id --raw +limacharlie ai chats terminate --id +``` + +| Subcommand | Org equivalent | Notes | +|---|---|---| +| `chats list` | `session list` | Lists sessions where you are the owning UID. Same `--status`, `--limit`, `--cursor` flags. | +| `chats get` | `session get` | Same `--full-prompt` toggle. | +| `chats history` | `session history` | Same internal-system-message filter; same `--raw` to disable it. | +| `chats terminate` | `session terminate` | Calls `DELETE /v1/sessions/{id}` (user-scoped). | + +Sessions you create with `ai chat` will appear in `chats list`. Sessions you create with `ai start-session` (or that DR rules trigger) will appear in `session list`. The two sets do not overlap; a `chats get --id ` returns "not found" rather than the org session, and vice versa. + ## Related pages - [User Sessions](user-sessions.md) — concepts, session states, profiles, the web UI. diff --git a/docs/9-ai-sessions/user-sessions.md b/docs/9-ai-sessions/user-sessions.md index a8eacac7f..56ecf62c3 100644 --- a/docs/9-ai-sessions/user-sessions.md +++ b/docs/9-ai-sessions/user-sessions.md @@ -104,8 +104,8 @@ ws.send(JSON.stringify({ })); ``` -!!! tip "Attach from the terminal" - The LimaCharlie CLI can also attach to a running session, stream its messages, and send prompts interactively. See [Command Line Interface](cli.md#limacharlie-ai-session-attach) for `limacharlie ai session attach --id --interactive`. +!!! tip "Chat from the terminal" + The LimaCharlie CLI's `limacharlie ai chat` command starts a new user session and drops you straight into the interactive chat — no manual `POST /v1/sessions` + WebSocket bring-up. Pre-requisite is running `limacharlie ai auth claude login` (or `set-key`) once to register your Anthropic credential. See [Command Line Interface](cli.md#limacharlie-ai-chat) for the full flag set, and `ai session attach --id --interactive` for re-attaching to a session you started earlier. ## Session Profiles From 6632dbf6a6812873d3bba39348315162f05d33d0 Mon Sep 17 00:00:00 2001 From: Maxime Date: Sat, 18 Apr 2026 20:12:25 -0700 Subject: [PATCH 3/3] docs(ai-sessions): document `--verbose` and default noise filter for `ai session attach` / `ai chat` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Matches refractionPOINT/python-limacharlie@4f1e200, which cleaned up the pretty-printed live stream so `ai chat` is actually readable: - Plumbing `system` subtypes (credential_diagnostics, model_set, hook_started, autoinit_loaded, ttl_added_to_system_prompt, ...), `session_status` startup pings and `usage_delta` frames are hidden by default. - Empty assistant-tool-use-only frames, user tool_result wrappers and summary-less `result` pings are skipped. - Timestamps are abbreviated to `HH:MM:SS`. - A new `--verbose`/`-v` flag on both `ai session attach` and `ai chat` restores the firehose (useful when debugging session startup or correlating with server logs). Changes in docs/9-ai-sessions/cli.md: - Flag tables for `ai session attach` and `ai chat` gain a `--verbose`/`-v` row that cross-links the new "Default noise filter" subsection. - New "Default noise filter" subsection under "Output format" enumerates the filtered types / subtypes / empty-frame rules and calls out that the same set is used by `ai session history` / `ai chats history`. - The existing one-liner under `ai session history` now cross-links the shared filter section so readers see both surfaces share it. - Output-format section notes that timestamps default to `HH:MM:SS` and `--verbose` preserves the full ISO-8601 value. No behavioural change elsewhere — `--raw` semantics, endpoint selection, interactive controls and the colour-coded table are unchanged. Cross-links: * python-limacharlie: https://github.com/refractionPOINT/python-limacharlie/commit/4f1e200 Co-Authored-By: Claude Opus 4.7 (1M context) --- docs/9-ai-sessions/cli.md | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/docs/9-ai-sessions/cli.md b/docs/9-ai-sessions/cli.md index 8d91ed1dd..9f7eec4d5 100644 --- a/docs/9-ai-sessions/cli.md +++ b/docs/9-ai-sessions/cli.md @@ -67,7 +67,7 @@ limacharlie ai session history --id limacharlie ai session history --id --raw ``` -Internal system bootstrap messages (credential diagnostics, `claude_md_loaded`, MCP config debug, etc.) are filtered out by default. Pass `--raw` to include them. +Internal system bootstrap messages (credential diagnostics, `claude_md_loaded`, MCP config debug, etc.) are filtered out by default — same set hidden from the live stream by [`ai session attach`](#default-noise-filter). Pass `--raw` to include them. ## `limacharlie ai session terminate` @@ -104,6 +104,7 @@ limacharlie ai session attach --id --raw | jq . | `--read-only` | Use the org-scoped read-only WebSocket (`/v1/ws/org/sessions/{id}`). Requires `ai_agent.get` on the session's owning org. Send operations are blocked client-side. | | `--no-history` | Don't render the history block on connect; just show new messages. | | `--raw` | Print each WebSocket frame as a single JSON line instead of colour-coded formatting. | +| `--verbose`, `-v` | Show the full firehose: plumbing `system[subtype]` messages (`init_received`, `model_set`, `hook_started`, …), `session_status` pings, `usage_delta` frames, and full ISO timestamps instead of the default `HH:MM:SS`. See [Default noise filter](#default-noise-filter). | ### Endpoint selection and fallback @@ -145,6 +146,8 @@ Notices (connection status, read-only fallback, errors) go to **stderr**; sessio | `tool_approval_request` (non-interactive) | yellow bold | `approval requested for NAME: {input}` | | `ask_user_question` (non-interactive) | magenta bold | `question: ` | +Timestamps are abbreviated to `HH:MM:SS` by default; pass `--verbose` to preserve the full ISO-8601 value the server sent. + With `--raw` each frame is a single JSON object per line, making it easy to post-process: ```bash @@ -152,6 +155,16 @@ limacharlie ai session attach --id $SID --raw \ | jq -c 'select(.type=="tool_use") | .payload' ``` +### Default noise filter + +The AI Sessions runner emits a number of housekeeping frames at the start of every session and between tool calls. Without filtering they overwhelm the live stream — the interesting assistant turns get buried between dozens of `system[credential_diagnostics]:` / `system[model_set]:` / `session_status: {...}` / empty `assistant:` headers. The pretty renderer therefore hides the following frames by default: + +- **Plumbing message types** — `session_status` (startup/status pings), `usage_delta` (per-API-call token tallies), `sdk_session_id`. +- **Plumbing `system` subtypes** — every bootstrap event emitted by the bridge (`credential_diagnostics`, `init_received`, `claude_md_loaded`, `mcp_config_debug`, `mcp_servers_set`, `model_set`, `max_turns_set`, `max_budget_set`, `task_budget_set`, `one_shot_mode_set`, `permission_mode_set`, `tools_configured`, `system_prompt_set`, `oid_added_to_system_prompt`, `ttl_added_to_system_prompt`, `plugins_resolved`, `autoinit_loaded`, `autoinit_error`, `resuming_sdk_session`, `user_mcp_servers_loaded`, `mcp_servers_loaded`, `session_patterns_loaded`, `unknown_plugin`, `claude_md_error`, …) plus Claude SDK hook events (`hook_started`, `hook_response`, `hook_matched`). +- **Empty frames** — `assistant` turns that carry only a `tool_use` block (the accompanying `tool_use` message already renders the call), `user` frames that wrap a `tool_result` (same — the `tool_result` message already renders the output), and `result` pings with no human-readable summary. + +This filter applies to both the initial history block and the live stream. Pass `--verbose` / `-v` to disable it and see every frame; `--raw` bypasses the renderer entirely and prints untouched JSON. The same noise set is used by [`ai session history`](#limacharlie-ai-session-history) and [`ai chats history`](#limacharlie-ai-chats); `--raw` on those commands includes the filtered frames. + ## `limacharlie ai start-session` Start a new AI session by reusing an `ai_agent` Hive record as a **template** and overriding individual fields for this run. @@ -336,6 +349,7 @@ limacharlie ai chat | `--denied-tools` | Comma-separated list of denied tool names. | | `--plugin` (repeatable) | Plugin names to enable. | | `--idempotent-key` | Deduplication key for session creation. | +| `--verbose`, `-v` | Disable the [default noise filter](#default-noise-filter) and use full ISO timestamps — same flag as on `ai session attach`. | The flag set is intentionally narrower than [`ai start-session`](#limacharlie-ai-start-session): there is no `--definition` (chat sessions are blank, not template-derived), no environment merge, and no credential-override flags (`--anthropic-key` / `--lc-api-key` / `--lc-uid`) since the session uses the per-user credential set via `auth claude` and runs without an attached LC service identity.