Metadata-Version: 2.4
Name: langstage-cli
Version: 0.4.0
Summary: The terminal stage for your LangGraph agent — Claude Code-style CLI for any CompiledGraph
Author-email: Kedar Dabhadkar <kdabhadk@gmail.com>
License-Expression: MIT
Project-URL: Homepage, https://github.com/dkedar7/langstage-cli
Project-URL: Repository, https://github.com/dkedar7/langstage-cli
Project-URL: Issues, https://github.com/dkedar7/langstage-cli/issues
Keywords: langgraph,langchain,langstage,cli,agents,llm,ai
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: langgraph>=0.2.0
Requires-Dist: langgraph-stream-parser<0.4,>=0.3
Requires-Dist: click>=8.0.0
Requires-Dist: python-dotenv
Requires-Dist: deepagents
Provides-Extra: dev
Requires-Dist: pytest>=7.0.0; extra == "dev"
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
Requires-Dist: black>=23.0.0; extra == "dev"
Requires-Dist: ruff==0.15.15; extra == "dev"
Requires-Dist: mypy>=1.0.0; extra == "dev"
Dynamic: license-file

# 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).

![langstage-cli](examples/image.png)

## 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](https://github.com/dkedar7/langstage) | `langstage run --agent my_agent.py:graph` |
| JupyterLab | [langstage-jupyter](https://github.com/dkedar7/langstage-jupyter) | `pip install langstage-jupyter`, then the chat sidebar in `jupyter lab` |
| Terminal | langstage-cli | **you are here** |
| VS Code | [langstage-vscode](https://github.com/dkedar7/langstage-vscode) | chat participant + stdio sidecar |
| Reference agent | [langstage-hermes](https://github.com/dkedar7/langstage-hermes) | `LANGSTAGE_AGENT_SPEC=langstage_hermes.agent:graph` on any stage |
| Shared core | [langgraph-stream-parser](https://github.com/dkedar7/langgraph-stream-parser) | typed events + config resolver behind every stage |

## Installation

```bash
pip install langstage-cli
```

Or install directly from GitHub:
```bash
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:
```bash
langstage-cli --demo "hello"
```

Run with the default agent (requires `ANTHROPIC_API_KEY`):
```bash
export ANTHROPIC_API_KEY="your_api_key"
langstage-cli
```

Or specify your own agent:
```bash
langstage-cli -a path/to/your_agent.py:graph
```

This launches an interactive conversation loop with your agent.

## Usage

```bash
# Use the default agent
langstage-cli

# Send a message directly
langstage-cli "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
```

## Commands

In the interactive loop:
- `/q` or `/quit` - Exit
- `/c` - Clear conversation history
- `/h` or `/help` - Show help

## Environment Variables

```bash
# 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"

# Stream mode (updates or values)
export LANGSTAGE_STREAM_MODE="updates"
```

## 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`:

```toml
[agent]
spec = "my_agent.py:graph"
workspace_root = "."

[ui]
verbose = true
async_mode = false
stream_mode = "updates"

[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)
  --async-mode/--sync-mode        Async streaming (default: sync)
  --stream-mode TEXT              Stream mode (updates or values)
  -v, --verbose                   Verbose output
```

## Creating Your Own Agent

Your agent file should export a compiled LangGraph graph:

```python
# 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-20250514",
    checkpointer=MemorySaver(),
)
```

Then run it:
```bash
langstage-cli -a my_agent.py:agent
```

## Programmatic Use

```python
from langstage_cli import stream_graph_updates, prepare_agent_input

input_data = prepare_agent_input(message="Hello!")

for chunk in stream_graph_updates(graph, input_data):
    if chunk.get("chunk"):
        print(chunk["chunk"], end="")
```

## License

MIT License - see LICENSE file for details.
