Skip to content
rushikeshg25Public

About

cli coding Harness

Topics

Resources

Security policy

Stars

9 stars

Watchers

0 watching

Forks

Latest commit

 

History

183 Commits

Folders and files

Repository files navigation

Cool-Code: a fast, native CLI coding agent

An intelligent command-line coding agent - describe what you want, and it reads, plans, and edits your codebase using live tools. Similar in spirit to Claude Code and Gemini CLI, now rewritten in Go with a Bubble Tea TUI and native provider tool-calling.

Rewritten in Go. Cool-Code was previously a TypeScript/Node CLI. It is now a single statically-linked Go binary - no node_modules, faster start-up, real goroutine concurrency, and a polished Charm-stack terminal UI. The agent uses each provider's native function-calling API (Anthropic, OpenAI, Gemini) instead of parsing tool calls out of free text.

Overview

Cool-Code combines large language models with a comprehensive set of development tools for an interactive development experience. It works with multiple model providers (Google, OpenAI, Anthropic) and finds context live through search and read tools - no vector database required.

Features

  • Multiple model providers - Google, OpenAI, or Anthropic. Connect one with /connect (keys stored in ~/.coolcode/credentials.json) or export the matching env var; the provider is inferred from the model id.
  • Native tool-calling with streaming - structured function-calling against each provider's API. Transport responses stream internally, while only completed final answers enter the transcript.
  • Explore subagents - the agent can fan out several read-only spawn_agent explorers concurrently to investigate independent areas of a codebase, with live per-agent status in the TUI.
  • Concurrent tools + cancellation - independent read-only tool calls run in parallel; Esc or Ctrl+C cancels a running turn without quitting.
  • Two-pane TUI - a Bubble Tea terminal UI with a persistent header and, above 100 columns and while there is work to show, a sidebar carrying the live task list and running subagents. Context is reported as a percentage of the model's window, or as a token count when that window is unknown. Syntax-highlighted fenced code, multiline input (Alt+Enter), mouse-wheel scrolling, input-history recall, colored diff previews for edits, a / slash-command palette with Tab autocomplete, and Shift+Tab to switch modes. Errors and failed tool calls are visually distinct from ordinary output.
  • Three agent modes - Plan (read-only investigation → detailed plan), Agent (autonomous execution), Ask (read-only Q&A). After Plan mode produces a plan, choose Start implementation to jump straight into Agent mode.
  • Project memory (COOLCODE.md) - persistent project instructions loaded into every prompt.
  • Skills - discoverable, model-invoked instruction modules under .coolcode/skills/ (compatible with Claude Code skills).
  • Web access - web_fetch and web_search tools.
  • Streaming output - assistant text appears as it arrives, buffered to line boundaries so secret redaction still sees complete lines. Scratch prose emitted before a tool call is dropped in favour of the tool lines that follow.
  • Cost tracking - a running session spend in the status bar for models with a published rate, plus /cost. Unknown models and custom endpoints report nothing rather than a guess.
  • Session persistence - conversations saved to ~/.coolcode/sessions/ (including on quit and cancel); resume with --continue / --resume and the prior conversation reappears in the transcript.
  • Reliability - automatic retry with backoff on transient API errors, and real token usage from provider responses in the status bar.
  • Task tracking, input queuing, safety guardrails - real-time checklists, mid-turn message queuing, and path/read/danger protections.

Install

Go install (recommended)

go install github.com/rushikeshg25/cool-code@latest

This places a cool-code binary in your $GOBIN (usually ~/go/bin - make sure it's on your PATH).

Build from source

git clone https://github.com/rushikeshg25/cool-code.git
cd cool-code
make build      # produces ./cool-code
# or: go build -o cool-code .

Connect a provider

The easiest way: start cool-code and run /connect - pick a provider, paste your API key, and it is stored in ~/.coolcode/credentials.json (mode 0600). The chosen provider and default model are saved in ~/.coolcode/settings.json. Repository configuration cannot override provider identity, endpoints, credential selection, guardrails, or confirmation policy.

Env vars keep working as a fallback:

export GOOGLE_GENERATIVE_AI_API_KEY=your_api_key_here   # Gemini (default)
# export OPENAI_API_KEY=your_api_key_here               # OpenAI
# export ANTHROPIC_API_KEY=your_api_key_here            # Anthropic

OpenAI-compatible gateways and CLI proxies must be configured in trusted global settings. The CLI routes security-sensitive keys to ~/.coolcode/settings.json automatically:

cool-code config set llm.provider openai
cool-code config set llm.model gpt-5.6-sol
cool-code config set llm.baseUrl http://localhost:8317/v1
cool-code config set llm.apiKeyEnv CLIPROXY_API_KEY
export CLIPROXY_API_KEY=your_proxy_key

COOLCODE_API_BASE_URL and COOLCODE_API_KEY provide equivalent process-environment overrides. Custom endpoints require an explicit proxy key; first-party provider credentials are never forwarded to them. Remote endpoints require HTTPS, while HTTP is accepted only for loopback proxies. A trusted LAN proxy can be explicitly enabled with cool-code config set llm.allowInsecureHttp true; this weakens transport security and should not be used across untrusted networks.

A regular, non-symlink .env file may supply variables ending in _API_KEY; point llm.apiKeyEnv at one to use it. COOLCODE_API_KEY is not read from .env - it takes effect with no global setting, so a cloned repository could otherwise substitute the credential your requests are billed and logged against. Export it in your shell instead. Endpoint and process-control variables in project .env files are ignored.

Usage

Run inside your project directory:

cool-code

Command-line options

cool-code --yes               # start without the init prompt
cool-code --no-init           # exit without initializing
cool-code --allow-dangerous   # skip danger confirmations
cool-code --copy              # copy final responses to the clipboard
cool-code --continue          # resume the most recent session for this dir
cool-code --resume <id>       # resume a specific saved session
cool-code --effort high       # set reasoning effort for this run
cool-code --mode plan         # start in plan, agent, or ask mode

Non-interactive mode

cool-code --print "list the exported functions in internal/tools"
echo "summarize the recent changes" | cool-code --print
cool-code --print --json "what does the path jail do?"   # structured output
cool-code --print --verbose "run the tests"              # tool activity on stderr

--print runs a single turn without the TUI and writes the result to stdout, so the agent can be scripted or run in CI. The prompt comes from an argument or from piped stdin. Progress goes to stderr, keeping stdout pipeable. Confirmations are refused rather than auto-approved, since there is nobody to ask; pass --allow-dangerous to opt in.

Subcommands

cool-code scan                       # summarize project structure
cool-code scan --refresh --json      # refresh cache, JSON output
cool-code task "Add user auth"       # one-shot structured plan
cool-code config get llm.model
cool-code config set llm.model "gemini-2.5-flash"
cool-code config set llm.maxTokens 2048
cool-code skill install ./path/to/skill
cool-code skill install https://github.com/user/some-skill.git --global

Agent modes

  1. Plan - investigates with read-only tools and produces a detailed, file-level plan plus a task breakdown, without touching your code. When ready, offers Start implementation or Keep planning.
  2. Agent (default) - executes tasks autonomously, applying edits and running commands.
  3. Ask - read-only mode; mutating tools (edit, new file, shell, rename, replace) are blocked.

Switch mid-session with Shift+Tab (cycles Plan → Agent → Ask) or /mode plan|agent|ask.

Interactive commands

Type / to open the command palette; press Tab to complete the highlighted command.

  • /help - show available commands
  • /mode - show or switch mode
  • /effort - show or set reasoning effort (minimal|low|medium|high|xhigh)
  • /pin / /unpin - pin a file's contents into context (or list/unpin)
  • /context - preview context, pinned files, and token usage
  • /compact - summarize the conversation and free up context
  • /model - show or switch the model (e.g. /model claude-sonnet-4-5)
  • /cost - show token usage and estimated spend for this session
  • /sessions - list saved sessions for this directory
  • /install-skill - install a skill from a local path or git URL (add --global)
  • /clear - clear the screen
  • /exit - exit

You can also type new messages while the agent is working - they're queued and picked up after the current step.

Model providers

The provider is inferred from the model id when llm.provider is unset:

  • gpt-*, o1*, o3* → OpenAI
  • claude-* → Anthropic
  • everything else (e.g. gemini-*) → Google
cool-code config set llm.model "gpt-4o"           # inferred as OpenAI
cool-code config set llm.model "claude-sonnet-5"  # inferred as Anthropic
cool-code config set llm.provider "openai"        # or set it explicitly

If the required key is missing, the CLI prints provider-specific setup guidance and exits.

Project memory & skills

Create a COOLCODE.md in your project root for persistent, project-specific instructions (loaded every turn; global fallback ~/.coolcode/COOLCODE.md).

Skills are reusable instruction modules under .coolcode/skills/<name>/SKILL.md (project) or ~/.coolcode/skills/<name>/SKILL.md (global), each with optional name/description frontmatter. The agent sees a catalog and calls the use_skill tool to load one on demand. Install skills from a local path or git URL with cool-code skill install or /install-skill.

Configuration (.coolcode.json)

{
  "llm": {
    "temperature": 0.2,
    "maxTokens": 2048,
    "contextWindow": 200000
  },
  "features": {
    "scanCache": true,
    "fileTreeMaxDepth": 4,
    "maxContextTokens": 120000,
    "compactAfter": 40
  }
}

maxContextTokens bounds how much conversation is selected for each request. It is not the model's context window, and a request can exceed it, since the system prompt and pinned files sit outside it. compactAfter is the message count at which the conversation is summarized and older history is folded into that summary, keeping the 20 most recent messages verbatim; set it to 0 to disable compaction. Compaction is reported in the transcript when it happens, and /compact runs it on demand.

Provider identity and security-sensitive settings (llm.model, llm.provider, llm.baseUrl, llm.apiKeyEnv, llm.allowInsecureHttp, features.allowDangerous, features.confirmEdits) are global-only. Set them with cool-code config set; repository-controlled values are ignored, and the CLI lists any it ignored at startup.

llm.contextWindow declares the model's context window, used only to report how full the context is. It is needed when the model id is not one cool-code recognises, which includes most proxies and gateways; without it the status bar shows an absolute token count instead of a percentage rather than measuring against a guess.

guardrails.blockReadPatterns is the one exception: a project file may add patterns, since that can only narrow what the agent may read. It can never remove one.

Safety

  • Canonical path jail - reads, searches, writes, pins, and added directories are restricted to explicitly granted roots. Paths are resolved component by component, the way the kernel does, so .. after a symlink cannot escape, and tools act on the resolved path rather than the string they were given.
  • Protected paths - tools cannot write inside .git or .coolcode, where a hook or config would become code execution.
  • Read guardrails - blockReadPatterns applies to reads, edits, searches, pins, context trees, git diffs, and subagents. .gitignore is respected by trees and searches.
  • Trusted endpoints - repositories cannot select proxy hosts, credential variables, guardrails, or bypass flags. Remote proxies require HTTPS and cross-origin redirects are disabled.
  • Command isolation - every arbitrary shell command and project-code execution (run_tests, lint_fix, format_file, add_script) requires confirmation by default. Commands assembled from model- or repository-controlled values run as argv with no shell, so a crafted search pattern or filename cannot inject. Child processes receive a small environment allowlist without API keys, tokens, cookies, or cloud credentials. Shell, test, and lint commands whose executable text would be hidden by credential redaction are refused.
  • Network isolation - web fetches require HTTPS and reject loopback, private, carrier-grade NAT, reserved, link-local, multicast, NAT64, and cloud metadata addresses, including after redirects and DNS resolution.
  • Data-loss prevention - common credentials and sensitive environment values are redacted before provider egress, terminal rendering, and session persistence, in subagents as well as the main loop. Provider errors never include endpoint URLs, and any provider message they quote is redacted and truncated.
  • Terminal integrity - escape sequences are stripped from model and tool output. Command approvals show the complete command with control characters visibly escaped and long lines available by scrolling.
  • Untrusted content - COOLCODE.md, skills, and fetched pages enter the prompt inside untrusted-content markers, and the agent is told to treat directions found there as data to report rather than follow.
  • Private persistence - credentials and sessions use private directories and mode 0600 files; symlink-backed config, credential, session, memory, skill, and .env files are rejected.
  • Read-only modes - Plan and Ask modes deterministically block mutating tools and project-code execution.

Architecture

main.go                      # entry → cmd.Execute()
cmd/                         # cobra CLI: root + config / scan / skill / task
internal/
  llm/        provider-agnostic tool-calling over Anthropic / OpenAI / Gemini
  agent/      processor (agentic loop), context, prompts, danger gating, task plan
  tools/      24 tools + JSON-schema defs, path safety, registry
  config/     .coolcode.json load/save + dotted get/set
  session/    ~/.coolcode/sessions persistence
  skills/     SKILL.md discovery + install (local path / git URL)
  memory/     COOLCODE.md loader
  project/    gitignore matching, folder tree, project scan
  tui/        Bubble Tea app, Lipgloss theme, Glamour markdown, commands
  types/      shared domain types

The agent loop sends each provider the tool schemas and a running message list, executes the tool calls it returns, feeds results back, and repeats until the model produces a final message.

Development

make build   # build ./cool-code
make test    # go test ./...
make vet     # go vet ./...
make fmt     # gofmt -w .

Requires Go 1.25.13+ (or a newer supported, patched Go release). External tools used at runtime when present: git, rg (ripgrep, for find_symbol), bash, and npx prettier (for format_file).

Future scope

  • Semantic codebase index - a local embedding index kept in sync via a Merkle tree of file hashes, exposed as a codebase_search tool.
  • Subscription sign-in for /connect (Claude Pro/Max, ChatGPT/Codex OAuth).
  • Full-toolset subagents (explore-only subagents shipped; write-capable ones need permission routing).
  • Edit checkpoints and /undo, granular permission allowlists, custom slash commands, MCP support, hooks, and multimodal input.
  • @file mentions - the composer already completes paths; it does not yet attach the file's contents.

Changelog

2.3.2: Security fixes and accurate activity status (2026-09-15)

Upgrading. Source builds now require Go 1.25.13 or a newer supported, patched Go release. Directory moves through rename_file are refused; regular file renames remain supported. Shell, test, and lint commands are refused when credential redaction would hide executable text in their approval preview. Path guardrails now match case-insensitively on every platform.

Tool authorization and approvals. Read-only subagents enforce their tool permissions at execution. Interactive --mode ask and --mode plan are honored, including when resuming a session at startup. Command approvals show the full command and working directory, visibly escape control characters, and allow long commands to be scrolled into view. Inferred test and lint commands are fixed before approval.

Filesystem protection. Module scaffolding validates every output path; README writes respect protected paths. Skill installation uses trusted directory handles and preserves the previous installation if copying fails. Scan-cache updates cannot truncate symlink or hardlink targets. Directory renames cannot move protected files into readable locations.

Data protection. Git diffs and symbol searches apply the application's read policy to individual paths, including case aliases, directory aliases, and custom glob patterns. Queued prompts, task planning, and restored history receive secret redaction. Task, subagent, and CLI output strip terminal control sequences before rendering.

Activity status. The interface reports the operation the agent is actually performing and shows elapsed time while it is working.

2.3.1: TUI fixes on top of 2.3.0 (2026-08)

Everything here corrects something 2.3.0 introduced.

Upgrading. The context figure now measures against the model's context window rather than features.maxContextTokens. If your model id is not one cool-code recognises, which includes most proxies and gateways, the status bar shows a token count instead of a percentage until you declare the window:

cool-code config set llm.contextWindow 200000

Markdown formats as it streams. The streaming entry was plain-wrapped, so a long answer showed ## Steps and **bold** literally for its whole duration and only formatted once the last fragment arrived. Completed blocks are now rendered as they land, while the block still being written stays plain, so a half-arrived bold or an unclosed fence cannot render wrong and then reflow.

Prose the model writes before calling a tool is kept rather than discarded. That was invisible while nothing streamed; with streaming on it meant watching a long answer arrive and then vanish.

The context figure was wrong, not just badly scaled. It measured against features.maxContextTokens, which bounds how much conversation is selected for a request, not the model's window, and a request can legitimately exceed it because the system prompt sits outside it. That reported 250% on a short conversation. An unrecognised model now reports a token count rather than a percentage taken from a guessed denominator.

One header, not two. The persistent header was added without removing the banner it replaced, so the name and version rendered twice; the status bar also kept printing the mode, model and effort the header already showed. Mode, model and effort now live in the status bar alone, beside the composer that acts on them, and the header carries identity.

Layout. The sidebar no longer claims a full-height column on an idle session to say "No active tasks", and the rule runs through the header row so the two columns each have their own title, instead of the header spanning both and reading as the sidebar's heading.

The startup warning about global-only keys in .coolcode.json now fires only for values that differ from the ones actually in effect, instead of for every duplicate, which made a correct setup look broken.

2.3.0: security fixes, two-pane TUI, streaming and cost (2026-08)

Upgrading. Four behaviour changes worth knowing about:

  • COOLCODE_API_KEY is no longer read from a project .env. It applies with no global setting, so honouring it from a repository file let a cloned project choose which provider account requests were billed and logged against. Export it in your shell, or name a different *_API_KEY variable and point llm.apiKeyEnv at it. Other *_API_KEY values still load from .env.
  • features.maxContextTokens now defaults to 120000 rather than 20000. Requests carry more history, which costs more per turn; set it back if that matters to you.
  • Tools can no longer write inside .git or .coolcode. A workflow that had the agent edit .git/config or install a hook will now be refused.
  • edit_file reports a replacement count instead of returning the whole edited file.

Security. Two defects reachable without user cooperation: shellEscapeSingleQuotes emitted '\"'\"' where POSIX needs '\'', leaving the shell parser unquoted, which made find_symbol and git_diff (both read-only, so available in Plan and Ask mode and to subagents) into command execution; and the path jail cleaned .. lexically before resolving symlinks, then performed I/O on the raw string, so link/../secret escaped the workspace. Commands are built as argv with no shell, and paths are resolved component by component with callers acting on the resolved path.

Also: tool writes refused inside .git and .coolcode; read guardrails extended to edit_file and the git tools, and edit_file no longer returns the whole file; format_file and add_script now confirm before running project code; terminal escape sequences stripped from model, tool and confirmation text; the skills installer no longer follows symlinks or inherits the environment; repository and web content marked untrusted in the prompt; .env can no longer substitute the provider credential; CGNAT and other reserved ranges blocked in web fetches. internal/tools coverage raised from 38.9%, and gosec added to CI alongside a read-only workflow token.

TUI. A layout pass computes the frame once, fixing a double footer render and a render that mutated model state. Above 100 columns the transcript gains a sidebar with the live task list and running subagents; a persistent header replaces the banner that scrolled away. Fenced code is syntax highlighted, which it never was, and markdown colours come from the palette rather than ANSI-256 literals. Errors and failed tool calls are visually distinct.

Features. Streaming turned on, line buffered so redaction still sees whole lines. Compaction bounded, less lossy, configurable and visible, with /compact; the context window default raised from 20k. Per-command timeouts instead of a fixed 30 seconds. /model, /cost, and a non-interactive --print mode with --json.

2.2.1: Security hardening (2026-08)

  • Trusted global-only proxy endpoints, credential binding, HTTPS validation, redirect blocking, and sanitized provider errors.
  • Symlink-aware workspace jails across reads, searches, writes, pins, skills, memory, and multi-root access.
  • Confirmation for arbitrary commands and project-code execution, with sensitive environment variables removed from child processes.
  • SSRF protection for web fetches, including private networks, cloud metadata, redirects, and DNS rebinding checks.
  • Secret redaction before model egress and session persistence; sessions and credentials now use private filesystem permissions.
  • Deterministic read-only Plan and Ask modes, plus final-answer-only transcript rendering that suppresses intermediate model prose.

2.2 - Responsive TUI, proxy endpoints & multi-root workspaces (2026-08)

  • Responsive compact TUI, persistent composer, bounded menus and overlays.
  • Distinct PLAN READY cards and improved Markdown formatting.
  • /add-dir multi-root workspace support and cross-directory completion.
  • OpenAI-compatible proxy/base URL and API-key environment configuration.
  • Reasoning effort via --effort, /effort, and llm.reasoningEffort.
  • Terminal OSC reply filtering and render regression tests.

2.1 - Subagents, concurrency & quality of life (2026-07)

  • Explore subagents - new spawn_agent tool; the agent fans out concurrent read-only mini-agents (own history, 15-iteration cap, cannot nest) with live per-agent status lines in the TUI.
  • Parallel tools - independent read-only tool calls in one assistant turn run concurrently; mutating calls stay sequential with results in original call order.
  • Cancellation - Esc or Ctrl+C aborts an in-flight turn (LLM request, shell commands, and web requests all stop); Ctrl+C while idle quits. Interrupted tool calls are closed cleanly so the next request never fails on unpaired tool calls.
  • Streaming - assistant output streams token-by-token on all three providers (Anthropic, OpenAI, Gemini) over SSE.
  • /connect - interactive provider setup; API keys stored in ~/.coolcode/credentials.json (0600), provider/model defaults in ~/.coolcode/settings.json, env vars as fallback. Starting without a key opens the TUI with a hint instead of exiting.
  • Reliability - automatic retry with exponential backoff on 429/5xx/network errors (honors Retry-After); real token usage from provider responses in the status bar; sessions persist on quit and cancel; fixed a data race between the status bar and the agent loop.
  • TUI - multiline input (Enter submits, Alt+Enter/Ctrl+J newline), mouse-wheel and PgUp/PgDn scrolling, input-history recall on Up/Down, --resume repopulates the visible transcript, markdown re-wraps on window resize, edit confirmations show red/green diff hunks.
  • Safety - edit_file and shell_command directories are confined to the project root; confirmEdits works independently of allowDangerous; all tool error labels are now descriptive.

2.0 - Go rewrite

  • Full rewrite from TypeScript/Node to a single Go binary: native provider function-calling (Anthropic, OpenAI, Gemini), Bubble Tea/Lipgloss/Glamour TUI, cobra CLI, plan/agent/ask modes, sessions, skills, project memory, and 23 tools. The TypeScript version lives on the node branch.

About

cli coding Harness

Topics

Resources

Security policy

Stars

9 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages