Skip to main content

acra-cli

Agentic CLI for LLM-powered research, task execution, code generation, workflow automation, memory, and sandboxed validation.

acra-cli is an installable Python package that provides the acra command-line tool and a reusable LangGraph-based agent workflow. Install the package as acra-cli, run it from the terminal as acra, and import the Python package as acra.

It is built for developers who want a local CLI for asking an LLM-powered agent to research, plan, generate code, validate generated projects, and keep workflow context across runs.

Status: beta. The package is usable, but some CLI command groups are still scaffolds. The most complete surfaces today are installation, provider configuration, profile setup, key management, the interactive shell, research workflows, and Python-level workflow APIs.

Highlights

  • Installable PyPI package: acra-cli
  • Console command: acra
  • Python import package: acra
  • Interactive CLI shell powered by Typer, Rich, and prompt-toolkit
  • LangGraph workflow with planner, researcher, coder, executor, critic, memory, and human nodes
  • Provider support for Gemini, OpenAI, Groq, Ollama, and HuggingFace
  • Configuration profiles stored in ~/.acra/config.json
  • OS keyring support for API keys
  • Research command with depth, sources, formatting, output, JSON, and memory options
  • Generated project saving and validation
  • ChromaDB-backed vector memory and JSON workflow memory modules
  • Optional extras for provider-specific dependencies and checkpoint backends

What's New in 0.2.2

acra memory, acra session, acra brain, and acra graph were all previously stub commands that printed placeholder text and did nothing. This release wires them to the backends that already existed, fixes model selection being silently ignored, and fixes two bugs in where generated files actually end up.

New features

  • acra memory list, search, and clear are now real, scoped to the current directory's project. clear asks for confirmation (--yes to skip it). New acra memory stats shows success rate and average quality score for the project.
  • acra session list shows every project acra has continuity for, with directory, profile, and a live run count / success rate. acra session resume <id> looks up which directory a thread belongs to.
  • acra brain models now covers all six supported providers (was two). acra brain test actually checks whether the brain's provider has a key configured, instead of an unconditional stub.
  • acra graph show is wired to the real workflow graph: a summary table by default, --mermaid for the raw diagram source, --save <path> to export it.

Bug fixes

  • Model selection was silently ignored. acra config init saved a model to your profile, but nothing ever read it -- only environment variables mattered. Provider and model now resolve as env var, then profile, then default, correctly per provider (a profile's model for one provider is never misapplied if an env var switches to a different provider). acra config show now displays what's actually in effect and where it came from.
  • workspace had no effect. A profile's saved workspace directory was only ever used for cosmetic display; every generated project always landed under the fixed global data directory regardless of what workspace was configured. Generated projects now save to the configured workspace, falling back to the previous global location when none is set.
  • Generated files were sometimes never saved at all. For build, ask, review, and explain (all of which default to not executing code), the executor was returning before ever writing files to disk -- the result panel would list "generated files" that didn't actually exist anywhere once the process exited. Files are now always saved regardless of whether --execute was passed.
  • session_id was never set, so every project's memory silently landed in one shared file regardless of directory. Memory storage is now scoped per project the same way checkpoint continuity is.
  • --no-memory previously had no effect on the memory agent, which stored an entry regardless. It now correctly skips storage.

What's New in 0.2.1

This release jumps from 0.1.5 straight to 0.2.1 (0.1.6 was never published) to mark a batch of fixes serious enough that they change actual runtime behavior, not just polish: a routing/schema audit across every agent that fixes a confirmed infinite loop, closes the exact cause of the recurring "Unexpected transition" warnings, and makes memory persistence actually happen for the first time.

Critical fix

  • Fixed an infinite loop in the memory agent. memory_agent determined its own next step by reading next_agent back out of the state it was just handed, rather than setting it deterministically. Since the critic agent routes to memory by setting state["next_agent"] = "memory", and that value is still present when memory_agent runs, it would read back "memory", do its work, and then output "memory" again as its own next step -- routing into itself, forever, with no error and no way out short of killing the process. This was dormant until the critic-routing fix below made memory actually reachable for the first time; before that, the critic always skipped straight to "end" and this code path was never exercised. memory_agent now always deterministically routes to "end", matching its one real edge in the graph.

Schema, prompt, and routing audit (all four agents)

Read every agent's Pydantic schema and ChatPromptTemplate end to end and cross-checked each against acra.graph.edges.GRAPH_EDGES, the graph's actual declared transitions. Found and fixed real mismatches, not just style issues:

  • Coder: the prompt was internally self-contradictory -- one section listed next_agent as "executor, critic, human", the section right below it dropped "human" and kept "critic", which the graph has never actually supported as a transition from coder. This was the exact, confirmed cause of the repeated "Unexpected transition from 'coder' to 'human'" warnings. The schema is now narrowed to executor only, the coder agent deterministically sets next_agent itself rather than trusting the model's choice, and human was added to the graph's valid coder transitions for the one legitimate case (interactive approval) that still needs it.
  • Researcher: the prompt explicitly told the model to route to "planner" or "human", neither of which the graph supports from researcher (only "coder" is valid) -- and researcher_agent had no override at all, so any of those choices silently ended the entire workflow early. Schema narrowed to coder only; the agent now sets it deterministically.
  • Critic: the prompt said "approved -> end", and the schema didn't even list "memory" as an option -- meaning a successfully approved run could never reach memory persistence at all, despite the graph explicitly supporting it. Schema now includes "memory"; the critic agent deterministically routes based on review outcome (approved -> memory, needs_improvement/failed -> coder, unsafe -> human if interactive else back to coder for a fix attempt).
  • Planner: the prompt claimed retries exceeding a safe limit route to "human", but the actual code has always deterministically routed to "critic" instead in that case -- harmless, since the code already ignores the model's own choice here, but the prompt was actively teaching an outcome that never happens. Corrected the prompt; also removed "executor" from the schema since the planner's deterministic logic never assigns it.
  • Unified inconsistent internal branding ("AgentForge" in two prompts, "OMNIAGENT" in the other two) to "OmniAgent" throughout.

New features

  • Task commands (ask, build, fix, review, explain, run) now show acra's live "thought process" while a run is in progress: each agent's output streams token-by-token as it's generated, parsed on the fly into a short human-readable summary (the plan being built, research findings, which files are being written, review feedback and score) instead of raw JSON, and resolves into a clean permanent status line once that agent finishes.
  • --memory (the default on every task command) now has real effect: acra persists a checkpoint thread per working directory and profile, so a follow-up command in the same directory continues the same project instead of starting from a blank slate. --no-memory starts a genuinely fresh, unpersisted run every time. The new --new flag starts a separate, fresh project on demand without turning memory off going forward -- use it whenever a request in the same directory is unrelated to whatever was last built there.
  • Task commands no longer execute generated code by default. build, ask, review, and explain generate files without running them unless you pass --execute; fix and run still execute by default, since verifying a fix or literally running something is the point of those two, but --no-execute turns that off too.

Other fixes since 0.1.5

  • Fixed acra build (and every other task command) always attempting to run generated code in the Docker sandbox, even when nothing asked for it to be executed.
  • Fixed a major continuity bug where a follow-up command in the same directory (for example, asking to improve the UI of a project just built) had no knowledge of the previous run and could generate an unrelated project from scratch instead of continuing the existing one.
  • Fixed OmniAgentCallbacks raising AttributeError on on_llm_new_token once real token streaming was in use, which previously flooded the terminal with callback error spam during every run.
  • Fixed the live "thinking" output showing raw, partially-streamed JSON syntax instead of a readable summary.
  • Fixed a crash (AttributeError: 'dict' object has no attribute 'topic') introduced by an earlier attempted fix for a LangGraph checkpoint warning: research_agent.py's existing code already converted findings/sources to plain dicts correctly further down; converting them a second time, earlier, broke that code's attribute access. Reverted to the original, correct extraction.
  • Fixed the checkpoint warning itself (Deserializing unregistered type acra.schemas.critic_schema.ReviewIssue) at its actual source: critic_agent.py was storing raw Pydantic objects directly into checkpointed state; they're now converted to plain dicts first.

What's New in 0.1.5

New features

  • Provider credentials can now be stored with acra keys and used directly by Gemini, OpenAI, Groq, and HuggingFace Cloud workflows.
  • The configuration wizard stores provider and research credentials outside the plaintext profile file, using the OS keyring when available and a permission-restricted local fallback otherwise.
  • Long-running task and research commands show a live progress spinner.
  • Task and research results are rendered as readable summaries, findings, sources, and generated-file lists instead of raw workflow state.
  • Commands launched from the interactive shell now stream their output live.

Bug fixes

  • Fixed saved provider keys not being read by LLM initialization.
  • Fixed profile setup writing API and research keys to plaintext configuration.
  • Fixed interactive-shell commands buffering output until completion.
  • Fixed unwieldy raw dictionary and message-object output after task or research runs.

Requirements

  • Python >=3.11
  • At least one supported LLM provider or local inference backend
  • Optional: Docker, if you use execution paths that run generated projects in containers

Installation

Install the base package:

pip install acra-cli

Install provider-specific extras as needed:

pip install "acra-cli[openai]"
pip install "acra-cli[groq]"
pip install "acra-cli[ollama]"
pip install "acra-cli[huggingface]"

Install checkpointing extras:

pip install "acra-cli[sqlite]"
pip install "acra-cli[postgres]"

Install multiple extras together:

pip install "acra-cli[openai,groq,sqlite]"

After installation, run:

acra

or:

python -m acra

Quick Start

Configure a provider:

export LLM_PROVIDER=gemini
export GOOGLE_GEMINI_API_KEY="your-key"

Start the interactive shell:

acra

Create a local configuration profile:

acra config init

Show the active profile:

acra config show

Store a key in your OS keyring:

acra keys set GEMINI_API_KEY

Run a research workflow:

acra research research "Compare LangGraph and CrewAI for code-generation workflows"

The repeated research research is intentional in the current CLI: the first research is the command group and the second research is the subcommand.

Provider Configuration

acra reads provider settings from environment variables. Select the active backend with:

export LLM_PROVIDER=gemini

Supported values:

  • gemini
  • openai
  • groq
  • ollama
  • huggingface_local
  • huggingface_cloud

Common optional setting:

export LLM_TEMPERATURE=0.6

Gemini

Gemini support is included in the base package dependencies.

export LLM_PROVIDER=gemini
export GEMINI_MODEL=gemini-2.5-flash
export GOOGLE_GEMINI_API_KEY="your-key"

GEMINI_API_KEY is also accepted as a fallback credential variable.

OpenAI

pip install "acra-cli[openai]"

export LLM_PROVIDER=openai
export OPENAI_MODEL=gpt-4o-mini
export OPENAI_API_KEY="your-key"

Groq

pip install "acra-cli[groq]"

export LLM_PROVIDER=groq
export GROQ_MODEL=llama-3.3-70b-versatile
export GROQ_API_KEY="your-key"

Ollama

pip install "acra-cli[ollama]"

export LLM_PROVIDER=ollama
export OLLAMA_MODEL=mistral
export OLLAMA_BASE_URL=http://localhost:11434

Make sure Ollama is running:

ollama serve

HuggingFace Cloud

pip install "acra-cli[huggingface]"

export LLM_PROVIDER=huggingface_cloud
export HF_MODEL=mistralai/Mistral-7B-Instruct-v0.1
export HF_API_KEY="your-token"

HuggingFace Local

pip install "acra-cli[huggingface]"

export LLM_PROVIDER=huggingface_local
export HF_MODEL=mistralai/Mistral-7B-Instruct-v0.1
export HF_DEVICE=cpu

Use HF_DEVICE=cuda for compatible GPU environments.

Configuration Profiles

Profiles are stored in:

~/.acra/config.json

Create or update the default profile:

acra config init

Create a named profile:

acra config init --profile work

Show a profile:

acra config show
acra config show --profile work

The setup wizard prompts for:

  • provider
  • model
  • provider API key
  • theme
  • workspace path
  • research API keys

Key Management

acra can store credentials in your operating system keyring.

Set a key interactively:

acra keys set OPENAI_API_KEY

Set a key directly:

acra keys set OPENAI_API_KEY "your-key"

List key status:

acra keys list

Delete a key:

acra keys delete OPENAI_API_KEY

Supported provider key names are GEMINI_API_KEY, OPENAI_API_KEY, GROQ_API_KEY, and HF_API_KEY. Keys are stored in your OS keyring when it is available. On systems without a keyring backend, acra uses a local credentials file with owner-only permissions.

Research key names:

acra keys set research.web
acra keys set research.github
acra keys set research.docs
acra keys set research.arxiv

Environment fallback variables:

  • GEMINI_API_KEY or GOOGLE_GEMINI_API_KEY
  • OPENAI_API_KEY
  • GROQ_API_KEY
  • HF_API_KEY
  • ACRA_RESEARCH_WEB_KEY
  • ACRA_RESEARCH_GITHUB_KEY
  • ACRA_RESEARCH_DOCS_KEY
  • ACRA_RESEARCH_ARXIV_KEY

CLI Usage

Run the top-level help after installation:

acra --help

Global options include:

  • --profile
  • --workspace
  • --no-memory
  • --dry-run
  • --json
  • --verbose / -v
  • --quiet / -q
  • --timeout

Interactive Shell

Running acra without a subcommand starts the shell:

acra

You can also launch it explicitly:

acra serve

Inside the shell, type commands such as:

config show
keys list
research research "What are good approaches for agent memory?"
memory list
session list
graph show
exit

Research

Run:

acra research research "What is the best architecture for a local-first AI coding agent?"

Options:

  • --depth: shallow, standard, or deep
  • --sources: comma-separated source list
  • --format: citations, summary, or detailed
  • --output: write output to a file
  • --save: persist research output into memory
  • --follow-up: keep the session open for follow-up questions
  • --no-memory: skip memory persistence
  • --profile: select a profile
  • --json: output JSON
  • --verbose / -v: show detailed output

Examples:

acra research research "Survey Python sandboxing options" --depth deep
acra research research "Compare ChromaDB and FAISS for agent memory" \
  --sources web,github,arxiv \
  --format detailed \
  --output research-report.md
acra research research "LangGraph checkpointing options" \
  --format summary \
  --json

Task Commands

ask, build, fix, review, explain, and run all run the same underlying planner → researcher → coder → executor → critic workflow; they differ only in the label shown in the result panel, not in behavior.

acra ask "how many moons are in our solar system"
acra build "a Flask app that tracks reading habits"
acra fix "the login endpoint returns 500 on empty passwords"
acra review "the auth module for security issues"
acra explain "how the checkpoint system works"
acra run "the data migration script"

Common options on every task command:

  • --profile: profile to use

  • --memory / --no-memory (default --memory): whether this run continues the checkpointed project/conversation for the current directory and profile, or starts completely fresh. See "Continuity Between Commands" below.

  • --new: start a fresh project/thread in this directory instead of continuing the last one, without turning --memory off going forward. Use this whenever the request is unrelated to whatever was last built here.

  • --interactive: route agent approval requests to a human-in-the-loop prompt

  • --execute / --no-execute: whether to actually run the generated project in the Docker sandbox afterward. Defaults differ by command:

    Command Default Reasoning
    build --no-execute Generating a project doesn't require running it
    ask --no-execute A question doesn't need code execution
    review --no-execute Reviewing doesn't need re-running
    explain --no-execute Explaining doesn't need execution
    fix --execute Verifying the fix is usually the point
    run --execute That's what "run" means

    Pass --execute or --no-execute explicitly to override any command's default.

Execution, when it happens, always runs inside a locked-down Docker container (no network, dropped capabilities, memory/PID limits). Docker must be installed and the invoking user must have permission to use it; without that, --execute will fail with a Docker connection error rather than silently falling back to running code on the host.

Continuity Between Commands

With --memory (the default), acra persists a checkpoint thread per (profile, working directory) pair. Running acra build "..." and then, from the same directory, acra ask "improve the ui" will give the second command the first one's generated files and project context to work from, instead of starting a new, unrelated project.

This continuity is directory-scoped, not request-scoped: acra does not try to detect whether a new request is actually related to the last one. Running two unrelated acra build commands back to back from the same directory will make the second one try to continue/patch the first project instead of starting the new one you asked for. Pass --new on the second command whenever the request is a different project, not a follow-up:

acra build "a money manager app"
acra build "an indian restaurant ordering app" --new   # unrelated -- needs --new
acra build "add a dashboard to that"                    # follow-up -- no --new needed

Use --no-memory on a specific command for a one-off run that doesn't touch or read the persisted thread at all, or run from a different directory to keep projects separated automatically.

Configuration:

acra config init
acra config show

Keys:

acra keys set GEMINI_API_KEY
acra keys list
acra keys delete GEMINI_API_KEY

Memory:

acra memory list
acra memory search "previous docker error"
acra memory clear

Sessions:

acra session list
acra session resume <session-id>

Graph:

acra graph show
acra graph run

Note: memory, session, and graph command groups are currently available but include placeholder handlers in this beta release. The underlying Python modules are more complete than the current CLI wrappers.

Python Usage

The package exposes reusable workflow and configuration modules.

Run the compiled LangGraph workflow:

from acra.graph.workflow import OmniAgentCallbacks, create_workflow

workflow = create_workflow()

result = workflow.invoke(
    {
        "user_request": "Build a small Python CLI that validates JSON files",
        "interactive": False,
        "retry_count": 0,
        "max_retries": 5,
    },
    config={"callbacks": [OmniAgentCallbacks()]},
)

print(result)

Use the LLM factory:

from acra.agents.llm import llm

model = llm()
response = model.invoke("Say hello in one sentence.")

print(response.content if hasattr(response, "content") else response)

Load a profile:

from acra.config.profile_manager import ProfileManager

profile = ProfileManager().load_profile()
print(profile)

Use JSON memory:

from acra.agents.memory.memory_manager import get_memory_manager

memory = get_memory_manager("example-session")
memory.add_memory(
    "workflow_result",
    {
        "user_request": "Create a CLI",
        "execution_success": True,
        "quality_score": 8.5,
    },
)

print(memory.get_recent_memories(limit=3))

Data Locations

Profile configuration:

~/.acra/config.json

Application data is stored in a platform-specific user data directory resolved with platformdirs.

Override it with:

export OMNIAGENT_DATA_DIR=/path/to/acra-data

Important subdirectories:

  • credentials.json: permission-restricted credential fallback when no OS keyring is available
  • projects/: generated project files
  • memory/storage/: JSON memory files
  • memory/chroma_db/: ChromaDB vector memory
  • memory/checkpoints/data/: workflow checkpoint data

Current Beta Notes

  • The package version is 0.2.2.
  • The top-level CLI currently attaches serve, config, keys, research, memory, session, graph, and workspace.
  • The codebase contains additional command modules such as brain, context, logs, and plugin, but they are not currently attached to the top-level CLI.
  • Some CLI command groups return placeholder output while the Python modules behind them continue to evolve.

Troubleshooting

Missing provider dependency

Install the matching extra:

pip install "acra-cli[openai]"
pip install "acra-cli[groq]"
pip install "acra-cli[ollama]"
pip install "acra-cli[huggingface]"

Missing API key

Set the provider key:

export GOOGLE_GEMINI_API_KEY="your-key"
export OPENAI_API_KEY="your-key"
export GROQ_API_KEY="your-key"
export HF_API_KEY="your-token"

Or store it with:

acra keys set GEMINI_API_KEY

Ollama connection failure

Start Ollama and make sure the model is available:

ollama serve
ollama pull mistral

Then configure:

export LLM_PROVIDER=ollama
export OLLAMA_MODEL=mistral
export OLLAMA_BASE_URL=http://localhost:11434

License

acra-cli is licensed under the GNU Affero General Public License v3.

Package Metadata

  • PyPI package name: acra-cli
  • Console command: acra
  • Python import package: acra
  • Version: 0.2.2
  • Python: >=3.11
  • Console script: acra=acra.cli:app_main
  • Author: Raj Tembe

Download files

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

Source Distribution

acra_cli-0.2.2.tar.gz (204.9 kB view details)

Uploaded Source

Built Distribution

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

acra_cli-0.2.2-py3-none-any.whl (257.2 kB view details)

Uploaded Python 3

File details

Details for the file acra_cli-0.2.2.tar.gz.

File metadata

  • Download URL: acra_cli-0.2.2.tar.gz
  • Upload date:
  • Size: 204.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.12.3

File hashes

Hashes for acra_cli-0.2.2.tar.gz
Algorithm Hash digest
SHA256 1dfdfd0f0aa900fb8896fa7a440c9ad344288dbfed77998624135000ea3c41ac
MD5 3d37ff4931642eaa63490a8fdf222136
BLAKE2b-256 dea4177cd8223f93a83e28142a027f4b0417ad304ff63b27b3ef996a065ef8ab

See more details on using hashes here.

File details

Details for the file acra_cli-0.2.2-py3-none-any.whl.

File metadata

  • Download URL: acra_cli-0.2.2-py3-none-any.whl
  • Upload date:
  • Size: 257.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.12.3

File hashes

Hashes for acra_cli-0.2.2-py3-none-any.whl
Algorithm Hash digest
SHA256 3c529da94792796f95347efb7064fc3509a2b4f69d6db5750ea8f141ef2419c2
MD5 90c2753fbff5e7eb06e0ed53ab5d50b6
BLAKE2b-256 c6a48b56851b180722350c59cdf2d5c1a4f582b4b4e014bad6d026df9517f479

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.2.2 This release

2 files

0.2.1

2 files

0.1.5

2 files

0.1.4

2 files

0.1.3

2 files

0.1.2

2 files

0.1.1

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page