Skip to content

hsaliak/std_slop

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

1,077 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

std::slop

CI/CD - Multi-Platform Build & Release

CodeQL Advanced

std::slop

std::slop is a persistent, SQLite-driven C++ CLI agent built around a JavaScript control plane based on QuickJS-ng. Its primary way to inspect repositories, compose tool calls, validate results, and make changes is run_js: a synchronous JavaScript execution environment with safe tools.* helpers for file edits, shell commands, database queries, scratchpad updates, and higher-level workflow orchestration. That programmable control plane is what makes std::slop different from agents that only issue one tool call at a time: repeated operations can become deterministic scripts, scripts can be validated, and successful patterns can be promoted into reusable helpers.

The agent can also learn from its own workflows. The self_improvement_learner skill can be invoked directly with requests such as "hey self_improvement_learner learn from session history"; it identifies repeated run_js orchestration patterns and promotes them into persisted JavaScript functions through tools.persist_function(args). Persisted helpers are validated before storage, discovered through tools.help() and /tools js_help, and loaded automatically in later run_js invocations. This lets std::slop simplify future tool calling: a verbose sequence of reads, edits, shell validation, or JSON reshaping can become a single reusable function such as runCommandSummary(...).

✨ Key Features

  • 🧠 run_js control plane: std::slop primarily operates through run_js, a programmable JavaScript layer that batches local tool calls, loops over structured data, validates intermediate state, and returns compact JSON results.
  • 🎭 Personas & Skills: Define global agent instructions via AGENTS.md and extend capabilities using modular, on-demand SKILL.md files.
  • 🌱 Self-improving helpers: The self_improvement_learner skill can turn repeated run_js workflows into persisted functions via tools.persist_function(args), reducing complex tool orchestration to small reusable helpers.
  • 🧭 Dynamic workflow harnesses: The dynamic_workflow_harness skill helps agents choose bounded run_js patterns for repository surveys, fan-out analysis, evaluator loops, proposal tournaments, external content review, and validation guards.
  • πŸ“– Ledger-Driven: All interactions and tool calls are stored in SQLite for persistence and auditability.
  • πŸ“ Session Scratchpad: Maintain a per-session planning buffer with /scratchpad edit, /scratchpad save, and read_scratchpad/write_scratchpad tools.
  • πŸŽ›οΈ Context Control: Granular control over conversation history via SQL-backed retrieval and rolling windows. As the context is built per-session, you can create multiple sessions and even clone existing ones to go down different paths.
  • πŸ“¬ Mail workflows: Use docs/mail_mode.md for the manual patch-based workflow or docs/mail-loop/README.md for the automated mail-loop orchestrator.
  • πŸ€– Multi-Model: Supports Google Gemini and OpenAI-compatible APIs (OpenRouter, etc.) and OpenAI Responses API (with chatgpt plus/pro oauth).
  • πŸ“£ Hotwords: Quick, single-turn skill activation using hey <skill> <query> syntax. Eg: "hey code_reviewer review these patches".

πŸš€ Quick Start

Download

The project ships Linux x86-64 and macOS binaries every release. You can directly use them.

πŸ“‹ Prerequisites

  • C++17 compiler (Clang/GCC)
  • Bazel (Bazelisk recommended)
  • Git: Targets must be valid git repositories. Usually, a git add and an initial commit is sufficient to trigger all the git enabled features.

πŸ› οΈ Build and Install

# Build the binary
bazel build //:std_slop

# Optional: Add to your PATH
cp ./bazel-bin/app/std_slop /usr/local/bin/

⌨️ Usage

std::slop works best when it can track a specific project. Initialize a git repository and run it from the root:

mkdir my-project && cd my-project
git init
std_slop

For quick one-off tasks, you can use Batch Mode:

std_slop --prompt "Refactor main.cpp to remove all unused includes" 

Batch mode accepts exactly one instruction source, and optional piped stdin is prepended as context:

std_slop --prompt-file task.md
ls *.cc | std_slop --prompt "sort these files in alphabetical order"
cat errors.log | std_slop --prompt-file diagnose.md

Use exactly one instruction source: --prompt or --prompt-file. Empty instructions are rejected. Empty or whitespace-only piped stdin is ignored.

For scripts, batch mode can emit one structured JSON object to stdout:

std_slop --prompt-file task.md --output json | jq -r .assistant_message

The JSON object contains ok, session, model, active_skills, assistant_message, error, and duration_ms.

Batch mode also takes in --model which is useful to specify the model to use and --session which is useful to indicate the session the prompt should be executed under. Batch mode works off an in memory sqlite db. If you want the db persisted you can point it to a DB with the --prompt-db argument. /commands are also supported.

Read the Walkthrough first for the recommended getting-started flow, authentication setup paths, config.ini setup, docs-folder navigation, and llm_query subquery/persona configuration. Then use docs/README.md as the docs index for deeper reference material.

Authentication Quick Notes

  • Gemini: set GOOGLE_API_KEY or put it in ~/.config/slop/config.ini
  • OpenAI-compatible API key: set OPENAI_API_KEY, optionally combine with --openai_base_url, or put both in config.ini
  • OpenAI OAuth (Responses API): run std_slop --fetch_openai_oauth_token or std_slop --fetch_openai_oauth_device_token, then start with --openai_oauth

βš™οΈ Configuration

You can configure std::slop using environment variables or a configuration file.

Configuration File

The agent looks for a configuration file at ~/.config/slop/config.ini. You can also specify a custom path using the --config flag. It is STRONGLY RECOMMENDED that slop.db lies in a central directory or outside the codebase. It generates 2 other artifact files, at least ensure that your .gitignore contains this. The context ledger is completely stored in the database, and it can inadvertently capture information from your environment if you are not careful. Eg Environment Variables.

For a getting-started walkthrough that covers config methods end-to-end, see docs/WALKTHROUGH.md.

[slop]
model = gemini-3-flash-preview
# OR
openai_api_key = sk-...
openai_base_url = https://api.openai.com/v1
# use_responses = true   # optional: use OpenAI Responses API with API key mode
# openai_oauth = true    # optional: use OpenAI OAuth token + Responses API
# openai_oauth_token_path = /custom/path/chatgpt_plus_token.json

See docs/example_config.ini for a full list of options.

Configure LLM sub-agents (specialized llm_query tools)

You can define config-based llm_query specializations as first-class tools. This is useful for role-focused delegation (for example: code review, repo exploration) without rewriting prompts each time.

Add one INI section per specialization using the llm_tool_ prefix:

[llm_tool_code_review_llm]
system_prompt_patch = You are a strict code reviewer focused on correctness and regressions.
session_id = code_review
skill = code_reviewer
context_window = 8

After startup, call the specialized tool directly by name (for example llm_tool_code_review_llm) with a query argument.

For a complete multi-specialization example, see docs/example_subqueries.ini. Detailed behavior and policy constraints are documented in docs/impl/subqueries.md.

JavaScript control-plane helpers (run_js)

Agents can use the top-level run_js tool to execute a synchronous QuickJS snippet when a task is easier to express as local control flow: batching file reads, reshaping JSON, looping over small file edits, or running a focused shell validation. Pass a JavaScript body in the code field and end with return <json-serializable value>; when a result is needed. Optional JSON input is exposed as globalThis.input; use it for source-code or edit payload strings instead of embedding those strings in JavaScript literals.

Inside the snippet, tools.* helper methods validate arguments before they call the host tool. Use tools.help() to discover the current helper/tool catalog, and use tools.dispatch(name, args) for run-js-callable host tools that do not have a dedicated helper method. Host calls still pass through the normal tool executor, permission checks, and subquery policy. run_js cannot recursively invoke itself.

Minimal example:

return tools.read_file({ path: 'README.md', start_line: 1, end_line: 20 });

Batching example:

const status = tools.execute_bash({
  cwd: '.',
  command: 'git status --short',
  allow_nonzero_exit: false,
  timeout_seconds: 60
});
const help = tools.help();
return { status: status.stdout, run_js_callable: help.run_js_callable };

Keep snippets bounded and deterministic, summarize large outputs before returning them, and prefer exact edit_tool edits for source changes. For reusable JavaScript, use tools.persist_function(args) after checking the current helper catalog with tools.help(); persisted functions are stored in js_functions and shown by /tools js_help. For adaptive multi-step tasks, activate the dynamic_workflow_harness skill to select a small, budgeted run_js template instead of hand-rolling an unbounded workflow.

Environment Variables

  • SLOP_DEBUG_HTTP=1: Enable full verbose logging of all HTTP traffic (headers & bodies).

πŸ’» Code

  • C++ Standard: C++17.
  • Style: Google C++ Style Guide.
  • Exceptions: Disabled (-fno-exceptions).
  • Memory: RAII and std::unique_ptr exclusively.
  • Error Handling: absl::Status and absl::StatusOr.
  • Asan and Tsan clean at all times.

πŸ“š Documentation

πŸ—οΈ Architecture & Codebase Layout

core/ - The Engine

The core logic is divided into modules:

  • database.h: Manages the SQLite-backed ledger. Handles persistence for messages, memos, tools, and skills.
  • tool_dispatcher.h: Implements a thread-safe execution engine. It dispatches multiple tool calls concurrently while ensuring results are returned in the proper order for the LLM.
  • cancellation.h: Provides a mechanism for interrupting tasks. It supports registering callbacks to kill shell processes or abort HTTP requests.
  • orchestrator.h: high-level interface for model interaction. Implementations for Gemini and OpenAI manage history windowing and response parsing.
  • shell_util.h: Executes shell commands in a separate process group, with support for live output polling and termination on cancellation.
  • http_client.h: A minimalist, cancellation-aware HTTP client used for all model API calls.

Interface & Display

  • interface/: Implements the terminal UI. The UI is minimal but clean, uses readline for user input, color codes and ASCII Codes.
  • markdown/: Uses tree-sitter-markdown to provide syntax highlighting (C++, Python, Go, JS, Rust, Bash) and structured rendering for agent responses. This is a stand alone Markdown parser / renderer library in C++.
  • app/main.cpp: The primary event loop. Coordinates between the Orchestrator, ToolDispatcher, and UI.

About

STD::SLOP An Sqlite/C++ Code CLI

Resources

License

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors