AgentOS markAgentOS

CLI Reference


The agentos CLI is the fastest way to configure, run, inspect, and automate AgentOS.

Run:

agentos --help
agentos <command> --help

Main Commands

CommandPurpose
agentos initInitialize a workspace.
agentos upgradeUpgrade AgentOS and restart the managed gateway to match.
agentos doctorDiagnose readiness and print recovery steps.
agentos onboardRun or inspect first-run setup.
agentos authProvider logins that are not API keys (login/status/logout; xAI today).
agentos configureReconfigure provider, router, channels, search, x-search, image generation, or memory embedding.
agentos gatewayRun and manage the gateway server.
agentos chatStart interactive terminal chat.
agentos agentRun a single automation-friendly agent turn.
agentos sessionsList, inspect, rename, resume, abort, delete, or export sessions.
agentos projectsGroup sessions into projects with shared knowledge injected into every member session.
agentos skillsList, search, view, install, update, publish, and inspect skills.
agentos memoryInspect and maintain memory.
agentos channelsConfigure and inspect messaging channels.
agentos providersConfigure and inspect LLM providers.
agentos searchConfigure and use web search.
agentos sandboxInspect or change default sandbox posture.
agentos cronManage scheduled AgentOS runs.
agentos costInspect usage and estimated cost.
agentos contextShow the fixed per-request context cost and what each tool profile would cost.
agentos diagnosticsEnable or disable runtime diagnostics logging.
agentos replayReplay a recorded turn from the decision log.
agentos migrateImport state from external agent runtimes.
agentos modelsInspect available models.
agentos agentsManage durable agents.
agentos mcp-serverRun the AgentOS MCP server bridge.
agentos distEmit a reproducible workspace-state inventory.
agentos resetReset a session, rotating it to a fresh transcript.

Run Surfaces

Web UI and gateway:

agentos gateway run
agentos gateway start --json
agentos gateway status
agentos gateway restart
agentos gateway stop

agentos gateway status (and --json) reports both the installed CLI version (cliVersion) and the running gateway's version (gatewayVersion); when they differ it sets versionMismatch and prints a diagnostic advising a restart — the normal state right after a package upgrade with --no-restart, or after a manual upgrade.

Terminal chat:

agentos chat
agentos chat --model gpt-5.4-mini
agentos chat --session <session-key>
agentos chat --standalone --workspace /path/to/project

Chat REPL slash commands

agentos chat exposes a prompt-toolkit REPL with a slash-command palette. The most useful ones:

CommandPurpose
/new [title]Start a new chat session. The optional title is persisted as the session's display name and shown in the bottom toolbar and /status.
/resume <key>Resume an existing session by key (or a prefix / display-name match in gateway mode).
/statusShow the current session, model, permissions, and the active Pilot Router tier (or auto).
/model <id>Override the model for this session.
/clear / /resetClear the current conversation context. The screen is wiped too (including scrollback), so the cleared turns are gone from view as well as from context.
/compactCompact older context into a summary.
/costShow per-session token and cost totals.
/save [path]Save the transcript to a Markdown file.
/c0/c3Pin the Pilot Router to a configured tier for this session. The pin appears in the bottom toolbar (e.g. tier:c3) and stays active until you exit or run /auto.
/use <model-id>Pin the route to a specific model, outside the configured tiers. The model must belong to the active provider.
/autoRestore automatic Pilot Router routing (clears the tier pin).
/plan [off]Toggle plan mode: the session becomes research-only (read, search, and analysis tools) until you approve the plan the agent presents via exit_plan_mode. /plan off leaves plan mode — from text surfaces it is also how you approve a presented plan before telling the agent to proceed. Gateway mode only.
/helpList the commands available on the current surface.
/exit / /quitLeave the REPL.

Router tier commands (/c0/c3, /auto) are available in both gateway and --standalone modes. Tiers not present in your [agentos_router] config are rejected with a readable error. In --standalone mode the router must be enabled in config; otherwise the command reports "Pilot Router is disabled or unavailable."

A tier pin you set is sticky: it holds every turn until you clear it with /auto (or the process ends). It does not time out. Pin /c3 and forget, and every later turn keeps paying for c3 — check /status if you are unsure what is in force. This differs from the routing the model may pick for itself mid-turn, which still lapses on its own after ten idle minutes.

/use pins a model that is not one of your four configured tiers. It is a separate verb from /model, whose argument filters the model listing — /model gpt shows you the gpt models, /use gpt-5.6-terra switches to one. Because every turn runs through the single configured llm.provider (a tier's provider field is metadata, not a client selector), only that provider's models can be pinned; anything else is refused at the point of choosing rather than failing on the next turn. A directly-named model rides on the default tier, inheriting its thinking level and pricing baseline — settings a bare model id does not carry.

While a pin is in force the model's own router_control tool is withdrawn, so it cannot route around your choice. Two exceptions are worth knowing:

  • Image turns. A turn with an image attachment is routed to a vision-capable tier before pins are consulted, so it runs on that tier, not your pinned one. The Web UI flags such a turn.
  • Large context. A pinned turn skips the large-context tier floor. If the conversation outgrows the pinned model's context window, the turn fails at the provider rather than being quietly upgraded. Pin a larger tier, or run /auto.

Assistant label and session chrome

The assistant speaker label shown on the marker and the pre-token waiting row defaults to agentos. Override it with the AGENTOS_ASSISTANT_LABEL environment variable — the value is read once at startup and used by every renderer, so it stays consistent across the streamed reply marker, the waiting header, and the queued-turn marker.

AGENTOS_ASSISTANT_LABEL="Hani" agentos chat

The active input row is framed by a top and bottom rule, so the typing area reads as a distinct box between the transcript and the bottom toolbar:

────────────────────────────────────────
 ◢ you  <your message here>
────────────────────────────────────────
 title · model · [tier:cN]

Press Enter to submit the current message. Use Alt+Enter or Shift+Enter to insert a newline when your terminal reports those modified keys distinctly; Ctrl+J is the portable newline fallback. The input frame grows with the message up to 10 visible lines, then scrolls internally while remaining pinned above the bottom toolbar. Up and Down move between lines in a multiline draft before moving through chat input history at the first or last line.

The bottom toolbar renders title · model · [tier:cN] while typing. The title comes from /new <title> (or is loaded from the gateway on /resume); the tier chip appears only while a Pilot Router hold is active. /status mirrors the same fields plus the active permissions posture.

Full-screen surface (default). agentos chat renders the conversation in a scrollable in-app pane above a permanently-pinned input frame (Claude Code style), so the frame stays visible while the assistant streams. The branded welcome screen renders at the top of the pane on launch. PgUp/PgDn scroll back through history; the mouse wheel scrolls when the pointer is over the transcript. New output re-pins to the newest line.

Select and copy. Drag with the left mouse button across the transcript to highlight any span (the selection shows in reverse video); releasing the button copies the plain text — ANSI styling stripped, CJK width-aware — to the system clipboard (pbcopy on macOS, wl-copy/xclip/xsel on Linux, clip on Windows, OSC 52 escape as a fallback). Click anywhere to clear the selection. The emulator's own selection gesture (typically Shift+drag on Linux, Option+drag in iTerm2) also still works if you prefer it.

Markdown rendering. The assistant's streamed reply is styled inline as it arrives: #/##/### headings render in the brand accent, > quotes get a dimmed bar, --- becomes a rule, list markers are tinted, tables keep their pipes aligned, fenced code blocks stream in a uniform code color (no waiting for the closing fence), and inline spans — **bold**, *italic*, ~~strike~~, inline `code`, and [text](url) links — are styled in place. File names, branch names, and other important terms the model wraps in backticks stand out in the accent color. Reasoning-model <think>…</think> blocks render as a recessive gray-bar, dim-italic region (the tags themselves are hidden) so the chain-of-thought stays visible but never competes with the reply. The render is write-once (no repaint loop), and NO_COLOR (or a non-color terminal) downgrades the stream to plain text so piped output stays greppable.

Input navigation follows the current logical line in multiline drafts: Home/End and Ctrl+A/Ctrl+E move to that line's start/end. On macOS, Cmd+Left/Cmd+Right work when the terminal maps those shortcuts to Home/End; use Ctrl+A/Ctrl+E as the portable fallback.

Full-screen is the default for an interactive terminal. Non-TTY / piped invocations fall back to native scrollback automatically. To force a mode set AGENTOS_CHAT_FULLSCREEN:

AGENTOS_CHAT_FULLSCREEN=0 agentos chat   # opt out — stream to native scrollback
AGENTOS_CHAT_FULLSCREEN=1 agentos chat   # force full-screen (e.g. under a pipe)

One-shot automation:

agentos agent -m "Review the current directory"
agentos agent --json -m "Return a short machine-readable summary"
agentos agent --workspace /path/to/project --workspace-strict -m "Inspect this repo"
agentos agent --timeout 600 --max-iterations 30 -m "Run a bounded investigation"

Useful automation flags:

FlagPurpose
--workspaceSet the workspace root.
--workspace-strictRestrict read-side file tools to the workspace.
--workspace-lockdownContain writes to workspace or scratch directory.
--scratch-dirPlace temporary scripts/logs/candidate patches in a known directory.
--file / -fAttach a local file; repeat for multiple files.
--unattended / --interactiveRun without a live approval surface (unattended is default).
--stateless / --clean-roomUse clean-room prompt bootstrap.
--stateless-keep-project-rulesWith clean-room bootstrap, keep AGENTS.md project rules only.
--no-memory-captureDo not write this invocation to durable searchable memory.
--session-idTarget a specific session key/id for cross-invocation continuity.
--timeout / -TSet total agent wall-clock timeout in seconds.
--max-iterationsBound the model/tool loop.
--iteration-timeout-secondsPer-iteration timeout in seconds (one LLM call + tool executions).
--tool-timeout-secondsPer-tool execution timeout in seconds.
--request-timeout-secondsSingle LLM HTTP/streaming request timeout in seconds.
--max-provider-retriesBound transient provider retries.
--length-capped-continuationsBound automatic continuations after length-limited provider output.
--thinkingOverride reasoning level (off, minimal, low, medium, high, xhigh, adaptive).
--permissionsSelect restricted, bypass, or full permission posture.
--transcript-pathWrite a JSONL transcript for automation.
--usage-pathWrite usage JSON.
--session-db-pathPersist session replay across invocations.
--jsonEmit machine-readable JSON output.

Upgrade

agentos upgrade is the primary upgrade path. It detects how AgentOS was installed, installs the published PyPI release of use-agent-os[recommended], and — by default — restarts the managed gateway and verifies the running gateway reports the new version before declaring success (a "successful" upgrade that leaves the daemon on old code is the common upgrade regret).

It always targets the release, never a local checkout. To install a checkout, run bash scripts/install_source.sh — that script is the only path that rebuilds the React control UI (npm ci && npm run build) before installing.

agentos upgrade                 # upgrade, restart the gateway, verify
agentos upgrade --check         # is a newer release available? change nothing
agentos upgrade --dry-run       # print the exact command that would run
agentos upgrade --no-restart    # upgrade only; leave the gateway on OLD code
agentos upgrade --timeout 900   # bound the upgrade subprocess (default 600s)
FlagPurpose
--checkQuery PyPI for a newer release (5s timeout); offline prints could not check (offline). Changes nothing.
--dry-runPrint the upgrade command that would run and whether the gateway would be restarted; touch nothing.
--no-restartUpgrade the package but do not restart the gateway. Prints an unmissable warning that it still runs the old version; run agentos gateway restart yourself.
--timeoutUpgrade-subprocess timeout in seconds (default 600). On timeout the tool's process group is killed with recovery guidance — never a half-state.
--configTarget a specific config file for the gateway restart.
--jsonMachine-readable output.

Per install method:

  • uv tool — delegated automatically as uv tool install --force --python <running major.minor> "use-agent-os[recommended]", resolving uv to an absolute path over a hardened PATH. install rather than upgrade is load-bearing: uv tool upgrade takes only a bare tool name and re-resolves whatever uv's receipt recorded, so an install laid down from a checkout (install_source.sh passes .) keeps rebuilding the wheel from the working tree — re-packaging whatever src/agentos/gateway/static/dist/ is on disk, because nothing in the upgrade path runs npm run build. --force is required so an already-installed tool is genuinely rebuilt instead of no-op'ing, and it also self-heals a stale cache or an orphaned interpreter (e.g. after the base Python moves). --python pins the rebuilt venv to the interpreter already in use, so a forced reinstall never moves a 3.13 install onto another version.
  • pipx — the same shape: pipx install --force "use-agent-os[recommended]".
  • pip / editable / unknown — not faked: prints the exact manual command (e.g. python -m pip install --upgrade "use-agent-os[recommended]") and exits with a distinct code. The editable hint points at git pull && bash scripts/install_source.sh, since an editable install serves the control UI straight out of the checkout.

Extras are always [recommended] — the same profile install_source.sh installs by default. Without them the ONNX embedding models and the pilot router degrade silently at runtime.

When the current install was built from a local directory (detected via PEP 610 direct_url.json), the command prints a note naming that directory and scripts/install_source.sh before proceeding. It is informational only: it never prompts, blocks, or changes the exit code. --json reports the same as sourceDirectory (null for a release install).

Exit codes: 0 success (upgraded + verified, or --check/--dry-run); 3 this install method needs a manual command (printed); 1 the upgrade failed, timed out, or the post-restart version could not be verified.

Config migrations run at gateway start and write a timestamped backup before rewriting any file, so ~/.agentos/ config and data are safe across upgrades.

Version skew

Commands that talk to the gateway compare the CLI and gateway versions once per run:

  • Gateway older than the CLI (normal right after an upgrade, before a restart) — prints a warning on stderr, never blocks.
  • Gateway newer than the CLI (you downgraded the CLI, or drive a newer gateway from a stale environment) — refused, because a newer gateway may have written config with a newer schema. Fix by upgrading the CLI or restarting the gateway from this environment; override in an emergency with AGENTOS_ALLOW_VERSION_SKEW=1.

Update notifications

On gateway-connected commands the CLI checks PyPI at most once every 24h and, if a newer release exists, prints a one-line notice on stderr. Similarly, the Web UI queries the gateway on connection and displays a dismissible banner if an update is available. The check is suppressed on non-interactive CLI runs (no TTY) and in CI. Control it with:

  • updates.notify = false in agentos.toml (or the setup UI's Finish step) — turns the notices off entirely (both CLI and Web UI).
  • AGENTOS_NO_UPDATE_NOTICE=1 — silences it for a single run/session.

See Configuration.

Configuration Commands

Provider and router:

agentos onboard
agentos onboard status
agentos configure provider --provider openrouter --api-key-env OPENROUTER_API_KEY
agentos configure router --router recommended
agentos providers list
agentos providers configure openrouter
agentos providers status

providers status includes a circuit column with the active provider's failover circuit-breaker state (closed, half_open, or open (42s)); see Providers and Models.

Provider-specific setup examples, including OpenCAP, live in Providers and Models.

Search:

agentos search list
agentos search configure duckduckgo
agentos search query "latest AgentOS release"
agentos configure search --search-provider duckduckgo

X (Twitter) search — a separate xAI-backed tool, not a web_search backend. With a SuperGrok / X Premium+ subscription, sign in instead of using a key:

agentos auth login xai      # device-code flow; preferred over XAI_API_KEY
agentos auth status         # never prints a token
agentos auth logout xai

agentos auth login xai --no-wait --json 2>/dev/null   # start, print link + code, exit
agentos auth login xai --resume --json 2>/dev/null    # exit 0 done, 3 not yet, 1 failed
agentos onboard catalog x-search
agentos configure x-search --api-key-env XAI_API_KEY
agentos configure x-search --x-search-model grok-4.5 --x-search-reasoning-effort low
agentos configure x-search --no-x-search-enabled

The x_search tool stays hidden from the agent until an xAI credential is reachable. See X (Twitter) Search.

Channels:

Built-in channel types are discord, email, slack, and telegram; agentos channels types is the authoritative catalog. On upgrade, config entries for retired built-in channel types are removed only after AgentOS creates the normal secure config backup.

agentos channels types
agentos channels describe telegram
agentos channels native-commands telegram
agentos channels native-commands slack --request-url https://agent.example/slack/events
agentos channels add telegram --name personal
agentos channels add email --name inbox \
  --field imap_host=imap.example.com --field imap_username=agent@example.com \
  --field imap_password=<app-password> --field smtp_host=smtp.example.com \
  --field from_address=agent@example.com --field allowed_senders=you@example.com
agentos channels list
agentos channels status
agentos channels pairing list personal
agentos channels pairing approve personal ABCD2345
agentos channels pairing deny personal <telegram-user-id>
agentos channels pairing revoke personal <telegram-user-id>
agentos channels enable personal
agentos channels disable personal
agentos channels restart personal
agentos channels remove personal

native-commands prints the native platform payload derived from the same channel command registry used for text /command dispatch. Telegram and Discord menus synchronize when their adapters start. Slack also synchronizes at startup when its channel entry has app_id, a short-lived app configuration manifest_token, and command_request_url. Otherwise import the exported Slack manifest fragment manually; its --request-url must point to the gateway's Slack webhook endpoint.

Telegram direct messages always require pairing. Pairing is binary (unpaired/paired), with no admin or owner tier. Groups are disabled by default and require an explicit group chat ID, a paired sender, and—by default—a bot mention. Any connected Control client may approve, deny, or disconnect a pairing.

Platform-Native Interactive Approvals

Platform-native interactive tool approvals (such as Slack block actions, Telegram inline keyboard callbacks, and Discord message components) allow operators to approve or deny gated tool executions directly using interactive buttons in their messaging app.

For security, interactive approvals are:

  • Restricted to Direct Messages (DMs): Interactive approval prompts are only sent in channel DMs, not group/channel chats, ensuring they cannot be triggered or visible to unauthorized participants in a shared room.
  • Access Gated: Each button click/interaction verifies that the clicker's sender ID is paired and authorized under the channel's access policy. Clicking by an unpaired or unauthorized user is dropped and rejected.
  • Session Bound: Approval tokens are strictly bound to their originating chat session key. A click received from a different chat context or user session will mismatch and be ignored.

Raw config:

agentos config get llm.provider
agentos config set gateway.port 18791

For Ollama models that do not reliably support native tool calls, set tools.enabled = false in the config file to run in plain-text mode. Keep it enabled for tool-capable cloud models such as glm-5.2:cloud; the Ollama provider preserves native tool-call history between turns.

More detail:

Environment Variables

agentos config edits the TOML config. agentos env edits ~/.agentos/.env, which is where OS environment variables live — the credentials skills and external binaries read, and provider keys you would rather not keep in the config file.

agentos env list                       # every variable AgentOS knows about
agentos env list --missing             # only the ones that are not set
agentos env list --category skill      # provider | search | image | audio | memory | skill | custom
agentos env get OPENAI_API_KEY         # state and description, value masked
agentos env get OPENAI_API_KEY --reveal
agentos env set OPENAI_API_KEY --stdin # value read from stdin
agentos env import GITHUB_TOKEN         # copy from a tool that already has it
agentos env unset OPENAI_API_KEY

agentos env import covers the case where the credential is not really missing. If you have run gh auth login, AgentOS can see that the GitHub CLI holds a token and copy it in rather than asking you to go find one; agentos env list marks such variables. Nothing is imported without you asking — a token you granted to another tool is not automatically something an agent should get. The copy does not follow that tool's own rotation, so re-run the import after rotating.

Values are never printed unless you ask for them with --reveal, which prompts first. Prefer --stdin or the interactive prompt over --value: a value passed as a flag lands in your shell history and in the process list.

When the gateway is running, the change applies to it immediately, so a skill that needed the variable becomes eligible without a restart. When no gateway is running the file is written directly and the command says the value applies at next start. Provider keys always need a restart to take full effect, because the client was constructed at boot with the previous value — the command tells you when that is the case.

Names that steer subprocess execution (PATH, LD_PRELOAD, PYTHONPATH, EDITOR, …) or AgentOS runtime posture (AGENTOS_AGENT_PERMISSIONS, AGENTOS_GATEWAY_TOKEN, AGENTOS_STATE_DIR, …) or outbound routing (HTTP_PROXY, AGENTOS_LLM_PROXY, AGENTOS_TRUST_ENV, … — proxy names in any casing) are refused, so this surface cannot be used to widen what the agent is allowed to do. Edit ~/.agentos/.env by hand if you genuinely need one of them. Variables already set that way keep working; only writing through AgentOS is gated.

If agentos env list reports a variable as coming from process env, the shell that started the gateway exported it and that value wins over the file. Editing the file will not change anything until the export is removed.

Shell commands the agent runs inherit most of this environment, but not the gateway token or the sandbox guard switches, and execute_code forwards only a small allowlist plus what a skill declares. See Credentials and child processes.

Read:

Skills

agentos skills init <name>
agentos skills init <name> --description "A custom skill description" -t "trigger1" -t "trigger2" --with-script
agentos skills list
agentos skills list --json
agentos skills search pdf
agentos skills view pdf-toolkit
agentos skills install <skill-name>
agentos skills install <skill-url> --source bankr
agentos skills install <skill-url> --source aeon
agentos skills update --all
agentos skills uninstall <skill-name>

agentos skills init <name> initializes a new custom skill template.

  • --description / -d provides a description of the skill.
  • --trigger / -t registers activation trigger terms (repeatable).
  • --target-dir / -p specifies the target parent directory. If omitted, the tool resolves to the highest precedence existing layer directory in the workspace/personal layers list.
  • --with-script scaffolds an executable script scripts/run.py template and entrypoint command configuration.
  • --force / -f forces overwrite of generated files without purging the parent folder.

The skills list table is unchanged: name, layer, eligible, description. --json carries more, and now reports the same facts the Web UI shows for the same skill instead of a separate, thinner answer:

KeyWhat it says
layerwhere the files are — bundled, managed, personal, project, workspace, extra
acquisitionhow the skill got there: kind is shipped, hub, or local, plus source_id, author, identifier, version, installed_at, source_trust, scan_verdict, and the removable / updatable booleans
publisher{id, name, url, logo}, all empty strings when the skill is unbranded. Only publishers on an allowlist inside AgentOS resolve to a name; a skill cannot brand itself by writing one into its manifest
provenanceunchanged, and independent of publisher — where the text came from and under what licence
statusready, needs_setup, or not_declared, alongside a disabled boolean and a status_detail line

acquisition.removable is the honest answer to "can agentos skills uninstall remove this", not a restatement of the layer: a hub install whose recorded path no longer matches the configured skills.managed_dir reports false, while updatable stays true because an update re-fetches by identifier.

status answers "can this run". ready means the manifest declared requirements and every one is satisfied; not_declared means there was no requires: block to check. Both run — the split records only whether AgentOS verified anything, which is why the Web UI shows them under one Ready count and leaves the distinction to status_detail. needs_setup covers a missing binary, a missing required env var, a wrong OS, and a skill switched off via skills.disabled / skills.enabled; only the disabled boolean tells the last one apart, and it is the only one no install will fix.

A required env var must be non-blank to count. export ORACLE_KEY= leaves the variable set but empty, which no API key, token, or path survives, so it reports as missing rather than as satisfied.

acquisition.author is an attribution string, not an identity. It is whatever the catalog row credited — a handle a publisher chose — so it passes through no allowlist and must never be rendered with a logo or read as a trust signal; publisher is the only field that answers "who vouches for this". It is empty only when it would repeat the resolved brand, so a partner skill is credited once rather than twice — a different credit survives. That is the wallet-published case: a skill written from a wallet on bankr.bot but named in the wheel's user-skill allowlist carries Bankr's publisher and the author's handle (e.g. @igoryuzo) as its author.

There is deliberately no availability key in CLI output. Whether the agent is currently being offered a skill depends on a chat session's tool surface, which a CLI process does not have; the gateway's skills.list and the Web UI answer that instead. An absent key means "not computed", not "not offered".

Read:

Sessions and History

agentos sessions list
agentos sessions list --search api-refactor    # match name, key, subject or model
agentos sessions show <session-key>
agentos sessions rename <session-key> "api-refactor"
agentos sessions rename <session-key> --clear  # drop the custom name
agentos sessions resume <session-key>
agentos sessions abort <session-key>
agentos sessions export <session-key>
agentos sessions delete <session-key>

Sessions are auto-named. rename gives one a human-readable label that shows up in sessions list, in the chat toolbar, and in the Web UI session list, and that --search, resume, and show all accept in place of the key. Inside a chat, /rename <name> does the same for the session you are in (no name clears it). Names are trimmed, collapsed to one line, and capped at 120 characters.

Projects

agentos projects list
agentos projects create "Token research" --knowledge "Shared context here"
agentos projects create "Token research" --knowledge-file notes.md
agentos projects show <project-id>
agentos projects update <project-id> --name "New name" --knowledge-file notes.md
agentos projects move <session-key> <project-id>   # 'none' detaches
agentos projects delete <project-id>               # sessions survive, detached

A project groups chat sessions across agents and carries a free-form knowledge text (capped at 24,000 characters — the same ceiling the per-turn injection applies, so everything that saves reaches the prompt in full). Every session in the project gets that knowledge injected into its system prompt as a Project Knowledge block — edit it and the next turn of every member session picks it up. Sessions of any agent can join the same project (the --agent on create only sets the default agent for new chats in the project). New sessions can start inside a project (agentos chat sessions join via projects move, the Web UI has a "New chat in project" button), and deleting a project never deletes sessions: they just detach and stop receiving the knowledge. Agents can manage projects from prompting through the projects_create / projects_list / projects_update / projects_move_session tools, and session_search scope=project searches only sibling sessions of the calling session's project. The tools are scoped to the calling session: projects_update edits only the session's own project, projects_list returns knowledge text only for that project, and projects_move_session moves only the calling session — everything else stays on the CLI/Web UI surface.

Read: Sessions and History

Memory

agentos memory status
agentos memory index
agentos memory list --source all
agentos memory ingest /path/to/docs
agentos memory curated get --target memory
agentos memory curated add "Important project convention"
agentos memory search "preference"
agentos memory show <path>
agentos memory raw-fallbacks list

Read: Memory

Durable Agents and Scheduling

agentos agents list
agentos agents add research --name Research --workspace /path/to/research
agentos agents delete research
agentos cron list
agentos cron add --every 1h --text "Summarize important updates" --name hourly-summary
agentos cron status <job-id>
agentos cron runs <job-id>
agentos cron output <job-id>

--job-kind picks what fires: reminder (delivers --text verbatim, no LLM), script (runs a file, no LLM), agent_turn (the agent runs --text as a prompt), or system_event. It defaults to auto, which is reminder for normal targets — so the example above repeats that sentence hourly rather than summarizing anything. Add --job-kind agent_turn to have the agent do the work.

Running a script on a schedule, without a model

agentos cron add --every 5m --script watch-memory.sh --name memory-watchdog
agentos cron update <job-id> --script watch-disk.sh --workdir /srv/app
agentos cron add --every 15m --script watch_rss.py --name hn \
  --script-arg --url --script-arg https://news.ycombinator.com/rss

--script implies --job-kind script and resolves relative to ~/.agentos/scripts/; absolute paths, ~, and .. are refused, and so is a symlink out of that directory. Subdirectories are allowed, and {job_id} anywhere in the path is replaced with the created job's own id, so a job can own a directory named after itself in one add. .sh/.bash run under bash, anything else under python. --script-arg (repeatable) passes argv straight to the script — never through a shell. Non-empty stdout is delivered verbatim, empty stdout is a silent run, and a non-zero exit or --timeout delivers the error and fails the job. Secrets are masked in the output, and the gateway token is withheld from the child process. The bundled cron-watchers skill ships scripts for RSS, JSON endpoints, and GitHub repos that already follow this contract.

Seeing what the script did

A job scheduled from the CLI has no conversation attached, so "delivered verbatim" has nowhere to deliver to: the stdout lands on the run record and the chat stays empty. --session-key names the chat the job reports into — the run itself stays isolated, only the output is mirrored there:

agentos sessions list                       # copy the key of the chat you want
agentos cron add --every 5m --script watch-memory.sh --name memory-watchdog \
  --session-key 'agent:main:webchat:<id>'

Either way agentos cron runs <job-id> shows each run's Output and Delivery columns. The Output column is a 500-character preview, so the whole list stays small no matter how much a job prints; agentos cron output <job-id> prints one run's output in full (the most recent run, or --run <run-id> for an older one — run ids come from agentos cron runs --json). A Delivery of fwd:no_session_target is the scheduler saying the script printed something that reached no conversation — add --session-key. Jobs created from the Web UI or from a chat already carry their originating session, so their output shows up in that chat without any extra flag.

Add --script to an --job-kind agent_turn job instead and it becomes a pre-run collector: its stdout is handed to the agent as context, and a tick where it prints nothing skips the turn entirely — no LLM call at all. See Scheduling.

No LLM runs, so no tokens are spent — but nothing reviews the script before it executes either. It runs on this host as you, unattended, so treat ~/.agentos/scripts/ as trusted as your shell profile. Only an interactive CLI or Web caller can create one; the in-agent cron tool refuses job_kind='script' from a channel.

Announcing to a specific channel

--announce --channel telegram --to <chat-id> pins where a job reports, and --account, --no-deliver, --best-effort-deliver, and --webhook-url cover the rest. The in-agent cron tool accepts the channel case too, through a delivery object — also restricted to an interactive CLI or Web caller, so a chat participant cannot redirect a job into a room they were never in. Webhook delivery and failure destinations stay CLI/Web/RPC-only. See Scheduling.

Letting a cron job run shell-based skills

By default, cron jobs of kind agent_turn run elevated under the bypass mode (controlled globally by permissions.cron_default_mode). This allows them to run shell-based commands (like those in skills) without interactive approval prompts.

If you wish to opt out a job from elevated execution, pass --no-elevated:

agentos cron add --every 6h --agent main --no-elevated \
  --name "LP check" --text "Use the senior-unilp-manager skill to review my LP positions"
agentos cron list                       # the Elevated column shows the mode
agentos cron update <job-id> --elevated-mode bypass

Related flags: --elevated (which sets the job to explicitly run elevated), --elevated-mode {bypass,full}, and --tool-policy '<json>' (profile, allow, alsoAllow, deny — can only narrow the cron baseline). profile must be one of coding, full, memory_only, messaging, minimal; omit the key to inherit rather than inventing a name, since an unknown one is rejected when the job is written. Elevation is only accepted on agent-turn jobs; reminders and system events never run an agent turn with the job's tool policy.

What you are accepting. Every time the job fires, with nobody watching, an LLM decides which shell commands run on this host as you, and they run — no approval prompt, no sandbox, with your environment variables and API keys passed through to the child process. If the skill signs transactions, an unattended turn can sign and broadcast them. write_file, git_commit, apply_patch and execute_code stay off the offered tool surface, but exec_command reaches all of them, so treat that list as a default rather than containment. Most importantly, anything the job reads from the network (web_fetch, web_search, RPC responses, token metadata) is untrusted input one reasoning step away from that shell.

Still enforced: the never-bypassable command denylist; the sensitive-path block on destructive operations against ~/.ssh, .env* and private keys, which bypass keeps and full disables; workspace lockdown and write-deny globs; no private-memory reads (force-denied for every cron caller, and no tool policy can revive them); no cron tool, so the job cannot schedule or elevate another; and no message tool, so output goes only where you configured delivery. Note the sensitive-path block does not stop a read of a secret file — once exec_command is on, secrets on disk are reachable.

A cron turn also never loads USER.md, so anything per-user the skill needs (wallet address, chain, thresholds) has to come from the task text or the environment.

Practical shape: one skill and one narrow task per elevated job, a tight --timeout, --session-target isolated, delivery and a failure destination configured, and if the skill has a dry-run/confirm handshake, keep cron on the read half and leave broadcasts to an interactive session.

Read:

Cost, Diagnostics, and Replay

agentos context
agentos context --json
agentos cost
agentos diagnostics status
agentos diagnostics on
agentos diagnostics off
agentos replay --session <session-key> --turn <turn-id>

agentos context answers a different question from agentos cost: not what a session spent, but what every request carries before the conversation starts. Tool schemas dominate it — around 7,300 tokens on a stock install, charged on every call in every turn — and the command prices each [tools] profile against the current one so the trade is visible before you make it. A profile is fixed for the session, so narrowing it does not disturb the prompt cache.

agentos cost aggregates and displays model usage and estimated cost reports from the gateway:

agentos cost [--by-model] [--json] [--csv]
agentos cost --start-date YYYY-MM-DD --end-date YYYY-MM-DD
agentos cost --agent-id <agent-id> --channel-type <channel-type>
agentos cost --tool-name <tool-name> --skill <skill-name>
agentos cost --export /path/to/export.csv
OptionPurpose
--by-modelGroup aggregate rows by model.
--jsonEmit machine-readable JSON.
--csvEmit machine-readable CSV.
--start-dateFilter by start date (YYYY-MM-DD).
--end-dateFilter by end date (YYYY-MM-DD).
--agent-idFilter by agent ID.
--channel-typeFilter by channel type.
--tool-nameFilter by tool name.
--skillFilter by skill name.
--exportPath to export results (JSON/CSV).

Use diagnostics and replay when you need to understand why a turn behaved a certain way. For Prometheus metrics (/metrics), OTLP trace export, and log retention settings under [observability], see Configuration.

Read:

MCP Server Bridge

agentos mcp-server run
agentos mcp-server run --gateway ws://localhost:18792/ws

Read: MCP Server Bridge