bandit-agent-framework

mcp
Guvenlik Denetimi
Basarisiz
Health Uyari
  • License — License: Apache-2.0
  • Description — Repository has a description
  • Active repo — Last push 0 days ago
  • Low visibility — Only 5 GitHub stars
Code Basarisiz
  • rm -rf — Recursive force deletion command in .github/workflows/image-generation-images.yaml
Permissions Gecti
  • Permissions — No dangerous permissions requested

Bu listing icin henuz AI raporu yok.

SUMMARY

Local-first, model-agnostic AI agent framework — the runtime behind the Bandit Stealth CLI and VS Code / Cursor extension. Apache-2.0.

README.md
Burtson Labs

Bandit Agent Framework

A local-first AI coding agent — in your editor, at your terminal, or embedded in your app.

Your code never leaves your machine. Works with any Ollama model.

Docs
CLI on npm
VS Code Marketplace
Open VSX
License
CI

Full documentation: docs.burtson.ai


Two hosts, one runtime

Host When to use Install
Bandit Stealth (VS Code / Cursor) Editing code, reviewing diffs, rich panel UI code --install-extension BurtsonLabs.bandit-stealth
Bandit CLI (bandit) Terminal workflows, CI, scripting, remote dev over SSH npm i -g bandit-stealth-cli

Both talk to the same stealth-core-runtime. Skills, memory files, and hooks work identically across them.


Quick start — CLI

# 1. Install Ollama and a model
brew install ollama
ollama pull gemma4:e4b              # CLI default — ~3 GB, multimodal, agent-ready

# 2. Install the CLI (curl, or npm if you prefer)
curl -fsSL https://burtson.ai/bandit-stealth-cli/install.sh | sh
# npm i -g bandit-stealth-cli

# 3. Run in any project
cd ~/my-project
bandit                              # interactive REPL
bandit "explain @src/auth.ts"       # one-shot with file mention

First launch:

╭── bandit 1.7.348 ───────────────────────────
│  ollama/gemma4:e4b  •  7 skills  •  session 20260530-091245-ab3c
╰────────────────────────────────────────────
Type /help for commands, @path to pin a file, or exit to quit.

› _

Quick start — VS Code

Search Bandit Stealth in the Extensions panel, install, and open the side panel. The agent uses tools automatically — reading files, searching code, running commands, writing changes.


Features

Skills that auto-activate

Drop a markdown skill into .bandit/skills/ and it loads on the next turn.
Skills are context packages — YAML frontmatter for metadata, a markdown body
that becomes the playbook the agent reads when the skill activates. Triggers
are regex matches on the user prompt; skills with activation: always run
every turn. Legacy JSON skills still load.

The default set covers:

  • Filesystem core (always on) — read/write/edit, search, run commands, todo tracking, web fetch/search
  • Git (always on) — status, diff, log, blame, commit drafting
  • Code review — activates on "review my changes" / "review this PR"
  • Testing — activates on "write tests", auto-detects vitest / jest / mocha / pytest / cargo test
  • Planning — activates on "refactor", multi-step prompts
  • Semantic search — activates on "how does", "where is", embedding lookups via local nomic-embed-text
  • Mail search — activates when a Gmail MCP server is connected and the prompt references mail

Run /skills inside the REPL for the full list with descriptions and tool sets.
See examples/skills/README.md for the authoring guide
and copy-paste starters.

Project memory

Drop a BANDIT.md, CLAUDE.md, or AGENTS.md at the workspace root — the
agent auto-loads it into the system prompt so it learns your conventions
once, not every turn. All three names work; AGENTS.md is the OpenAI Codex
/ GitHub Copilot convention and loads alongside the others if present.

The format that works best splits into two parts — behavior (how the agent
should act in this repo, inspired by Karpathy's CLAUDE.md) and project facts
(repo-specific things you'd otherwise re-explain every session):

## Behavior

### Before editing
- Read the file first. Don't apply_edit blind.
- For changes larger than ~10 lines, prefer `replace_range` with line numbers
  over `apply_edit`'s exact-match string.

### When changing existing code
- Don't refactor adjacent code that wasn't broken.
- Match existing style, even if you'd do it differently.

### When finishing a task
- Run the relevant verification (`test_run` / `run_command lint`).
- Don't claim done until verification passed.

## Project Facts
- This repo uses pnpm, not npm.
- Integration tests must hit a real database — no mocks.
- Prefer small focused PRs. Don't batch unrelated changes.

The repo root BANDIT.md is the reference implementation.

Use /remember <fact> inside the REPL to append a bullet from any session.
/memory shows everything loaded on the current turn. /init scaffolds a
fresh BANDIT.md in this two-section shape by reading the repo.

Topic memory (lazy-loaded)

For facts that only matter on some tasks — a migration playbook, an API
quirk, a deprecated module's history — drop a MEMORY.md index at the
repo root that points at files under memory/:

# Project memory — topic index

- [Auth conventions](memory/auth.md) — when editing src/auth/*
- [Migration playbook](memory/migrations.md) — when adding DB migrations
- [CLI ink refactor](memory/cli-ink-refactor.md) — when changing the CLI input layer

The index (capped at 4 KB) loads into every system prompt; the linked files
do NOT. The agent reads the hook on each entry, and when one matches the
current task it calls read_memory(name="<slug>") to pull in the full
file (capped at 32 KB).

When to put a fact in BANDIT.md vs memory/<slug>.md:

  • BANDIT.md — true on every turn (style rules, repo layout, default commands).
  • memory/<slug>.md — only relevant to some tasks (deep history, area-specific
    playbooks, things that would bloat the system prompt for every other task).

This repo's own BANDIT.md is the reference implementation of
the always-loaded half.

File mentions

Prefix a path with @ in any prompt and the CLI inlines the file contents before the model sees it:

› why is @src/auth/login.ts throwing on line 42?

Up to 8 mentions per prompt, 64 KB each, auto-truncated.

Session persistence

Every REPL session is saved as JSONL under ~/.bandit/sessions/. Resume anytime:

bandit --resume 20260419-124501-ab3c
# or inside the REPL:
› /session list
› /session resume 20260419-124501-ab3c

In-agent todos

The agent can call todo_write to track multi-step work. Useful for longer tasks — the model sees its own plan and checks off steps as it finishes them.

Web fetch and search

web_fetch <url> pulls docs, RFCs, release notes directly into the conversation.
HTML is stripped to readable text, 16 KB cap, no auth. SSRF-guarded — refuses
to hit RFC1918, loopback, or cloud-metadata addresses unless
BANDIT_ALLOW_PRIVATE_WEB_FETCH=1 is set.

web_search <query> returns ranked snippets via Tavily (free tier, set
TAVILY_API_KEY). The model gets titles, URLs, and short content blurbs — it can
follow up with web_fetch on a result when it needs the full page.

Slash commands (REPL)

Command Does
/help List slash commands
/doctor Check setup, provider, model profile, and next actions
/clear Reset conversation (keeps session id)
/model <name> Switch model mid-session
/skills List loaded skills
/session list / resume <id> / new Manage sessions
/memory Show auto-loaded BANDIT.md / CLAUDE.md
/remember <fact> Append a bullet to BANDIT.md so the next session knows it
/trace, /trace list, /trace failed Inspect recent turn telemetry and failed runs from workspace/global .bandit/turns; the IDE opens the Trace Logs viewer
/insights Generate a local HTML report that synthesizes sessions + turn logs into cross-repo wins, tool stats, and friction
/exit Quit

Unified-diff approval gate

Every file edit (write_file, apply_edit, replace_range, apply_patch) goes through the approval gate. The CLI and extension show a compact diff before touching disk:

╭── edit: src/auth/login.ts
│   function login(user, pass) {
│ - return checkPassword(user, pass);
│ + if (!user || !pass) throw new Error('missing creds');
│ + return await checkPassword(user, pass);
│   }
│    (+2 -1)
╰── apply? [y/N]

Each choice shows the exact rule it stores, so a grant never covers more than the prompt said:

│ 1 allow once   2 allow turn   3 allow session   4 always allow   5 deny
│ grants: any `git status …` command — until this session ends
╰── ↑↓←→ or 1–6 to choose · enter confirms · esc cancels

Approving git status grants git status …, not every shell command. allow turn covers a
batch of similar calls until the agent finishes the current turn, then expires.

Auto mode

/auto on in the CLI, bandit --auto, or "permissions": { "mode": "auto" } in
.bandit/settings.json lets routine work run without prompting — reading, editing files
inside the project, running builds and tests.

Auto mode always asks before anything destructive, and that floor cannot be configured
away — not by a settings file, and not by a saved allow rule that would otherwise cover the
call:

Always asks Examples
Deleting files delete_file, rm
Writing outside the project ../../etc/hosts, ~/.zshrc
Rewriting git history git push --force, git reset --hard, git clean -fd
Machine-wide installs npm i -g, brew install, pipx install, npm publish
Credential files .env, ~/.ssh/*, ~/.aws/credentials
Sending data out curl -d, scp, rsync host:, nc
Irreversible service calls MCP sendEmail, trashMessage, revokeAccess

/permissions shows the mode, your active grants, and everything auto mode ran without
asking. For unattended CI where nothing should prompt, set
BANDIT_DANGEROUSLY_APPROVE_ALL=1 — it has no floor, which is why it is named that.

For large files, read_file paginates with line numbers and a shown_hash. The agent can call replace_range with start_line, end_line, replacement content, and optional expected_hash copied from read_file to land a method/component-sized refactor without resending the whole file or a giant exact-match string.

Hooks

Drop .bandit/settings.json in any project:

{
  "hooks": {
    "PreToolUse":  [{ "match": "run_command", "command": "./scripts/guard.sh {{name}} {{primary}}" }],
    "PostToolUse": [{ "match": ".*", "command": "echo '{{name}} took {{duration}}ms' >> .bandit/audit.log" }],
    "Stop":        [{ "command": "osascript -e 'display notification \"bandit done\"'" }]
  }
}
  • Hooks are shell commands. They run with .bandit/ as the cwd.
  • {{name}}, {{primary}}, {{duration}} are expanded at call time.
  • A non-zero exit from a PreToolUse hook prints a warning (but doesn't yet abort — planned).

Insights — local-only activity report

/insights (CLI) or Bandit Stealth: Open Insights (IDE) generates a single self-contained HTML file from your local session and turn-log data — no server, no external resources, no telemetry, opens in any browser, sharable as one file. The report synthesizes how you and the agent have actually been working over time, broken into panels:

  • At a glance — sessions, user prompts, token estimate, total tool calls, longest / current streak, peak day, days since first run, commits made
  • Your story (optional AI summary, gated by insightsAiConsent) — three short narrative cards: What you shipped · How you work · Where Bandit got in your way. Cloud users see this when the cloud LLM consent is on; local Ollama users see it when a local model is configured. The framing prompt attributes every friction point to Bandit, never the user — the goal is empathetic product feedback, not a postmortem of the human
  • Recent wins (local synthesis, no AI) — cross-repo arc detection from raw session text
  • How you felt · Bigger arcs · Largest work highlights — extracted themes and longest investigations
  • Accomplishments — files touched, edits + writes applied, git operations, subagents spawned, languages touched, most-touched files
  • Activity (last 14 days) — inline SVG bar chart of prompt volume per day
  • Tool usage — top N tools by call count with success/error split
  • Productivity tips · Recent sessions · Top error patterns
  • Help shape Bandit — one-click mailto: button that ships the HTML to [email protected] only if you click it

Data sources are all local: ~/.bandit/sessions/*.jsonl (every REPL session) + <cwd>/.bandit/turns/*.jsonl (per-turn telemetry for the current workspace). The report writes to ~/.bandit/insights.html by default. The AI summary is the only path that touches a model — disable it with insightsAiConsent: deny in ~/.bandit/config.json (or the equivalent setting in the IDE) for a fully offline report.

Native tool calling (when the model supports it)

The runtime checks each model's built-in capability profile first (bandit-logic, the Qwen 3.6 family, Qwen 2.5 / 2.5-Coder, Llama 3.1+, Devstral, the bandit-core ≥12B fine-tunes) and routes tool schemas through Ollama's tools: field instead of the XML system-prompt block. Saves ~1.5–3 KB per turn and removes a whole class of "the model forgot the envelope" failures. Gemma 3 / Gemma 4 and other text-only families fall back to the XML protocol with the full mitigation stack armed. As of v1.7.340, the dispatch is gated on the built-in profile so an Ollama auto-detect glitch can't silently downgrade a tool-calling model — and the same retry ladder (3 native attempts → text channel switch → 3 text attempts → outer-text-retry → 3 more attempts → final-anchor re-prompt) protects every native-tools turn from transient gateway blips.

Model Context Protocol — both directions

Bandit speaks MCP as a client and a server. Drop any MCP server (filesystem, GitHub, Slack, GitLab, Gmail, Postgres, your own) into ~/.bandit/mcp-servers.json or <workspace>/.bandit/mcp-servers.json and its tools surface as <server>.<tool> alongside the native ones. Stdio (command/args/env) and remote Streamable HTTP (url + auth, including auth: "bandit" for the hosted gateway) both supported as of v1.7.333. First spawn of any server requires user approval; "Always allow" persists a fingerprint to ~/.bandit/mcp-trust.json. Connector wizards in the IDE Settings → Connections for GitHub/Slack/GitLab/Gmail/Custom; CLI parity via /mcp add github <token> etc.

bandit mcp serve turns the CLI into an MCP server exposing the native tool surface over stdio — any MCP client (Claude Desktop, Cursor, Cline, Continue) can drive Bandit's tools through the standard JSON-RPC envelope. --read-only strips write/exec tools for view-only clients.

Voice — pluggable providers, independent of chat

Speech-to-text and text-to-speech are configured separately from the chat provider. Run Ollama locally for chat and pair it with whichever voice setup matches your privacy / cost / latency preference. STT: Bandit cloud, OpenAI-compatible Whisper (faster-whisper-server, whisper.cpp HTTP, OpenAI, LiteLLM), or any custom multipart endpoint. TTS: Bandit cloud, OpenAI (tts-1 / tts-1-hd), ElevenLabs, a local Piper HTTP server, or any custom URL. Local-only setups (Ollama + self-hosted Whisper + Piper) work without a cloud account.

Mid-turn queue + background subagents

Type a follow-up while the agent is still working and it queues (queued: N · sends after this turn in the status row); Esc cancels the run and clears the queue. The agent can spawn background subagents for long investigations and keep iterating in the foreground — when a subagent finishes, its synopsis injects into the parent's next iteration instead of forcing a check_task poll loop (v1.7.336+). Inspect with /tasks, cancel with /tasks cancel <id>. Stop cascades to all in-flight subagents (v1.7.338).

UI/UX polish

  • ANSI color, box-drawn headers, "shifty eyes" spinner with a breathing glow on truecolor terminals
  • Clean → tool-name arg tool-call lines with ✦ using skill: … markers
  • Live plan dock — todo_write updates commit to scrollback as the plan evolves
  • Per-turn timer + live tok/s on the status line, terminal title reflects the active prompt
  • Colored unified diff viewer in the approval gate
  • Respects NO_COLOR / BANDIT_NO_COLOR / non-TTY stdout

Model support

Built-in capability profiles ship for the families listed below. Anything else gets auto-introspected through Ollama's /api/show and matched to a behavior profile by name pattern. The canonical inventory lives in packages/stealth-core-runtime/src/runtime/modelCapabilities.ts.

Recommended starting points — the proven set, aligned with the models the Ollama ecosystem promotes for agent work:

Your hardware Pick
Any machine, no GPU kimi-k2.6:cloud or kimi-k2.7-code:cloud (Ollama Cloud — see below)
24–48 GB GPU / unified memory qwen3.6:27b (best local agent pick)
16–32 GB gemma4:26b
Laptop / smaller gemma4:12b or gemma4:e4b
Apple silicon qwen3.6:27b-mlx, gemma4:26b-mlx (MLX builds resolve to the same profiles)
Model Size Native tool calling Vision Context Best for
bandit-logic (Qwen 3.6 27B, hosted) — ✓ ✓ 256K Cloud default — agent-tuned, no local install, thinking mode
qwen3.6:27b ~17 GB ✓ ✓ 256K Best local pick — same family as bandit-logic, M-series 48GB+ or H100-class
qwen3.6:35b ~24 GB ✓ ✓ 256K Larger Qwen 3.6; tends to stall in reasoning-only output, prefer 27B for agent loops
kimi-k2* (Ollama Cloud) — ✓ varies 256K Frontier agentic-coding family (1T MoE / 32B active). kimi-k2 / kimi-k2-thinking are text-only; kimi-k2.5 / :2.6 / :2.7-code are multimodal. Runs on Ollama Cloud, no local GPU — see Ollama Cloud
gemma4:31b ~19 GB text-fallback ✓ 128K RTX 5090 / GPU node — high-fidelity local
gemma4:26b ~17 GB text-fallback ✓ 128K Mac 32GB+ alternative when Qwen 3.6 is too heavy
gemma4:e4b ~3 GB text-fallback ✓ 16K Lightweight laptop pick — punches above its weight on tool sequencing
gemma4:e2b ~2 GB text-fallback ✓ 16K Smallest "effective" Gemma 4 tune
gemma3:12b / gemma3:27b ~9 / 17 GB text-fallback ✓ 32K Older Gemma 3 family — still works, gets less attention
qwen2.5-coder:14b / :32b / :72b ~9 / 20 / 45 GB ✓ — 128K Code-completion tune — good on concrete tasks, weaker as autonomous agent
qwen2.5:7b / :32b / :72b varies ✓ — 128K Qwen 2.5 base — text only, reliable tool emitter
qwen2.5vl / qwen2-vl varies ✓ ✓ 32–128K Qwen vision-language variants
llama3.1 varies ✓ — 128K Meta's Llama 3.1 — text only
llama3.2-vision varies text-fallback ✓ 128K Llama 3.2 multimodal
llama3 varies text-fallback — 8K Original Llama 3 — narrow context, kept for compatibility
bandit-core:12b / :27b / :31b varies ✓ optional 32K–128K Our own Gemma-3-derived fine-tunes (12B / 27B / 31B)
bandit-core-1 / bandit-core-2 (hosted) — varies varies 128K Hosted bandit fine-tunes — -1 for lightweight, -2 for RunPod 70B (text-only)
deepseek-coder:6.7b ~4 GB text-fallback — 16K Small, fast code model
llava varies text-fallback ✓ 4K Dedicated vision model (optional pull)
any other Ollama model — auto-detected via /api/show auto-detected auto-detected Drop-in via BANDIT_MODEL

Primary development and test targets are bandit-logic (cloud) and the gemma4 / qwen3.6 local families. Models we don't recommend for autonomous agent work — gpt-oss:120b (post-trained for OpenAI's harmony tool-call format, narrates without emitting tool calls), and code-completion tunes like qwen2.5-coder:32b on ambiguous prompts (asks for paths instead of probing). See apps/bandit-stealth/README.md for the full caveats.

Model behavior profiles now sit beside capability detection. /profile explains the active model's harness strategy — native vs text tools, fallback policy, safe context/output budget, thinking default, max tool parallelism, and reliability guardrails. Both the CLI and extension load .bandit/model-profiles.json, and the tool loop now uses those profile values to choose native-vs-text tools, serialize risky edit batches, cap parallel calls, and decide whether native failures should fall back to text tools.

When native tools are active, earlier tool calls and their results are replayed to the model in the provider's own message format (tool_calls plus role: "tool" messages) rather than as the loop's <tool_call> text; local models otherwise copy the text form, which Ollama's tool parsers swallow or reject. This is on for direct Ollama. A profile can set it per model family ("protocol": { "toolHistory": "text" } in .bandit/model-profiles.json), and BANDIT_TOOL_HISTORY=text (or native) forces one form for every model and provider. The Bandit gateway and OpenAI-compatible servers stay on the text form unless forced.

Ollama Cloud

Want a frontier model without the GPU? Ollama Cloud runs large
models — like Kimi K2 (1T MoE, 256K context, built for agentic coding) and gpt-oss:120b —
on Ollama's hosted infrastructure, accessed through the same API Bandit already speaks. Your
prompts run in the cloud; your repo still stays on your machine except for the context the model
needs (same as any hosted model).

Easiest path — local daemon (recommended):

# 1. Sign in to Ollama once (opens a browser)
ollama signin

# 2. Pull a cloud model — the cloud tag offloads to Ollama Cloud
ollama pull kimi-k2.7-code:cloud      # multimodal coding agent
#   or:  ollama pull kimi-k2:1t-cloud  # text-only base K2

# 3. Use it in Bandit like any local model
bandit --model kimi-k2.7-code:cloud
#   or inside the REPL:  /model kimi-k2.7-code:cloud

That's it — Bandit talks to your local Ollama daemon (localhost:11434), which transparently
offloads cloud-tagged models. Bandit ships tuned profiles for the whole Kimi family (native tool
calling, 256K context, vision on the multimodal k2.5 / k2.6 / k2.7-code variants), and both
cloud tag shapes — :1t-cloud and :cloud — resolve automatically.

Direct cloud API (no local daemon): point Bandit straight at ollama.com with an
API key:

// ~/.bandit/config.json
{
  "provider": "ollama",
  "model": "kimi-k2:1t",
  "ollama": {
    "url": "https://ollama.com",
    "headers": { "Authorization": "Bearer <your-ollama-api-key>" }
  }
}

In the VS Code / Cursor extension, set the Ollama base URL to https://ollama.com and paste
your key into the Ollama auth token field (stored in the OS secret store, sent as
Authorization: Bearer).

If a cloud model returns 401/403, you're not signed in or the key is missing/expired —
Bandit surfaces a hint pointing you at ollama signin. The model itself is fine.


Benchmarks

Two reproducible runs, same harness — a hosted model on a medium repo, and a frontier open model self-evaluating this monorepo. Not a leaderboard; just honest traces you can re-run.

A hosted model on a medium repo

bandit-logic (Qwen 3.6 27B via the hosted gateway) given a fresh "deep dive this repo and tell me what it does at a high level" prompt against a real React + TypeScript + Vite project (the author's personal portfolio site — 11 projects, ~30 files, no inlined @-mentions).

Metric Value
Wall-clock turn duration 28.25 s
LLM iterations 5 (4 tool-call rounds + 1 final answer)
Tool calls 12 (read_file ×10, ls ×1, list_files ×1)
Final answer length 2,022 chars (~500 tokens)
Per-iteration LLM time 5.05 s → 2.95 s → 2.56 s → 4.85 s → 12.81 s (final answer)
Provider bandit cloud (provider=bandit, model=bandit-logic)
CLI version 1.7.348
Trace Portfolio/.bandit/turns/turn-2026-05-30T21-26-52-368Z-afyl.jsonl

The shape of the run is what we want out of the harness: the model probes (ls + package.json), narrows (README + src/** listing), reads the entry points (App.tsx, main.tsx, index.html), pulls in the data files (projects.ts, experience.ts, skills.ts) and two representative section components, then commits to a final answer instead of padding with one more probe round. No reasoning-only stalls, no retry slots fired, no native-fallback re-prompts.

Hardware: the cloud provider serves bandit-logic from our own GPU pool; the client side ran on an M4 Max MacBook Pro. For local model comparisons, our reference rigs are an M4 Max (qwen3.6:27b ~ 17 GB resident, ~ 30 tok/s) and an RTX 5090 node (gemma4:31b ~ 19 GB resident, ~ 80 tok/s). Numbers will vary on different hardware; the run above is one data point, not a leaderboard.

Reproduce it yourself:

cd /path/to/any/medium-sized/repo
BANDIT_PROVIDER=bandit BANDIT_MODEL=bandit-logic \
  bandit "deep dive this repo and tell me what it does at a high level"
# Then read .bandit/turns/turn-*.jsonl for the full event timeline.

A frontier open model on the framework's own monorepo

A second run, same harness, harder target — a self-eval. Kimi K2 (kimi-k2.7-code:cloud — a 1-trillion-parameter MoE, ~32B active, served through Ollama Cloud) given a deliberately two-part prompt against this repository, the Bandit monorepo itself (622 TypeScript files across 6 packages and 4 apps — an order of magnitude larger than the portfolio above):

deep dive this repo and tell me what it does at a high level — and what could be holding this repo back from being even better

Metric Value
Wall-clock turn duration 64.2 s
LLM iterations 14 (13 tool-call rounds + a forced final synthesis)
Tool calls 60, batched across the 13 tool rounds (~4.6/round) — read_file ×44, ls ×8, search_code ×5, list_files ×2, run_command ×1 (git log --oneline -20)
Final answer length 6,800 chars (~1,700 tokens) — both halves of the prompt answered
Per-iteration LLM time 2.1 s median, 20.6 s on the closing synthesis round
Provider ollama, the local daemon proxying to Ollama Cloud (model=kimi-k2.7-code:cloud)
Bandit version 1.7.373 (VS Code extension)
Trace .bandit/turns/turn-2026-06-18T04-30-23-330Z-qo2s.jsonl

What stands out is the tool batching: rather than one read per round, Kimi fires four-to-six file reads or searches in parallel each iteration — one round reads six files at once, another runs five search_code queries in a single pass. The trajectory is what you'd want from a senior engineer dropped into an unfamiliar repo: probe (ls), broaden, read the entry points deeply, run targeted search_code for the cross-cutting concerns, check git log for recent direction, then synthesize. The write-up correctly named the layered package architecture and answered the critique half — flagging a real structural smell on its own: the agent-adapters/{provider,node,vscode,web,github} packages as near-identical empty shells, paying monorepo overhead for little host-specific code.

One caveat, reported honestly: this run hit the configured iteration ceiling (hitLimit: true) and was forced to commit to its answer after 13 rounds of exploration rather than stopping on its own. On a repo this size with a two-part prompt, that's the signal to raise BANDIT_MAX_ITERATIONS (or the extension's iteration setting) for monorepo-scale deep dives — the answer was complete, but Kimi clearly had more it wanted to read.

Reproduce it (Kimi cloud requires a paid Ollama plan — swap in a free local model like qwen3.6:27b to exercise the same loop):

ollama signin                      # one-time: links your Ollama Cloud account
ollama pull kimi-k2.7-code:cloud
BANDIT_PROVIDER=ollama BANDIT_MODEL=kimi-k2.7-code:cloud BANDIT_MAX_ITERATIONS=30 \
  bandit "deep dive this repo and tell me what it does at a high level — and what could be holding it back"

CLI environment

Var Default Description
BANDIT_PROVIDER ollama ollama or bandit
BANDIT_MODEL gemma4:e4b Model ID
BANDIT_API_KEY — Required when BANDIT_PROVIDER=bandit
BANDIT_API_URL https://api.burtson.ai/completions Completions / Bandit Cloud API endpoint
BANDIT_AUTH_URL https://auth.burtson.ai OIDC issuer / device-key auth API — point this at your own auth service when self-hosting
OLLAMA_URL http://localhost:11434 Ollama endpoint
BANDIT_MAX_ITERATIONS 20 Tool-use loop cap
BANDIT_PERMISSION_MODE ask auto runs routine calls unprompted (destructive ones still ask); dangerous disables every prompt
BANDIT_DANGEROUSLY_APPROVE_ALL 0 1 to approve everything, with no destructive-action floor — CI and sandboxes
BANDIT_AUTO_APPROVE 0 Deprecated alias for BANDIT_DANGEROUSLY_APPROVE_ALL
TAVILY_API_KEY — Enables the web_search tool (free tier at tavily.com)
BANDIT_ALLOW_PRIVATE_WEB_FETCH 0 1 to allow web_fetch against RFC1918/loopback/link-local hosts
BANDIT_NO_SECRET_REDACTION 0 1 to disable automatic secret redaction in tool output (debug only)
NO_COLOR — Disable ANSI colors

Architecture

User prompt
  ↓
SkillRegistry.resolveActiveSkills(prompt)
  ↓
ToolUseLoop (observe → act → replan)
  ↓
  ├─ ToolRegistry (XML tool defs in system prompt)
  │     ├─ Built-in tools (read, write, search, run, git, …)
  │     ├─ CLI tools (todo_write, remember, web_fetch, web_search)
  │     └─ Custom skills from .bandit/skills/*.md (or legacy *.json)
  │
  ├─ LLM Provider
  │     ├─ Ollama (/api/chat, streaming NDJSON)
  │     └─ Bandit Cloud (optional hosted inference)
  │
  ├─ LanguageAdapters (pre-write validation)
  │     └─ TypeScript, Python, JSON, C# (more via skills)
  │
  └─ Host-specific bindings
        ├─ bandit-stealth (VS Code / Cursor) — vscode API, webview UI
        └─ bandit-cli (terminal) — readline REPL, ANSI, sessions

Design rules:

  1. Local models are first-class citizens, not a fallback.
  2. One runtime, multiple hosts. Skills / memory / hooks are host-agnostic.
  3. Language adapters validate before write. Invalid content never reaches disk.
  4. Skills activate based on intent. The model decides when to plan vs. act directly.

What is still maturing

To keep expectations honest — areas still on the roadmap:

  • Plan mode (in the CLI — the VS Code extension has a variant)
  • Status-line / full TUI polish
  • Lossless trace replay for every native-tool run

See ROADMAP.md for what's planned.


Custom skills

Ask the agent to build one: "create a skill that runs my linter" — it writes .bandit/skills/linter.md (markdown with YAML frontmatter is the current shape; legacy *.json still loads) and next prompt it's live.

Or author by hand. The manifest format is documented in examples/skills/README.md.


Bandit Cloud

For teams that want hosted infrastructure — workspace indexing, Qdrant semantic search, team dashboards, GPU inference, PR automation — see Bandit Cloud.

Contributing tests

The agent runtime (@burtson-labs/agent-core) is the most heavily tested package. New behaviors should land with a contract test, and recurring failure modes worth defending against should land with a real-trace replay fixture.

  • Run everything: pnpm test (what CI runs on your PR). One package: pnpm --filter @burtson-labs/agent-core test
  • What's pinned: see packages/agent-core/README.md for the full coverage map (constructor options, every detector cluster, cancellation, compaction, replay).
  • Adding a regression fixture from a real failure trace: packages/agent-core/test/fixtures/turns/README.md walks through the steps — picking a .bandit/turns/*.jsonl, replay-completeness limits, naming, and what to assert.

Contributing

Bug fixes, local-model improvements, new skills, and docs PRs are all welcome. See CONTRIBUTING.md for the guide — repo layout, build commands, what we accept without prior discussion, and what to flag in an issue first.

Security

Email [email protected] for security reports — don't open public GitHub issues. Full disclosure policy in SECURITY.md.

Issues & feature requests

Open an issue for bugs and feature ideas, or email [email protected] if you'd rather not go through the public tracker.

License

Apache License 2.0 — Copyright 2026 Burtson Labs. See NOTICE for attribution.

In Memory of Ryan Richard Burres

This project is dedicated to my little brother, Ryan.

You are under no obligation under the Apache 2.0 license, but if this software has been useful to you, please consider a donation to the American Foundation for Suicide Prevention — Missouri Chapter.

AFSP funds research, education, advocacy, and survivor support — the work of preventing what took Ryan from us, and of helping the families left behind.

Yorumlar (0)

Sonuc bulunamadi