Skip to main content

langstage-cli

The terminal stage for your LangGraph agent. A Claude Code-style CLI that runs any LangGraph CompiledGraph — yours, not a bundled one — with streaming, tool-call rendering, and human-in-the-loop approval.

Renamed from deepagent-code (the old package name now just installs this one, and the deepagent-code command still works). Not to be confused with LangChain's deepagents-code (dcode) — that's a separate project; langstage-cli is the terminal stage of the LangStage family.

langstage-cli — the terminal stage for your LangGraph agent

Every stage for your LangGraph agent

langstage-cli is the terminal stage of the LangStage family: write your agent once — any LangGraph CompiledGraph — and run it on every stage with the same spec string (module:attr or path/to/file.py:attr), the same langstage.toml config file, and the same LANGSTAGE_* environment variables.

Stage Package Try it
Web app langstage langstage run --agent my_agent.py:graph
JupyterLab langstage-jupyter pip install langstage-jupyter, then the chat sidebar in jupyter lab
Terminal langstage-cli you are here
VS Code langstage-vscode chat participant + stdio sidecar
Reference agent langstage-hermes LANGSTAGE_AGENT_SPEC=langstage_hermes.agent:graph on any stage
Shared core langstage-core typed events + config resolver behind every stage

📖 Full documentation: https://dkedar7.github.io/langstage-docs/

Serve over AG-UI

This surface's agent — any LangGraph CompiledGraph — can also be served over the AG-UI protocol as a standalone HTTP endpoint:

pip install "langstage-core[agui]"
langstage-agui --agent my_agent.py:graph

Installation

pip install langstage-cli

Or install directly from GitHub:

pip install git+https://github.com/dkedar7/langstage-cli.git

Quick Start

No agent or API key yet? See the CLI working in one command:

langstage-cli --demo "hello"

Point it at your own agent (any LangGraph CompiledGraph):

export ANTHROPIC_API_KEY="your_api_key"   # if your agent calls Anthropic
langstage-cli -a path/to/your_agent.py:graph

This launches an interactive conversation loop with your agent.

Usage

# Keyless demo agent — no API key, no agent of your own
langstage-cli --demo "Hello"

# Scaffold a runnable starter agent + langstage.toml (then just run it)
langstage-cli init

# Send a message directly to your agent
langstage-cli -a my_agent.py:graph "Hello, agent!"

# Specify a custom agent file
langstage-cli -a my_agent.py:graph

# Use a module path
langstage-cli -a mypackage.agents:chatbot

# Read message from a file
langstage-cli -f ./prompt.md

# Non-interactive mode (auto-approve tool calls)
langstage-cli --no-interactive

# Verbose output
langstage-cli -v

# Keyless demo agent (no API key needed)
langstage-cli --demo

# Print the resolved configuration: each value, its source, and the
# env var / langstage.toml key that sets it
langstage-cli --show-config

# Resume a previous conversation across separate invocations
langstage-cli "remember: my name is Kedar"   # a fresh, PERSISTED session
langstage-cli -c "what's my name?"            # continue the most recent session
langstage-cli --list-sessions                 # list resumable sessions
langstage-cli --resume <id>                   # resume a specific one

Getting started with your own agent

langstage-cli --demo "hi"     # see the CLI work, keyless
langstage-cli init            # scaffold my_agent.py + langstage.toml (your own graph)
langstage-cli "hi"            # runs MY agent — no -a, no hand-editing

init writes a minimal, immediately-runnable starter agent (the stdlib StateGraph example below — needs only langgraph, a base dependency) plus a langstage.toml pointing at it, so the next langstage-cli "..." runs your graph. It refuses to overwrite an existing my_agent.py / langstage.toml unless you pass --force.

Resuming a session

Every invocation persists its conversation to a durable, per-workspace store so a later run can pick it up — the terminal-agent continuity of Claude Code / Codex / Aider, without you baking a checkpointer into your own graph:

  • --continue / -c — resume the most recent session for this workspace and keep going. If there's no prior session, it just starts a fresh one.
  • --resume <id> — resume a specific session (ids come from --list-sessions; a bare --resume also lists them). A short prefix works if it's unambiguous.
  • A plain run with no flag starts a new session that is still persisted, so it can be continued later.

State lives in ~/.langstage/sessions/<workspace-hash>.sqlite (honoring LANGSTAGE_CONFIG_HOME; override the whole location with LANGSTAGE_CLI_SESSIONS_DIR). Persistence is on by default — disable it with --no-persist, LANGSTAGE_PERSIST=0, or [session] persist = false in langstage.toml. A graph that compiles in its own checkpointer keeps it (yours always wins); the CLI only supplies a durable one when your graph has none. A pinned [configurable] thread_id now genuinely persists across runs.

Commands

In the interactive loop:

  • /help (/h, /?) - Show this help message, or /help <command> for one command
  • /status (/s) - Show session status (agent, thread, verbose, cwd)
  • /version (/v) - Show version and the current agent
  • /config (/cfg) - Show the resolved configuration, or set a runtime key: /config [key] [value]
  • /verbose - Toggle verbose output, or set it explicitly: /verbose [on|off]
  • /history (/hist) - Show recent conversation messages, optionally /history [N]
  • /clear (/c) - Clear conversation history
  • /reset (/restart) - Reset the session (clear history and start a new thread)
  • /quit (/q, /exit) - Exit
  • Tab autocompletes commands; Ctrl+C exits

Environment Variables

# Agent location (path/to/file.py:variable_name or module:variable)
# (DEEPAGENT_AGENT_SPEC / DEEPAGENT_SPEC still accepted as deprecated aliases)
export LANGSTAGE_AGENT_SPEC="my_agent.py:graph"
langstage-cli

# Working directory
export LANGSTAGE_WORKSPACE_ROOT="/path/to/workspace"

Configuration Files

langstage-cli reads TOML config from two locations and merges them (project overrides global):

  • Global: ~/.langstage/config.toml
  • Project: langstage.toml in the current directory or any ancestor

Legacy locations (~/.deepagents/config.toml, deepagents.toml) are still read as fallbacks; move your config when convenient — ~/.deepagents/ now belongs to LangChain's dcode.

Precedence: CLI args > env vars > project TOML > global TOML > defaults.

Example langstage.toml:

[agent]
spec = "my_agent.py:graph"

[workspace]
root = "."

[ui]
verbose = true

[configurable]
# seeds LangGraph RunnableConfig.configurable
thread_id = "my-thread"

CLI Options

Usage: langstage-cli [OPTIONS] [MESSAGE]

Arguments:
  MESSAGE  Optional input to send to the agent immediately

Options:
  -a, --agent TEXT                Agent spec (path/to/file.py:graph or module:graph)
  -g, --graph-name TEXT           Graph variable name (default: "graph")
  -f, --file PATH                 Read message from a file (any extension)
  --interactive/--no-interactive  Handle interrupts (default: interactive)
  -v, --verbose                   Verbose output
  --demo                          Run with the built-in keyless demo agent
  --show-config                   Print the resolved configuration and exit
  -q, --quiet                     Scriptable single-shot output: only the reply
  --verify                        Preflight the agent (one real turn); exit 0/1
  -c, --continue                  Resume the most recent session for this workspace
  --resume [ID]                   Resume a specific session (bare: list them)
  --list-sessions                 List resumable sessions for this workspace
  --persist/--no-persist          Persist this session so it can be continued (default: on)
  --force                         For `init`: overwrite existing files
  --version                       Show the version and exit

Subcommand:
  init                            Scaffold my_agent.py + langstage.toml in the current dir

Verifying an agent (CI gate)

--verify loads the configured agent and runs one real turn, exiting 0 if it completed cleanly and non-zero otherwise — so you can gate on it in CI before trusting an agent. It catches a missing key, a broken tool, or a non-runnable graph that a static "it imports" check would wave through (it runs the same langstage-core preflight every LangStage surface uses):

langstage-cli --verify -a my_agent.py:graph || { echo "agent broken" >&2; exit 1; }

Scriptable output

A single-shot run (a MESSAGE argument or -f/--file) prints only the agent's reply — no header, spinner, tool chatter, timing, or color — as soon as its output is piped (stdout isn't a TTY). Errors and diagnostics go to stderr, and the process exits non-zero if the turn failed, so a run is safe to capture:

answer=$(langstage-cli --demo "say hi") || echo "run failed" >&2
echo "$answer"        # -> (demo agent) You said: say hi

Pass -q/--quiet to force the same clean output in a terminal.

Creating Your Own Agent

Your agent file just needs to export a compiled LangGraph graph — langstage-cli runs any CompiledGraph. A minimal stdlib example (no extra deps):

# my_agent.py — needs only langgraph (a base dependency)
from langgraph.graph import StateGraph, START, END
from langgraph.graph.message import MessagesState
from langchain_core.messages import AIMessage

def respond(state):
    last = state["messages"][-1].content
    return {"messages": [AIMessage(content=f"You said: {last}")]}

g = StateGraph(MessagesState)
g.add_node("respond", respond)
g.add_edge(START, "respond")
g.add_edge("respond", END)
graph = g.compile()

Or a full deep agent (requires pip install deepagents):

# my_agent.py
from deepagents import create_deep_agent
from langgraph.checkpoint.memory import MemorySaver

agent = create_deep_agent(
    name="My Agent",
    model="anthropic:claude-sonnet-4-6",
    checkpointer=MemorySaver(),
)

Then run it:

langstage-cli -a my_agent.py:graph    # or :agent for the deepagents example

Programmatic Use

Since 1.0, streaming runs through the shared core's in-process AG-UI adapter (pip install "langstage-core[agui]"):

import asyncio
from langstage_core import load_agent_spec
from langstage_core.agui import build_agent, iter_chunk_frames

agent = build_agent(load_agent_spec("my_agent.py:graph"))

async def main():
    async for chunk in iter_chunk_frames(agent, "Hello!", thread_id="s1"):
        if chunk.get("chunk"):
            print(chunk["chunk"], end="")

asyncio.run(main())

License

MIT License - see LICENSE file for details.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

langstage_cli-0.6.30.tar.gz (95.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

langstage_cli-0.6.30-py3-none-any.whl (53.3 kB view details)

Uploaded Python 3

File details

Details for the file langstage_cli-0.6.30.tar.gz.

File metadata

  • Download URL: langstage_cli-0.6.30.tar.gz
  • Upload date:
  • Size: 95.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.15 {"installer":{"name":"uv","version":"0.11.15","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for langstage_cli-0.6.30.tar.gz
Algorithm Hash digest
SHA256 f9b7d81b3e241b985f195c842ffcb0dc52f575bc817cced32f99693fbc5f8943
MD5 3a750b4c56c05fd15ae76d7289aeb82f
BLAKE2b-256 32ad43dba6178a567c3ea7d92915441455d430714f57a94454a897f679f3f6c4

See more details on using hashes here.

File details

Details for the file langstage_cli-0.6.30-py3-none-any.whl.

File metadata

  • Download URL: langstage_cli-0.6.30-py3-none-any.whl
  • Upload date:
  • Size: 53.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.15 {"installer":{"name":"uv","version":"0.11.15","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for langstage_cli-0.6.30-py3-none-any.whl
Algorithm Hash digest
SHA256 8da987856a66059ac7ecbd6623e2ed4b26b7bee6b7fb37096e0e7231e730f852
MD5 7363e52df7d975d854c58c041b7d0321
BLAKE2b-256 2df8ea6f9ebebf99070447b812d7e9c41b98d6f8eade3f43c09ac6283e1c5c3f

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page