Skip to content

Releases: FiveTechSoft/CCHarbour

v0.8.26 — Hooks system

27 May 17:05

Choose a tag to compare

CCHarbour v0.8.26 — Hooks system: fire-and-forget turn_complete shell hooks with a /hook REPL command.

New since v0.8.25

  • /hook command. Full CRUD over hooks stored in
    .ccharbour/settings.json: /hook list, /hook add <event> <cmd>, /hook remove <event> <idx>, /hook edit <event> <idx> <cmd>, /hook test <event>, /hook log. Missing
    subcommand defaults to list. Unknown events echo the valid
    event list; out-of-range indices report the actual range.
  • turn_complete event. Fires on every turn outcome
    (success, error, interrupted) via CCHOOKS_Run from inside
    CCREPL_RunTurn. The fire is hb_processOpen with
    detach=.T., so the REPL never blocks on a hook. Each hook
    is wrapped in BEGIN SEQUENCE / RECOVER so a single bad
    command cannot take out the REPL or other hooks for the same
    fire.
  • CCHARBOUR_* env vars. Children inherit six env vars
    set on the CCHarbour process before each spawn:
    CCHARBOUR_EVENT, CCHARBOUR_STATUS
    (success/error/interrupted), CCHARBOUR_MODEL,
    CCHARBOUR_TOKENS, CCHARBOUR_DURATION_MS, CCHARBOUR_CWD.
  • Opt-in hooks_log. Set "hooks_log": true in
    .ccharbour/settings.json to append-log every fire to
    .ccharbour/hooks.log ([YYYY-MM-DD HH:MM:SS] event=... status=... cmd=...). Spawn failures and exceptions show up
    as ERROR spawn-failed / ERROR exception lines.
  • Settings reload on every fire. Editing the hooks block in
    .ccharbour/settings.json takes effect on the next turn
    without restarting CCHarbour (per-fire CCSETTINGS_Load).
  • New module src/cchooks.prg. Pure helpers
    (CCHOOKS_ValidEvents, IsValidEvent, List, Add,
    Remove, Edit), log writer (LogPath, Log), the runtime
    fire path (CCHOOKS_Run), and the user-facing renderer
    (CCHOOKS_Render, CCHOOKS_EventList). Registered in
    cc.hbp, cc_linux.hbp, and cc_mac.hbp so it links on
    every platform.
  • 42 new hooks assertions in tests/test_hooks.prg plus 4
    /hook parser tests in tests/test_ui.prg and a malformed-
    hooks merge regression test in tests/test_settings.prg. Test
    suite goes from 431 to 490 passing.
  • Banner version bumped to v0.8.26.

Future work is documented in
docs/superpowers/specs/2026-05-27-hooks-system-design.md:
more events (session_start, pre_tool_use, ...), per-hook
timeouts, JSON-on-stdin context, hook conditions
(on_status: [...]), and log rotation.

New since v0.8.24

  • Ollama auth fix. Ollama 0.20.4 silently hangs the request
    when Authorization: Bearer sk-... (a left-over DeepSeek /
    OpenAI key from a prior /provider deepseek session) is sent
    -- it appears to treat the credential as a cloud-forward
    token and waits on a remote that never answers. CCHarbour now
    forces Bearer ollama on every request to a localhost:11434
    URL via a CC_IsOllamaUrl check in ccapi.prg. The user's
    stored cloud key stays untouched in settings.json so the
    next /provider deepseek switch reuses it.
  • Accept: text/event-stream dropped for Ollama. With that
    header set, Ollama collapses tool calls into a JSON blob
    inside message.content instead of populating tool_calls.
    CCHarbour now omits the header for Ollama URLs; SSE still
    works because the body's "stream": true is what activates
    streaming.
  • stream_options.include_usage omitted for Ollama. Ollama
    0.20.x stalls when that field is present. /cost will not
    show token counts for Ollama turns as a result; cloud
    backends keep emitting the final usage chunk.
  • Ollama setup notes rewritten in pages/commands.md. The
    three quirks above are now documented, plus the real
    bottleneck: even after the fixes, sending all 17 of
    CCHarbour's tool schemas (~15 KB JSON) to llama3.1:8b
    takes Ollama > 90 s per turn on consumer GPUs and frequently
    hits the curl 120 s deadline. Best used for short
    conversational turns, not the full agent loop.

v0.8.24 — Ollama preset default switched to llama3.1:8b + setup notes.

New since v0.8.23

  • /provider ollama default model is now llama3.1:8b. Local
    testing showed qwen2.5-coder:7b (the previous default) emits
    bare JSON inside message.content instead of populating
    tool_calls, so Ollama's OpenAI-compatible endpoint never
    surfaces a tool call and the agent loop ends every turn with
    the [hint: 0 tool calls...] warning. llama3.1:8b returns
    proper tool_calls through the same endpoint and works with
    the loop end-to-end. Same caveat for the abliterated
    qwen2.5-coder GGUFs floating around on Hugging Face.
  • Updated applied-preset message and commands.md. Three real
    gotchas are now spelled out: (1) OLLAMA_CONTEXT_LENGTH=16384
    is required -- the default 4096 ctx is too small for the
    CCHarbour system prompt + 16 tool schemas (the request silently
    hangs at the curl 120 s timeout); (2) only models that route
    tool calls through the OpenAI tool_calls field actually
    work with CCHarbour (llama3.1:8b, mistral-nemo:12b,
    command-r confirmed; qwen2.5-coder confirmed broken);
    (3) Ollama 0.20.x can hang on /v1/chat/completions with
    stream:true and a populated tools array for some models --
    switch model if the timeout fires.

v0.8.23 — Ollama provider preset + one-shot no-tool-call hint.

New since v0.8.22

  • /provider ollama preset. Sets base_url to
    http://localhost:11434/v1 and the default model to
    qwen2.5-coder:7b. The placeholder API key ollama is
    auto-seeded so the agent loop does not block on the "no api
    key" branch -- Ollama's OpenAI-compatible endpoint ignores
    Authorization. The applied-preset message reminds the user
    to run ollama serve, pull the model, and pick a
    tool-calling-capable model (qwen2.5-coder, llama3.1+,
    mistral-nemo). Updated Presets: list, "no API key" banner
    warning, and the playground /help footer to mention ollama.
  • No-tool-call detection. CC_AgentRun now returns
    tool_call_count -- the total number of tool calls issued
    across the whole run. After every successful turn,
    CCREPL_MaybeWarnNoToolCall checks whether the count is
    zero AND the model's reply contains a phrase that suggests
    the model wanted to act but could not ("I would run...", "I
    cannot access...", "without access to tools", and ~15 more).
    When both conditions hold, a one-shot warn-coloured hint
    points at /provider model <name> with a curated list of
    tool-calling models. The hint is muted permanently once any
    tool call succeeds (proof of tool support); /clear and
    /provider re-arm it so the next backend gets a fair
    re-evaluation.

v0.8.22 — /load crash fix + working /loop and /rewind in the playground.

New since v0.8.21

  • Fixed /load crash. CCUI_SessionListOutput concatenated a
    Harbour DATE with a string (DToS(d) + " " + d) inside the row
    formatter and raised Fatal: Argument error the first time
    /load was run against a sessions directory that contained any
    saved file. The bug shipped in v0.8.21. Switched to
    DToC( mtime ) so the date renders as a plain string. Verified
    on Windows, macOS and Linux.
  • Playground /rewind [N]. Pops the conversation snapshot
    stack (capped at 20), restoring the message array and the
    cumulative usage counter to the state before the last user
    turn. Snapshots are pushed in handleSubmit just before the
    user message is appended, so slash commands and the
    API-key-missing branch do not push spurious entries.
  • Playground /loop <interval> <prompt>. Arms a
    setInterval that re-issues the prompt via handleSubmit
    every interval. Intervals accept s / m / h suffixes;
    bare numbers are seconds. /loop status, /loop stop and
    /loop clear mirror the native binary; ticks that would
    overlap a running turn are skipped.
  • Playground /clear now resets /loop and /rewind state.
    The handler flushes the rewind stack and cancels any armed
    loop alongside the existing project / conversation / usage
    reset.

v0.8.21 — /loop fixed-interval rerun + /rewind (double-tap Esc).

New since v0.8.20

  • /loop slash command. Re-run a prompt on a fixed interval,
    matching Claude Code's fixed-interval /loop. /loop 5m check CI
    arms a recurring turn every 5 minutes; intervals accept the s,
    m, h suffixes (a bare number is seconds). /loop /
    /loop status shows the active loop, /loop stop ends it while
    keeping the prompt text, /loop clear drops both. The sleep
    between turns is interruptible — pressing Esc ends the loop.
    Hooks in parallel to the existing /goal auto-continue, so
    /loop and /goal can be armed independently. Model-paced
    (self-scheduled) variant is not implemented in this release.
  • /rewind slash command + double-tap Esc. Undo the last
    conversation turn. /rewind pops one snapshot; /rewind N pops
    N. A double-tap of Esc (≤ 600 ms apart) at the idle prompt is
    detected in CCPROMPT_Poll and converted into a rewind
    interrupt kind, which CCREPL_PromptIdle returns as the literal
    /rewind. Snapshots are pushed before each user message,
    /init, /btw drain message, and /loop runner turn; the
    stack is capped at 20 entries (oldest falls off the bottom).
    Restored state covers aMsgs, s_cGoal, s_lGoalLooping,
    s_cLoopPrompt, s_nLoopIntervalSec, s_lLoopActive,
    s_lPlanMode, s_lLeanMode, s_hSessionUsage, and
    s_lCompactNudged. /clear and /load flush the stack. File
    modifications made by write / edit / shell are NOT rolled
    back — only the conversation.

v0.8.20 — Ask-prompt deadlock fix: non-TTY auto-deny + CCHARBOUR_ASK_TIMEOUT.

New since v0.8.19

  • **Non-TTY auto-den...
Read more

v0.8.25

26 May 19:45

Choose a tag to compare

CCHarbour v0.8.25 — Ollama-specific bug fixes uncovered by end-to-end testing.

New since v0.8.24

  • Ollama auth fix. Ollama 0.20.4 silently hangs the request
    when Authorization: Bearer sk-... (a left-over DeepSeek /
    OpenAI key from a prior /provider deepseek session) is sent
    -- it appears to treat the credential as a cloud-forward
    token and waits on a remote that never answers. CCHarbour now
    forces Bearer ollama on every request to a localhost:11434
    URL via a CC_IsOllamaUrl check in ccapi.prg. The user's
    stored cloud key stays untouched in settings.json so the
    next /provider deepseek switch reuses it.
  • Accept: text/event-stream dropped for Ollama. With that
    header set, Ollama collapses tool calls into a JSON blob
    inside message.content instead of populating tool_calls.
    CCHarbour now omits the header for Ollama URLs; SSE still
    works because the body's "stream": true is what activates
    streaming.
  • stream_options.include_usage omitted for Ollama. Ollama
    0.20.x stalls when that field is present. /cost will not
    show token counts for Ollama turns as a result; cloud
    backends keep emitting the final usage chunk.
  • Ollama setup notes rewritten in pages/commands.md. The
    three quirks above are now documented, plus the real
    bottleneck: even after the fixes, sending all 17 of
    CCHarbour's tool schemas (~15 KB JSON) to llama3.1:8b
    takes Ollama > 90 s per turn on consumer GPUs and frequently
    hits the curl 120 s deadline. Best used for short
    conversational turns, not the full agent loop.

v0.8.24 — Ollama preset default switched to llama3.1:8b + setup notes.

New since v0.8.23

  • /provider ollama default model is now llama3.1:8b. Local
    testing showed qwen2.5-coder:7b (the previous default) emits
    bare JSON inside message.content instead of populating
    tool_calls, so Ollama's OpenAI-compatible endpoint never
    surfaces a tool call and the agent loop ends every turn with
    the [hint: 0 tool calls...] warning. llama3.1:8b returns
    proper tool_calls through the same endpoint and works with
    the loop end-to-end. Same caveat for the abliterated
    qwen2.5-coder GGUFs floating around on Hugging Face.
  • Updated applied-preset message and commands.md. Three real
    gotchas are now spelled out: (1) OLLAMA_CONTEXT_LENGTH=16384
    is required -- the default 4096 ctx is too small for the
    CCHarbour system prompt + 16 tool schemas (the request silently
    hangs at the curl 120 s timeout); (2) only models that route
    tool calls through the OpenAI tool_calls field actually
    work with CCHarbour (llama3.1:8b, mistral-nemo:12b,
    command-r confirmed; qwen2.5-coder confirmed broken);
    (3) Ollama 0.20.x can hang on /v1/chat/completions with
    stream:true and a populated tools array for some models --
    switch model if the timeout fires.

v0.8.23 — Ollama provider preset + one-shot no-tool-call hint.

New since v0.8.22

  • /provider ollama preset. Sets base_url to
    http://localhost:11434/v1 and the default model to
    qwen2.5-coder:7b. The placeholder API key ollama is
    auto-seeded so the agent loop does not block on the "no api
    key" branch -- Ollama's OpenAI-compatible endpoint ignores
    Authorization. The applied-preset message reminds the user
    to run ollama serve, pull the model, and pick a
    tool-calling-capable model (qwen2.5-coder, llama3.1+,
    mistral-nemo). Updated Presets: list, "no API key" banner
    warning, and the playground /help footer to mention ollama.
  • No-tool-call detection. CC_AgentRun now returns
    tool_call_count -- the total number of tool calls issued
    across the whole run. After every successful turn,
    CCREPL_MaybeWarnNoToolCall checks whether the count is
    zero AND the model's reply contains a phrase that suggests
    the model wanted to act but could not ("I would run...", "I
    cannot access...", "without access to tools", and ~15 more).
    When both conditions hold, a one-shot warn-coloured hint
    points at /provider model <name> with a curated list of
    tool-calling models. The hint is muted permanently once any
    tool call succeeds (proof of tool support); /clear and
    /provider re-arm it so the next backend gets a fair
    re-evaluation.

v0.8.22 — /load crash fix + working /loop and /rewind in the playground.

New since v0.8.21

  • Fixed /load crash. CCUI_SessionListOutput concatenated a
    Harbour DATE with a string (DToS(d) + " " + d) inside the row
    formatter and raised Fatal: Argument error the first time
    /load was run against a sessions directory that contained any
    saved file. The bug shipped in v0.8.21. Switched to
    DToC( mtime ) so the date renders as a plain string. Verified
    on Windows, macOS and Linux.
  • Playground /rewind [N]. Pops the conversation snapshot
    stack (capped at 20), restoring the message array and the
    cumulative usage counter to the state before the last user
    turn. Snapshots are pushed in handleSubmit just before the
    user message is appended, so slash commands and the
    API-key-missing branch do not push spurious entries.
  • Playground /loop <interval> <prompt>. Arms a
    setInterval that re-issues the prompt via handleSubmit
    every interval. Intervals accept s / m / h suffixes;
    bare numbers are seconds. /loop status, /loop stop and
    /loop clear mirror the native binary; ticks that would
    overlap a running turn are skipped.
  • Playground /clear now resets /loop and /rewind state.
    The handler flushes the rewind stack and cancels any armed
    loop alongside the existing project / conversation / usage
    reset.

v0.8.21 — /loop fixed-interval rerun + /rewind (double-tap Esc).

New since v0.8.20

  • /loop slash command. Re-run a prompt on a fixed interval,
    matching Claude Code's fixed-interval /loop. /loop 5m check CI
    arms a recurring turn every 5 minutes; intervals accept the s,
    m, h suffixes (a bare number is seconds). /loop /
    /loop status shows the active loop, /loop stop ends it while
    keeping the prompt text, /loop clear drops both. The sleep
    between turns is interruptible — pressing Esc ends the loop.
    Hooks in parallel to the existing /goal auto-continue, so
    /loop and /goal can be armed independently. Model-paced
    (self-scheduled) variant is not implemented in this release.
  • /rewind slash command + double-tap Esc. Undo the last
    conversation turn. /rewind pops one snapshot; /rewind N pops
    N. A double-tap of Esc (≤ 600 ms apart) at the idle prompt is
    detected in CCPROMPT_Poll and converted into a rewind
    interrupt kind, which CCREPL_PromptIdle returns as the literal
    /rewind. Snapshots are pushed before each user message,
    /init, /btw drain message, and /loop runner turn; the
    stack is capped at 20 entries (oldest falls off the bottom).
    Restored state covers aMsgs, s_cGoal, s_lGoalLooping,
    s_cLoopPrompt, s_nLoopIntervalSec, s_lLoopActive,
    s_lPlanMode, s_lLeanMode, s_hSessionUsage, and
    s_lCompactNudged. /clear and /load flush the stack. File
    modifications made by write / edit / shell are NOT rolled
    back — only the conversation.

v0.8.20 — Ask-prompt deadlock fix: non-TTY auto-deny + CCHARBOUR_ASK_TIMEOUT.

New since v0.8.19

  • Non-TTY auto-deny on ask prompts. When a tool gated ask
    fires and stdin is not a TTY (piped input, script -c, a
    background SSH exec_command, a CI runner), CCREPL_AskPerm
    used to call the line reader anyway and block forever — no human
    was at the keyboard to type y. Now the path is short-circuited
    with a one-line [non-interactive stdin -- '<tool>' denied]
    notice and the call is denied immediately, so the agent loop
    surfaces an Error: tool ... denied by user result and keeps
    moving instead of hanging.
  • CCHARBOUR_ASK_TIMEOUT env var. Bounds the wait even on a
    real TTY. Set to a positive integer number of seconds; if no
    answer is typed before the deadline, the REPL prints
    [no response in Ns -- denied] and the call is denied. Default
    (unset or 0) keeps the original blocking behaviour. Both safety
    nets fall back to deny — a missing human can never silently
    approve.
  • New CCREPL_ReadLineTimeout(nSecs) helper. Poll-based stdin
    reader that wakes every 500 ms via the new
    CCCON_StdInWait( nMs ) C primitive (POSIX select() on
    STDIN_FILENO in src/ccconsole_posix.c; WaitForSingleObject
    on the Win32 input handle in src/ccconsole.c). Same paste/echo
    conventions as CCREPL_ReadLine so the editing experience is
    unchanged when the user does type.

v0.8.19 — /compact slash command + auto context-fill warning.

New since v0.8.18

  • /compact slash command. Summarises the older part of the
    conversation into one synthetic system note, keeping the system
    prompt and the last 4 turns verbatim. A stateless one-shot call
    with a strict "preserve exact paths / identifiers / errors /
    code verbatim, no paraphrase, no preamble" instruction. Refuses
    to compact when the very last assistant turn has a dangling
    tool_call (no matching tool response yet), so a compaction
    cannot orphan a tool-call id mid-cycle.
  • Soft "/compact" hint when context fills up. After every
    successful turn CCREPL_MaybeWarnCompact compares the last
    prompt_tokens against compact_threshold (default 0.7) of
    the model's context window and prints
    [context X% full -- run /compact ...] one time. Re-armable on
    /clear or after a successful /compact. Never auto-runs.
  • Per-model context windows. CCREPL_ModelContext maps the
    active model to its context size (deepseek 128k, kimi-k2...
Read more

v0.8.24

26 May 09:48

Choose a tag to compare

CCHarbour v0.8.24 — Ollama preset default switched to llama3.1:8b + setup notes.

New since v0.8.23

  • /provider ollama default model is now llama3.1:8b. Local
    testing showed qwen2.5-coder:7b (the previous default) emits
    bare JSON inside message.content instead of populating
    tool_calls, so Ollama's OpenAI-compatible endpoint never
    surfaces a tool call and the agent loop ends every turn with
    the [hint: 0 tool calls...] warning. llama3.1:8b returns
    proper tool_calls through the same endpoint and works with
    the loop end-to-end. Same caveat for the abliterated
    qwen2.5-coder GGUFs floating around on Hugging Face.
  • Updated applied-preset message and commands.md. Three real
    gotchas are now spelled out: (1) OLLAMA_CONTEXT_LENGTH=16384
    is required -- the default 4096 ctx is too small for the
    CCHarbour system prompt + 16 tool schemas (the request silently
    hangs at the curl 120 s timeout); (2) only models that route
    tool calls through the OpenAI tool_calls field actually
    work with CCHarbour (llama3.1:8b, mistral-nemo:12b,
    command-r confirmed; qwen2.5-coder confirmed broken);
    (3) Ollama 0.20.x can hang on /v1/chat/completions with
    stream:true and a populated tools array for some models --
    switch model if the timeout fires.

v0.8.23 — Ollama provider preset + one-shot no-tool-call hint.

New since v0.8.22

  • /provider ollama preset. Sets base_url to
    http://localhost:11434/v1 and the default model to
    qwen2.5-coder:7b. The placeholder API key ollama is
    auto-seeded so the agent loop does not block on the "no api
    key" branch -- Ollama's OpenAI-compatible endpoint ignores
    Authorization. The applied-preset message reminds the user
    to run ollama serve, pull the model, and pick a
    tool-calling-capable model (qwen2.5-coder, llama3.1+,
    mistral-nemo). Updated Presets: list, "no API key" banner
    warning, and the playground /help footer to mention ollama.
  • No-tool-call detection. CC_AgentRun now returns
    tool_call_count -- the total number of tool calls issued
    across the whole run. After every successful turn,
    CCREPL_MaybeWarnNoToolCall checks whether the count is
    zero AND the model's reply contains a phrase that suggests
    the model wanted to act but could not ("I would run...", "I
    cannot access...", "without access to tools", and ~15 more).
    When both conditions hold, a one-shot warn-coloured hint
    points at /provider model <name> with a curated list of
    tool-calling models. The hint is muted permanently once any
    tool call succeeds (proof of tool support); /clear and
    /provider re-arm it so the next backend gets a fair
    re-evaluation.

v0.8.22 — /load crash fix + working /loop and /rewind in the playground.

New since v0.8.21

  • Fixed /load crash. CCUI_SessionListOutput concatenated a
    Harbour DATE with a string (DToS(d) + " " + d) inside the row
    formatter and raised Fatal: Argument error the first time
    /load was run against a sessions directory that contained any
    saved file. The bug shipped in v0.8.21. Switched to
    DToC( mtime ) so the date renders as a plain string. Verified
    on Windows, macOS and Linux.
  • Playground /rewind [N]. Pops the conversation snapshot
    stack (capped at 20), restoring the message array and the
    cumulative usage counter to the state before the last user
    turn. Snapshots are pushed in handleSubmit just before the
    user message is appended, so slash commands and the
    API-key-missing branch do not push spurious entries.
  • Playground /loop <interval> <prompt>. Arms a
    setInterval that re-issues the prompt via handleSubmit
    every interval. Intervals accept s / m / h suffixes;
    bare numbers are seconds. /loop status, /loop stop and
    /loop clear mirror the native binary; ticks that would
    overlap a running turn are skipped.
  • Playground /clear now resets /loop and /rewind state.
    The handler flushes the rewind stack and cancels any armed
    loop alongside the existing project / conversation / usage
    reset.

v0.8.21 — /loop fixed-interval rerun + /rewind (double-tap Esc).

New since v0.8.20

  • /loop slash command. Re-run a prompt on a fixed interval,
    matching Claude Code's fixed-interval /loop. /loop 5m check CI
    arms a recurring turn every 5 minutes; intervals accept the s,
    m, h suffixes (a bare number is seconds). /loop /
    /loop status shows the active loop, /loop stop ends it while
    keeping the prompt text, /loop clear drops both. The sleep
    between turns is interruptible — pressing Esc ends the loop.
    Hooks in parallel to the existing /goal auto-continue, so
    /loop and /goal can be armed independently. Model-paced
    (self-scheduled) variant is not implemented in this release.
  • /rewind slash command + double-tap Esc. Undo the last
    conversation turn. /rewind pops one snapshot; /rewind N pops
    N. A double-tap of Esc (≤ 600 ms apart) at the idle prompt is
    detected in CCPROMPT_Poll and converted into a rewind
    interrupt kind, which CCREPL_PromptIdle returns as the literal
    /rewind. Snapshots are pushed before each user message,
    /init, /btw drain message, and /loop runner turn; the
    stack is capped at 20 entries (oldest falls off the bottom).
    Restored state covers aMsgs, s_cGoal, s_lGoalLooping,
    s_cLoopPrompt, s_nLoopIntervalSec, s_lLoopActive,
    s_lPlanMode, s_lLeanMode, s_hSessionUsage, and
    s_lCompactNudged. /clear and /load flush the stack. File
    modifications made by write / edit / shell are NOT rolled
    back — only the conversation.

v0.8.20 — Ask-prompt deadlock fix: non-TTY auto-deny + CCHARBOUR_ASK_TIMEOUT.

New since v0.8.19

  • Non-TTY auto-deny on ask prompts. When a tool gated ask
    fires and stdin is not a TTY (piped input, script -c, a
    background SSH exec_command, a CI runner), CCREPL_AskPerm
    used to call the line reader anyway and block forever — no human
    was at the keyboard to type y. Now the path is short-circuited
    with a one-line [non-interactive stdin -- '<tool>' denied]
    notice and the call is denied immediately, so the agent loop
    surfaces an Error: tool ... denied by user result and keeps
    moving instead of hanging.
  • CCHARBOUR_ASK_TIMEOUT env var. Bounds the wait even on a
    real TTY. Set to a positive integer number of seconds; if no
    answer is typed before the deadline, the REPL prints
    [no response in Ns -- denied] and the call is denied. Default
    (unset or 0) keeps the original blocking behaviour. Both safety
    nets fall back to deny — a missing human can never silently
    approve.
  • New CCREPL_ReadLineTimeout(nSecs) helper. Poll-based stdin
    reader that wakes every 500 ms via the new
    CCCON_StdInWait( nMs ) C primitive (POSIX select() on
    STDIN_FILENO in src/ccconsole_posix.c; WaitForSingleObject
    on the Win32 input handle in src/ccconsole.c). Same paste/echo
    conventions as CCREPL_ReadLine so the editing experience is
    unchanged when the user does type.

v0.8.19 — /compact slash command + auto context-fill warning.

New since v0.8.18

  • /compact slash command. Summarises the older part of the
    conversation into one synthetic system note, keeping the system
    prompt and the last 4 turns verbatim. A stateless one-shot call
    with a strict "preserve exact paths / identifiers / errors /
    code verbatim, no paraphrase, no preamble" instruction. Refuses
    to compact when the very last assistant turn has a dangling
    tool_call (no matching tool response yet), so a compaction
    cannot orphan a tool-call id mid-cycle.
  • Soft "/compact" hint when context fills up. After every
    successful turn CCREPL_MaybeWarnCompact compares the last
    prompt_tokens against compact_threshold (default 0.7) of
    the model's context window and prints
    [context X% full -- run /compact ...] one time. Re-armable on
    /clear or after a successful /compact. Never auto-runs.
  • Per-model context windows. CCREPL_ModelContext maps the
    active model to its context size (deepseek 128k, kimi-k2 200k,
    gpt-5 400k, ...) with a 32k fallback.
  • compact_threshold setting. New 0.7 default in
    CCSETTINGS_Defaults; users can tune it per project.
  • dispatch_agent_background ungated. Added to the never-gated
    list in CCPERM_Decide alongside dispatch_agent /
    propose_agents — same consent model.

v0.8.18 — Background subagents: dispatch_agent_background tool + /tasks slash command.

New since v0.8.17

  • dispatch_agent_background tool. Fire-and-forget variant of
    dispatch_agent. Returns a task-id (bg1, bg2, ...) IMMEDIATELY
    without blocking the parent. A fresh hb_threadStart worker runs
    CC_AgentRun in the background and writes progress into an in-
    memory registry; the parent agent can chain its next step right
    away.
  • Background-task registry (src/ccbg.prg). Mutex-protected
    hash keyed by task id. Each record carries id, type, prompt,
    timeout, status (queued / running / done / failed /
    cancelled / timed_out), started_ms, ended_ms,
    iterations, reply, error, cancel_requested. Public API:
    CCBG_NextId / Add / Update / Get / List / Kill / CancelRequested / ClearFinished. Workers MUST NOT touch the terminal (that would
    corrupt the dynamic input box); the main REPL polls the registry.
  • /tasks slash command. The user's only window into the
    registry:
    • /tasks -- tabular list (id, status, elapsed, type, prompt
      summary).
    • /tasks view <id> -- full record including reply / error.
    • /tasks kill <id> -- request cancel; worker exits a...
Read more

v0.8.23

26 May 09:06

Choose a tag to compare

CCHarbour v0.8.23 — Ollama provider preset + one-shot no-tool-call hint.

New since v0.8.22

  • /provider ollama preset. Sets base_url to
    http://localhost:11434/v1 and the default model to
    qwen2.5-coder:7b. The placeholder API key ollama is
    auto-seeded so the agent loop does not block on the "no api
    key" branch -- Ollama's OpenAI-compatible endpoint ignores
    Authorization. The applied-preset message reminds the user
    to run ollama serve, pull the model, and pick a
    tool-calling-capable model (qwen2.5-coder, llama3.1+,
    mistral-nemo). Updated Presets: list, "no API key" banner
    warning, and the playground /help footer to mention ollama.
  • No-tool-call detection. CC_AgentRun now returns
    tool_call_count -- the total number of tool calls issued
    across the whole run. After every successful turn,
    CCREPL_MaybeWarnNoToolCall checks whether the count is
    zero AND the model's reply contains a phrase that suggests
    the model wanted to act but could not ("I would run...", "I
    cannot access...", "without access to tools", and ~15 more).
    When both conditions hold, a one-shot warn-coloured hint
    points at /provider model <name> with a curated list of
    tool-calling models. The hint is muted permanently once any
    tool call succeeds (proof of tool support); /clear and
    /provider re-arm it so the next backend gets a fair
    re-evaluation.

v0.8.22 — /load crash fix + working /loop and /rewind in the playground.

New since v0.8.21

  • Fixed /load crash. CCUI_SessionListOutput concatenated a
    Harbour DATE with a string (DToS(d) + " " + d) inside the row
    formatter and raised Fatal: Argument error the first time
    /load was run against a sessions directory that contained any
    saved file. The bug shipped in v0.8.21. Switched to
    DToC( mtime ) so the date renders as a plain string. Verified
    on Windows, macOS and Linux.
  • Playground /rewind [N]. Pops the conversation snapshot
    stack (capped at 20), restoring the message array and the
    cumulative usage counter to the state before the last user
    turn. Snapshots are pushed in handleSubmit just before the
    user message is appended, so slash commands and the
    API-key-missing branch do not push spurious entries.
  • Playground /loop <interval> <prompt>. Arms a
    setInterval that re-issues the prompt via handleSubmit
    every interval. Intervals accept s / m / h suffixes;
    bare numbers are seconds. /loop status, /loop stop and
    /loop clear mirror the native binary; ticks that would
    overlap a running turn are skipped.
  • Playground /clear now resets /loop and /rewind state.
    The handler flushes the rewind stack and cancels any armed
    loop alongside the existing project / conversation / usage
    reset.

v0.8.21 — /loop fixed-interval rerun + /rewind (double-tap Esc).

New since v0.8.20

  • /loop slash command. Re-run a prompt on a fixed interval,
    matching Claude Code's fixed-interval /loop. /loop 5m check CI
    arms a recurring turn every 5 minutes; intervals accept the s,
    m, h suffixes (a bare number is seconds). /loop /
    /loop status shows the active loop, /loop stop ends it while
    keeping the prompt text, /loop clear drops both. The sleep
    between turns is interruptible — pressing Esc ends the loop.
    Hooks in parallel to the existing /goal auto-continue, so
    /loop and /goal can be armed independently. Model-paced
    (self-scheduled) variant is not implemented in this release.
  • /rewind slash command + double-tap Esc. Undo the last
    conversation turn. /rewind pops one snapshot; /rewind N pops
    N. A double-tap of Esc (≤ 600 ms apart) at the idle prompt is
    detected in CCPROMPT_Poll and converted into a rewind
    interrupt kind, which CCREPL_PromptIdle returns as the literal
    /rewind. Snapshots are pushed before each user message,
    /init, /btw drain message, and /loop runner turn; the
    stack is capped at 20 entries (oldest falls off the bottom).
    Restored state covers aMsgs, s_cGoal, s_lGoalLooping,
    s_cLoopPrompt, s_nLoopIntervalSec, s_lLoopActive,
    s_lPlanMode, s_lLeanMode, s_hSessionUsage, and
    s_lCompactNudged. /clear and /load flush the stack. File
    modifications made by write / edit / shell are NOT rolled
    back — only the conversation.

v0.8.20 — Ask-prompt deadlock fix: non-TTY auto-deny + CCHARBOUR_ASK_TIMEOUT.

New since v0.8.19

  • Non-TTY auto-deny on ask prompts. When a tool gated ask
    fires and stdin is not a TTY (piped input, script -c, a
    background SSH exec_command, a CI runner), CCREPL_AskPerm
    used to call the line reader anyway and block forever — no human
    was at the keyboard to type y. Now the path is short-circuited
    with a one-line [non-interactive stdin -- '<tool>' denied]
    notice and the call is denied immediately, so the agent loop
    surfaces an Error: tool ... denied by user result and keeps
    moving instead of hanging.
  • CCHARBOUR_ASK_TIMEOUT env var. Bounds the wait even on a
    real TTY. Set to a positive integer number of seconds; if no
    answer is typed before the deadline, the REPL prints
    [no response in Ns -- denied] and the call is denied. Default
    (unset or 0) keeps the original blocking behaviour. Both safety
    nets fall back to deny — a missing human can never silently
    approve.
  • New CCREPL_ReadLineTimeout(nSecs) helper. Poll-based stdin
    reader that wakes every 500 ms via the new
    CCCON_StdInWait( nMs ) C primitive (POSIX select() on
    STDIN_FILENO in src/ccconsole_posix.c; WaitForSingleObject
    on the Win32 input handle in src/ccconsole.c). Same paste/echo
    conventions as CCREPL_ReadLine so the editing experience is
    unchanged when the user does type.

v0.8.19 — /compact slash command + auto context-fill warning.

New since v0.8.18

  • /compact slash command. Summarises the older part of the
    conversation into one synthetic system note, keeping the system
    prompt and the last 4 turns verbatim. A stateless one-shot call
    with a strict "preserve exact paths / identifiers / errors /
    code verbatim, no paraphrase, no preamble" instruction. Refuses
    to compact when the very last assistant turn has a dangling
    tool_call (no matching tool response yet), so a compaction
    cannot orphan a tool-call id mid-cycle.
  • Soft "/compact" hint when context fills up. After every
    successful turn CCREPL_MaybeWarnCompact compares the last
    prompt_tokens against compact_threshold (default 0.7) of
    the model's context window and prints
    [context X% full -- run /compact ...] one time. Re-armable on
    /clear or after a successful /compact. Never auto-runs.
  • Per-model context windows. CCREPL_ModelContext maps the
    active model to its context size (deepseek 128k, kimi-k2 200k,
    gpt-5 400k, ...) with a 32k fallback.
  • compact_threshold setting. New 0.7 default in
    CCSETTINGS_Defaults; users can tune it per project.
  • dispatch_agent_background ungated. Added to the never-gated
    list in CCPERM_Decide alongside dispatch_agent /
    propose_agents — same consent model.

v0.8.18 — Background subagents: dispatch_agent_background tool + /tasks slash command.

New since v0.8.17

  • dispatch_agent_background tool. Fire-and-forget variant of
    dispatch_agent. Returns a task-id (bg1, bg2, ...) IMMEDIATELY
    without blocking the parent. A fresh hb_threadStart worker runs
    CC_AgentRun in the background and writes progress into an in-
    memory registry; the parent agent can chain its next step right
    away.
  • Background-task registry (src/ccbg.prg). Mutex-protected
    hash keyed by task id. Each record carries id, type, prompt,
    timeout, status (queued / running / done / failed /
    cancelled / timed_out), started_ms, ended_ms,
    iterations, reply, error, cancel_requested. Public API:
    CCBG_NextId / Add / Update / Get / List / Kill / CancelRequested / ClearFinished. Workers MUST NOT touch the terminal (that would
    corrupt the dynamic input box); the main REPL polls the registry.
  • /tasks slash command. The user's only window into the
    registry:
    • /tasks -- tabular list (id, status, elapsed, type, prompt
      summary).
    • /tasks view <id> -- full record including reply / error.
    • /tasks kill <id> -- request cancel; worker exits at next
      agent-loop boundary.
    • /tasks clear -- drop every finished / failed / cancelled
      / timed-out record.
  • Subagent filter widened. CCTOOLS_FilterForAgent removes BOTH
    dispatch_agent and dispatch_agent_background from a subagent's
    registry, so a subagent cannot spawn its own subagents (no
    unbounded recursion).
  • Help, README and pages/commands.md updated with the new
    command rows.

v0.8.17 — /save and /load now round-trip the full session state: goal, modes, skills, timer, and the pending suggestion.

New since v0.8.16

  • /save / /load preserve every REPL-level static, not just the
    conversation.
    Saved JSON now carries a new state block plus a
    suggest string in addition to model / usage / messages.
    /load restores them on top of the conversation so a reload is
    truly a full snapshot.
  • state block. CCREPL_StateExport() packs the current
    goal, goal_looping, session_turn_ms, plan_mode, lean_mode,
    and skills (active skill names) into a primitive hash.
    CCREPL_StateImport( hState ) reapplies them, silently skipping
    missing keys so legacy session files still load cleanly.
  • suggest field. The pending "Suggested next:" prompt that the
    model emitted on its last turn is persisted alongside...
Read more

v0.8.22

26 May 07:21

Choose a tag to compare

CCHarbour v0.8.22 — /load crash fix + working /loop and /rewind in the playground.

New since v0.8.21

  • Fixed /load crash. CCUI_SessionListOutput concatenated a
    Harbour DATE with a string (DToS(d) + " " + d) inside the row
    formatter and raised Fatal: Argument error the first time
    /load was run against a sessions directory that contained any
    saved file. The bug shipped in v0.8.21. Switched to
    DToC( mtime ) so the date renders as a plain string. Verified
    on Windows, macOS and Linux.
  • Playground /rewind [N]. Pops the conversation snapshot
    stack (capped at 20), restoring the message array and the
    cumulative usage counter to the state before the last user
    turn. Snapshots are pushed in handleSubmit just before the
    user message is appended, so slash commands and the
    API-key-missing branch do not push spurious entries.
  • Playground /loop <interval> <prompt>. Arms a
    setInterval that re-issues the prompt via handleSubmit
    every interval. Intervals accept s / m / h suffixes;
    bare numbers are seconds. /loop status, /loop stop and
    /loop clear mirror the native binary; ticks that would
    overlap a running turn are skipped.
  • Playground /clear now resets /loop and /rewind state.
    The handler flushes the rewind stack and cancels any armed
    loop alongside the existing project / conversation / usage
    reset.

v0.8.21 — /loop fixed-interval rerun + /rewind (double-tap Esc).

New since v0.8.20

  • /loop slash command. Re-run a prompt on a fixed interval,
    matching Claude Code's fixed-interval /loop. /loop 5m check CI
    arms a recurring turn every 5 minutes; intervals accept the s,
    m, h suffixes (a bare number is seconds). /loop /
    /loop status shows the active loop, /loop stop ends it while
    keeping the prompt text, /loop clear drops both. The sleep
    between turns is interruptible — pressing Esc ends the loop.
    Hooks in parallel to the existing /goal auto-continue, so
    /loop and /goal can be armed independently. Model-paced
    (self-scheduled) variant is not implemented in this release.
  • /rewind slash command + double-tap Esc. Undo the last
    conversation turn. /rewind pops one snapshot; /rewind N pops
    N. A double-tap of Esc (≤ 600 ms apart) at the idle prompt is
    detected in CCPROMPT_Poll and converted into a rewind
    interrupt kind, which CCREPL_PromptIdle returns as the literal
    /rewind. Snapshots are pushed before each user message,
    /init, /btw drain message, and /loop runner turn; the
    stack is capped at 20 entries (oldest falls off the bottom).
    Restored state covers aMsgs, s_cGoal, s_lGoalLooping,
    s_cLoopPrompt, s_nLoopIntervalSec, s_lLoopActive,
    s_lPlanMode, s_lLeanMode, s_hSessionUsage, and
    s_lCompactNudged. /clear and /load flush the stack. File
    modifications made by write / edit / shell are NOT rolled
    back — only the conversation.

v0.8.20 — Ask-prompt deadlock fix: non-TTY auto-deny + CCHARBOUR_ASK_TIMEOUT.

New since v0.8.19

  • Non-TTY auto-deny on ask prompts. When a tool gated ask
    fires and stdin is not a TTY (piped input, script -c, a
    background SSH exec_command, a CI runner), CCREPL_AskPerm
    used to call the line reader anyway and block forever — no human
    was at the keyboard to type y. Now the path is short-circuited
    with a one-line [non-interactive stdin -- '<tool>' denied]
    notice and the call is denied immediately, so the agent loop
    surfaces an Error: tool ... denied by user result and keeps
    moving instead of hanging.
  • CCHARBOUR_ASK_TIMEOUT env var. Bounds the wait even on a
    real TTY. Set to a positive integer number of seconds; if no
    answer is typed before the deadline, the REPL prints
    [no response in Ns -- denied] and the call is denied. Default
    (unset or 0) keeps the original blocking behaviour. Both safety
    nets fall back to deny — a missing human can never silently
    approve.
  • New CCREPL_ReadLineTimeout(nSecs) helper. Poll-based stdin
    reader that wakes every 500 ms via the new
    CCCON_StdInWait( nMs ) C primitive (POSIX select() on
    STDIN_FILENO in src/ccconsole_posix.c; WaitForSingleObject
    on the Win32 input handle in src/ccconsole.c). Same paste/echo
    conventions as CCREPL_ReadLine so the editing experience is
    unchanged when the user does type.

v0.8.19 — /compact slash command + auto context-fill warning.

New since v0.8.18

  • /compact slash command. Summarises the older part of the
    conversation into one synthetic system note, keeping the system
    prompt and the last 4 turns verbatim. A stateless one-shot call
    with a strict "preserve exact paths / identifiers / errors /
    code verbatim, no paraphrase, no preamble" instruction. Refuses
    to compact when the very last assistant turn has a dangling
    tool_call (no matching tool response yet), so a compaction
    cannot orphan a tool-call id mid-cycle.
  • Soft "/compact" hint when context fills up. After every
    successful turn CCREPL_MaybeWarnCompact compares the last
    prompt_tokens against compact_threshold (default 0.7) of
    the model's context window and prints
    [context X% full -- run /compact ...] one time. Re-armable on
    /clear or after a successful /compact. Never auto-runs.
  • Per-model context windows. CCREPL_ModelContext maps the
    active model to its context size (deepseek 128k, kimi-k2 200k,
    gpt-5 400k, ...) with a 32k fallback.
  • compact_threshold setting. New 0.7 default in
    CCSETTINGS_Defaults; users can tune it per project.
  • dispatch_agent_background ungated. Added to the never-gated
    list in CCPERM_Decide alongside dispatch_agent /
    propose_agents — same consent model.

v0.8.18 — Background subagents: dispatch_agent_background tool + /tasks slash command.

New since v0.8.17

  • dispatch_agent_background tool. Fire-and-forget variant of
    dispatch_agent. Returns a task-id (bg1, bg2, ...) IMMEDIATELY
    without blocking the parent. A fresh hb_threadStart worker runs
    CC_AgentRun in the background and writes progress into an in-
    memory registry; the parent agent can chain its next step right
    away.
  • Background-task registry (src/ccbg.prg). Mutex-protected
    hash keyed by task id. Each record carries id, type, prompt,
    timeout, status (queued / running / done / failed /
    cancelled / timed_out), started_ms, ended_ms,
    iterations, reply, error, cancel_requested. Public API:
    CCBG_NextId / Add / Update / Get / List / Kill / CancelRequested / ClearFinished. Workers MUST NOT touch the terminal (that would
    corrupt the dynamic input box); the main REPL polls the registry.
  • /tasks slash command. The user's only window into the
    registry:
    • /tasks -- tabular list (id, status, elapsed, type, prompt
      summary).
    • /tasks view <id> -- full record including reply / error.
    • /tasks kill <id> -- request cancel; worker exits at next
      agent-loop boundary.
    • /tasks clear -- drop every finished / failed / cancelled
      / timed-out record.
  • Subagent filter widened. CCTOOLS_FilterForAgent removes BOTH
    dispatch_agent and dispatch_agent_background from a subagent's
    registry, so a subagent cannot spawn its own subagents (no
    unbounded recursion).
  • Help, README and pages/commands.md updated with the new
    command rows.

v0.8.17 — /save and /load now round-trip the full session state: goal, modes, skills, timer, and the pending suggestion.

New since v0.8.16

  • /save / /load preserve every REPL-level static, not just the
    conversation.
    Saved JSON now carries a new state block plus a
    suggest string in addition to model / usage / messages.
    /load restores them on top of the conversation so a reload is
    truly a full snapshot.
  • state block. CCREPL_StateExport() packs the current
    goal, goal_looping, session_turn_ms, plan_mode, lean_mode,
    and skills (active skill names) into a primitive hash.
    CCREPL_StateImport( hState ) reapplies them, silently skipping
    missing keys so legacy session files still load cleanly.
  • suggest field. The pending "Suggested next:" prompt that the
    model emitted on its last turn is persisted alongside the messages
    and re-seeded into the editor on the first idle frame after
    /load, so the green Tab-acceptable preview survives a restart.
  • CCSKILL_ClearAll(). New helper that drops every active skill
    in one shot; called by CCREPL_StateImport before re-activating the
    loaded skill list so the restored set takes over from whatever was
    active.

v0.8.16 — /goal turns into "keep working until the condition is met": auto-continue loop + GOAL COMPLETE sentinel.

New since v0.8.15

  • /goal redesigned around "keep working until the condition is met".
    Setting a goal now arms an auto-continue loop in the main REPL:
    after every user-initiated turn the loop scans the last assistant
    reply for a literal GOAL COMPLETE sentinel. If absent it auto-
    feeds Continue toward the goal. ...reply with ONLY the literal sentinel... as the next user message and runs another turn.
  • GOAL COMPLETE sentinel. The injected system note teaches the
    model to emit GOAL COMPLETE on its own line when the condition
    is met. CCREPL_GoalDone( cReply ) checks the substring.
  • CC_GOAL_AUTO_CAP = 25. Hard cap on auto-iterations per user
    turn so a stubborn model cannot loop forever; the REPL prints
    [goal auto-continue cap (25) hit ...] when it trips.
  • Esc pauses the loop. CCREPL_RunGoalLoop drains the
    CCPROMPT_Interrupted flag and disarms s_lGoalLooping ...
Read more

v0.8.21

26 May 06:25

Choose a tag to compare

CCHarbour v0.8.21 — /loop fixed-interval rerun + /rewind (double-tap Esc).

New since v0.8.20

  • /loop slash command. Re-run a prompt on a fixed interval,
    matching Claude Code's fixed-interval /loop. /loop 5m check CI
    arms a recurring turn every 5 minutes; intervals accept the s,
    m, h suffixes (a bare number is seconds). /loop /
    /loop status shows the active loop, /loop stop ends it while
    keeping the prompt text, /loop clear drops both. The sleep
    between turns is interruptible — pressing Esc ends the loop.
    Hooks in parallel to the existing /goal auto-continue, so
    /loop and /goal can be armed independently. Model-paced
    (self-scheduled) variant is not implemented in this release.
  • /rewind slash command + double-tap Esc. Undo the last
    conversation turn. /rewind pops one snapshot; /rewind N pops
    N. A double-tap of Esc (≤ 600 ms apart) at the idle prompt is
    detected in CCPROMPT_Poll and converted into a rewind
    interrupt kind, which CCREPL_PromptIdle returns as the literal
    /rewind. Snapshots are pushed before each user message,
    /init, /btw drain message, and /loop runner turn; the
    stack is capped at 20 entries (oldest falls off the bottom).
    Restored state covers aMsgs, s_cGoal, s_lGoalLooping,
    s_cLoopPrompt, s_nLoopIntervalSec, s_lLoopActive,
    s_lPlanMode, s_lLeanMode, s_hSessionUsage, and
    s_lCompactNudged. /clear and /load flush the stack. File
    modifications made by write / edit / shell are NOT rolled
    back — only the conversation.

v0.8.20 — Ask-prompt deadlock fix: non-TTY auto-deny + CCHARBOUR_ASK_TIMEOUT.

New since v0.8.19

  • Non-TTY auto-deny on ask prompts. When a tool gated ask
    fires and stdin is not a TTY (piped input, script -c, a
    background SSH exec_command, a CI runner), CCREPL_AskPerm
    used to call the line reader anyway and block forever — no human
    was at the keyboard to type y. Now the path is short-circuited
    with a one-line [non-interactive stdin -- '<tool>' denied]
    notice and the call is denied immediately, so the agent loop
    surfaces an Error: tool ... denied by user result and keeps
    moving instead of hanging.
  • CCHARBOUR_ASK_TIMEOUT env var. Bounds the wait even on a
    real TTY. Set to a positive integer number of seconds; if no
    answer is typed before the deadline, the REPL prints
    [no response in Ns -- denied] and the call is denied. Default
    (unset or 0) keeps the original blocking behaviour. Both safety
    nets fall back to deny — a missing human can never silently
    approve.
  • New CCREPL_ReadLineTimeout(nSecs) helper. Poll-based stdin
    reader that wakes every 500 ms via the new
    CCCON_StdInWait( nMs ) C primitive (POSIX select() on
    STDIN_FILENO in src/ccconsole_posix.c; WaitForSingleObject
    on the Win32 input handle in src/ccconsole.c). Same paste/echo
    conventions as CCREPL_ReadLine so the editing experience is
    unchanged when the user does type.

v0.8.19 — /compact slash command + auto context-fill warning.

New since v0.8.18

  • /compact slash command. Summarises the older part of the
    conversation into one synthetic system note, keeping the system
    prompt and the last 4 turns verbatim. A stateless one-shot call
    with a strict "preserve exact paths / identifiers / errors /
    code verbatim, no paraphrase, no preamble" instruction. Refuses
    to compact when the very last assistant turn has a dangling
    tool_call (no matching tool response yet), so a compaction
    cannot orphan a tool-call id mid-cycle.
  • Soft "/compact" hint when context fills up. After every
    successful turn CCREPL_MaybeWarnCompact compares the last
    prompt_tokens against compact_threshold (default 0.7) of
    the model's context window and prints
    [context X% full -- run /compact ...] one time. Re-armable on
    /clear or after a successful /compact. Never auto-runs.
  • Per-model context windows. CCREPL_ModelContext maps the
    active model to its context size (deepseek 128k, kimi-k2 200k,
    gpt-5 400k, ...) with a 32k fallback.
  • compact_threshold setting. New 0.7 default in
    CCSETTINGS_Defaults; users can tune it per project.
  • dispatch_agent_background ungated. Added to the never-gated
    list in CCPERM_Decide alongside dispatch_agent /
    propose_agents — same consent model.

v0.8.18 — Background subagents: dispatch_agent_background tool + /tasks slash command.

New since v0.8.17

  • dispatch_agent_background tool. Fire-and-forget variant of
    dispatch_agent. Returns a task-id (bg1, bg2, ...) IMMEDIATELY
    without blocking the parent. A fresh hb_threadStart worker runs
    CC_AgentRun in the background and writes progress into an in-
    memory registry; the parent agent can chain its next step right
    away.
  • Background-task registry (src/ccbg.prg). Mutex-protected
    hash keyed by task id. Each record carries id, type, prompt,
    timeout, status (queued / running / done / failed /
    cancelled / timed_out), started_ms, ended_ms,
    iterations, reply, error, cancel_requested. Public API:
    CCBG_NextId / Add / Update / Get / List / Kill / CancelRequested / ClearFinished. Workers MUST NOT touch the terminal (that would
    corrupt the dynamic input box); the main REPL polls the registry.
  • /tasks slash command. The user's only window into the
    registry:
    • /tasks -- tabular list (id, status, elapsed, type, prompt
      summary).
    • /tasks view <id> -- full record including reply / error.
    • /tasks kill <id> -- request cancel; worker exits at next
      agent-loop boundary.
    • /tasks clear -- drop every finished / failed / cancelled
      / timed-out record.
  • Subagent filter widened. CCTOOLS_FilterForAgent removes BOTH
    dispatch_agent and dispatch_agent_background from a subagent's
    registry, so a subagent cannot spawn its own subagents (no
    unbounded recursion).
  • Help, README and pages/commands.md updated with the new
    command rows.

v0.8.17 — /save and /load now round-trip the full session state: goal, modes, skills, timer, and the pending suggestion.

New since v0.8.16

  • /save / /load preserve every REPL-level static, not just the
    conversation.
    Saved JSON now carries a new state block plus a
    suggest string in addition to model / usage / messages.
    /load restores them on top of the conversation so a reload is
    truly a full snapshot.
  • state block. CCREPL_StateExport() packs the current
    goal, goal_looping, session_turn_ms, plan_mode, lean_mode,
    and skills (active skill names) into a primitive hash.
    CCREPL_StateImport( hState ) reapplies them, silently skipping
    missing keys so legacy session files still load cleanly.
  • suggest field. The pending "Suggested next:" prompt that the
    model emitted on its last turn is persisted alongside the messages
    and re-seeded into the editor on the first idle frame after
    /load, so the green Tab-acceptable preview survives a restart.
  • CCSKILL_ClearAll(). New helper that drops every active skill
    in one shot; called by CCREPL_StateImport before re-activating the
    loaded skill list so the restored set takes over from whatever was
    active.

v0.8.16 — /goal turns into "keep working until the condition is met": auto-continue loop + GOAL COMPLETE sentinel.

New since v0.8.15

  • /goal redesigned around "keep working until the condition is met".
    Setting a goal now arms an auto-continue loop in the main REPL:
    after every user-initiated turn the loop scans the last assistant
    reply for a literal GOAL COMPLETE sentinel. If absent it auto-
    feeds Continue toward the goal. ...reply with ONLY the literal sentinel... as the next user message and runs another turn.
  • GOAL COMPLETE sentinel. The injected system note teaches the
    model to emit GOAL COMPLETE on its own line when the condition
    is met. CCREPL_GoalDone( cReply ) checks the substring.
  • CC_GOAL_AUTO_CAP = 25. Hard cap on auto-iterations per user
    turn so a stubborn model cannot loop forever; the REPL prints
    [goal auto-continue cap (25) hit ...] when it trips.
  • Esc pauses the loop. CCREPL_RunGoalLoop drains the
    CCPROMPT_Interrupted flag and disarms s_lGoalLooping without
    dropping the goal text -- [goal auto-continue paused by Esc -- /goal <text> or a new message to restart].
  • /goal stop. New sub-command that pauses the auto-continue
    loop without clearing the goal text (so the badge stays on).
    /goal clear still drops the goal entirely and disarms the loop.
  • Per-iteration progress line. [goal auto-continue N/25] prints
    before each automatic turn so the user can see the loop ticking.

v0.8.15 — /goal slash command: pin a session-wide objective the agent carries through every turn.

New since v0.8.14

  • /goal slash command. Pins a session-wide objective the agent
    carries through every subsequent turn until it is changed or
    cleared:
    • /goal — show the current goal (or (none)).
    • /goal <text> — store the goal AND inject it into the
      conversation as a system note, so the model sees the intent on
      the very next request without re-sending the goal on every
      turn.
    • /goal clear (alias /goal off) — drop the goal and tell the
      model to stop treating it as a constraint.
  • [goal] badge. When a goal is set, the status line under the
    input box shows a [goal] tag alongside [plan-mode] / [lean].
  • /clear resets the goal too. Resetting the conversation also
    clears the session goal and the session-turn timer accumulator, so
    the next session starts blank...
Read more

v0.8.20

25 May 21:50

Choose a tag to compare

CCHarbour v0.8.20 — Ask-prompt deadlock fix: non-TTY auto-deny + CCHARBOUR_ASK_TIMEOUT.

New since v0.8.19

  • Non-TTY auto-deny on ask prompts. When a tool gated ask
    fires and stdin is not a TTY (piped input, script -c, a
    background SSH exec_command, a CI runner), CCREPL_AskPerm
    used to call the line reader anyway and block forever — no human
    was at the keyboard to type y. Now the path is short-circuited
    with a one-line [non-interactive stdin -- '<tool>' denied]
    notice and the call is denied immediately, so the agent loop
    surfaces an Error: tool ... denied by user result and keeps
    moving instead of hanging.
  • CCHARBOUR_ASK_TIMEOUT env var. Bounds the wait even on a
    real TTY. Set to a positive integer number of seconds; if no
    answer is typed before the deadline, the REPL prints
    [no response in Ns -- denied] and the call is denied. Default
    (unset or 0) keeps the original blocking behaviour. Both safety
    nets fall back to deny — a missing human can never silently
    approve.
  • New CCREPL_ReadLineTimeout(nSecs) helper. Poll-based stdin
    reader that wakes every 500 ms via the new
    CCCON_StdInWait( nMs ) C primitive (POSIX select() on
    STDIN_FILENO in src/ccconsole_posix.c; WaitForSingleObject
    on the Win32 input handle in src/ccconsole.c). Same paste/echo
    conventions as CCREPL_ReadLine so the editing experience is
    unchanged when the user does type.

v0.8.19 — /compact slash command + auto context-fill warning.

New since v0.8.18

  • /compact slash command. Summarises the older part of the
    conversation into one synthetic system note, keeping the system
    prompt and the last 4 turns verbatim. A stateless one-shot call
    with a strict "preserve exact paths / identifiers / errors /
    code verbatim, no paraphrase, no preamble" instruction. Refuses
    to compact when the very last assistant turn has a dangling
    tool_call (no matching tool response yet), so a compaction
    cannot orphan a tool-call id mid-cycle.
  • Soft "/compact" hint when context fills up. After every
    successful turn CCREPL_MaybeWarnCompact compares the last
    prompt_tokens against compact_threshold (default 0.7) of
    the model's context window and prints
    [context X% full -- run /compact ...] one time. Re-armable on
    /clear or after a successful /compact. Never auto-runs.
  • Per-model context windows. CCREPL_ModelContext maps the
    active model to its context size (deepseek 128k, kimi-k2 200k,
    gpt-5 400k, ...) with a 32k fallback.
  • compact_threshold setting. New 0.7 default in
    CCSETTINGS_Defaults; users can tune it per project.
  • dispatch_agent_background ungated. Added to the never-gated
    list in CCPERM_Decide alongside dispatch_agent /
    propose_agents — same consent model.

v0.8.18 — Background subagents: dispatch_agent_background tool + /tasks slash command.

New since v0.8.17

  • dispatch_agent_background tool. Fire-and-forget variant of
    dispatch_agent. Returns a task-id (bg1, bg2, ...) IMMEDIATELY
    without blocking the parent. A fresh hb_threadStart worker runs
    CC_AgentRun in the background and writes progress into an in-
    memory registry; the parent agent can chain its next step right
    away.
  • Background-task registry (src/ccbg.prg). Mutex-protected
    hash keyed by task id. Each record carries id, type, prompt,
    timeout, status (queued / running / done / failed /
    cancelled / timed_out), started_ms, ended_ms,
    iterations, reply, error, cancel_requested. Public API:
    CCBG_NextId / Add / Update / Get / List / Kill / CancelRequested / ClearFinished. Workers MUST NOT touch the terminal (that would
    corrupt the dynamic input box); the main REPL polls the registry.
  • /tasks slash command. The user's only window into the
    registry:
    • /tasks -- tabular list (id, status, elapsed, type, prompt
      summary).
    • /tasks view <id> -- full record including reply / error.
    • /tasks kill <id> -- request cancel; worker exits at next
      agent-loop boundary.
    • /tasks clear -- drop every finished / failed / cancelled
      / timed-out record.
  • Subagent filter widened. CCTOOLS_FilterForAgent removes BOTH
    dispatch_agent and dispatch_agent_background from a subagent's
    registry, so a subagent cannot spawn its own subagents (no
    unbounded recursion).
  • Help, README and pages/commands.md updated with the new
    command rows.

v0.8.17 — /save and /load now round-trip the full session state: goal, modes, skills, timer, and the pending suggestion.

New since v0.8.16

  • /save / /load preserve every REPL-level static, not just the
    conversation.
    Saved JSON now carries a new state block plus a
    suggest string in addition to model / usage / messages.
    /load restores them on top of the conversation so a reload is
    truly a full snapshot.
  • state block. CCREPL_StateExport() packs the current
    goal, goal_looping, session_turn_ms, plan_mode, lean_mode,
    and skills (active skill names) into a primitive hash.
    CCREPL_StateImport( hState ) reapplies them, silently skipping
    missing keys so legacy session files still load cleanly.
  • suggest field. The pending "Suggested next:" prompt that the
    model emitted on its last turn is persisted alongside the messages
    and re-seeded into the editor on the first idle frame after
    /load, so the green Tab-acceptable preview survives a restart.
  • CCSKILL_ClearAll(). New helper that drops every active skill
    in one shot; called by CCREPL_StateImport before re-activating the
    loaded skill list so the restored set takes over from whatever was
    active.

v0.8.16 — /goal turns into "keep working until the condition is met": auto-continue loop + GOAL COMPLETE sentinel.

New since v0.8.15

  • /goal redesigned around "keep working until the condition is met".
    Setting a goal now arms an auto-continue loop in the main REPL:
    after every user-initiated turn the loop scans the last assistant
    reply for a literal GOAL COMPLETE sentinel. If absent it auto-
    feeds Continue toward the goal. ...reply with ONLY the literal sentinel... as the next user message and runs another turn.
  • GOAL COMPLETE sentinel. The injected system note teaches the
    model to emit GOAL COMPLETE on its own line when the condition
    is met. CCREPL_GoalDone( cReply ) checks the substring.
  • CC_GOAL_AUTO_CAP = 25. Hard cap on auto-iterations per user
    turn so a stubborn model cannot loop forever; the REPL prints
    [goal auto-continue cap (25) hit ...] when it trips.
  • Esc pauses the loop. CCREPL_RunGoalLoop drains the
    CCPROMPT_Interrupted flag and disarms s_lGoalLooping without
    dropping the goal text -- [goal auto-continue paused by Esc -- /goal <text> or a new message to restart].
  • /goal stop. New sub-command that pauses the auto-continue
    loop without clearing the goal text (so the badge stays on).
    /goal clear still drops the goal entirely and disarms the loop.
  • Per-iteration progress line. [goal auto-continue N/25] prints
    before each automatic turn so the user can see the loop ticking.

v0.8.15 — /goal slash command: pin a session-wide objective the agent carries through every turn.

New since v0.8.14

  • /goal slash command. Pins a session-wide objective the agent
    carries through every subsequent turn until it is changed or
    cleared:
    • /goal — show the current goal (or (none)).
    • /goal <text> — store the goal AND inject it into the
      conversation as a system note, so the model sees the intent on
      the very next request without re-sending the goal on every
      turn.
    • /goal clear (alias /goal off) — drop the goal and tell the
      model to stop treating it as a constraint.
  • [goal] badge. When a goal is set, the status line under the
    input box shows a [goal] tag alongside [plan-mode] / [lean].
  • /clear resets the goal too. Resetting the conversation also
    clears the session goal and the session-turn timer accumulator, so
    the next session starts blank.

v0.8.14 — Shell countdown lands above the box, diff bars equal width + bright-white text.

New since v0.8.13

  • Shell command countdown no longer painted inside the input box.
    CCTool_ShowCountdown / CCTool_ClearCountdown route through the
    CCREPL_OverwriteAtAnchor helper when the persistent box is
    mounted, so timeout 300s · 252s left lands on the scroll-region
    anchor above the box and a trailing CCREPL_Out( Chr(10) ) bakes
    the final value in for the result summary. The plain-CR fallback
    is kept for cooked / non-VT terminals.
  • Diff bars are all the same width. CCUI_ResultBlock scans the
    diff once for the widest added/removed line (floor 110), then pads
    every coloured bar to that width via CCUI_DiffPad( cLine, nWidth )
    -- no more ragged edges when one line is longer than the rest.
  • Diff text rendered in bright white. Added lines go from SGR
    37;42 to 97;42, removed from 48;5;52 to 97;48;5;52 -- the
    red bar now matches the green bar's contrast.

v0.8.13 — Dynamic-box paint hardening, live timing in the spinner / token bar, /provider key picked up on the next turn.

New since v0.8.12

  • Banner anchored at row 1. CCREPL_Run emits ESC[H ESC[2J
    before printing the banner so it is always at rows 1..N and the
    CCPROMPT_Activate( nHeaderRows + 1 ) anchor lands exactly below it.
    Previously the banner started at the cursor's row (often row 2 after
    the shell cc line), so subsequent writes overwrote the banner's
    bottom border.
  • Box paint uses absolute cursor jumps. `CC...
Read more

v0.8.19 — /compact + auto context-fill warning

25 May 10:03

Choose a tag to compare

CCHarbour v0.8.19 — /compact slash command + auto context-fill warning.

New since v0.8.18

  • /compact slash command. Summarises the older part of the
    conversation into one synthetic system note, keeping the system
    prompt and the last 4 turns verbatim. A stateless one-shot call
    with a strict "preserve exact paths / identifiers / errors /
    code verbatim, no paraphrase, no preamble" instruction. Refuses
    to compact when the very last assistant turn has a dangling
    tool_call (no matching tool response yet), so a compaction
    cannot orphan a tool-call id mid-cycle.
  • Soft "/compact" hint when context fills up. After every
    successful turn CCREPL_MaybeWarnCompact compares the last
    prompt_tokens against compact_threshold (default 0.7) of
    the model's context window and prints
    [context X% full -- run /compact ...] one time. Re-armable on
    /clear or after a successful /compact. Never auto-runs.
  • Per-model context windows. CCREPL_ModelContext maps the
    active model to its context size (deepseek 128k, kimi-k2 200k,
    gpt-5 400k, ...) with a 32k fallback.
  • compact_threshold setting. New 0.7 default in
    CCSETTINGS_Defaults; users can tune it per project.
  • dispatch_agent_background ungated. Added to the never-gated
    list in CCPERM_Decide alongside dispatch_agent /
    propose_agents — same consent model.

v0.8.18 — Background subagents: dispatch_agent_background tool + /tasks slash command.

New since v0.8.17

  • dispatch_agent_background tool. Fire-and-forget variant of
    dispatch_agent. Returns a task-id (bg1, bg2, ...) IMMEDIATELY
    without blocking the parent. A fresh hb_threadStart worker runs
    CC_AgentRun in the background and writes progress into an in-
    memory registry; the parent agent can chain its next step right
    away.
  • Background-task registry (src/ccbg.prg). Mutex-protected
    hash keyed by task id. Each record carries id, type, prompt,
    timeout, status (queued / running / done / failed /
    cancelled / timed_out), started_ms, ended_ms,
    iterations, reply, error, cancel_requested. Public API:
    CCBG_NextId / Add / Update / Get / List / Kill / CancelRequested / ClearFinished. Workers MUST NOT touch the terminal (that would
    corrupt the dynamic input box); the main REPL polls the registry.
  • /tasks slash command. The user's only window into the
    registry:
    • /tasks -- tabular list (id, status, elapsed, type, prompt
      summary).
    • /tasks view <id> -- full record including reply / error.
    • /tasks kill <id> -- request cancel; worker exits at next
      agent-loop boundary.
    • /tasks clear -- drop every finished / failed / cancelled
      / timed-out record.
  • Subagent filter widened. CCTOOLS_FilterForAgent removes BOTH
    dispatch_agent and dispatch_agent_background from a subagent's
    registry, so a subagent cannot spawn its own subagents (no
    unbounded recursion).
  • Help, README and pages/commands.md updated with the new
    command rows.

v0.8.17 — /save and /load now round-trip the full session state: goal, modes, skills, timer, and the pending suggestion.

New since v0.8.16

  • /save / /load preserve every REPL-level static, not just the
    conversation.
    Saved JSON now carries a new state block plus a
    suggest string in addition to model / usage / messages.
    /load restores them on top of the conversation so a reload is
    truly a full snapshot.
  • state block. CCREPL_StateExport() packs the current
    goal, goal_looping, session_turn_ms, plan_mode, lean_mode,
    and skills (active skill names) into a primitive hash.
    CCREPL_StateImport( hState ) reapplies them, silently skipping
    missing keys so legacy session files still load cleanly.
  • suggest field. The pending "Suggested next:" prompt that the
    model emitted on its last turn is persisted alongside the messages
    and re-seeded into the editor on the first idle frame after
    /load, so the green Tab-acceptable preview survives a restart.
  • CCSKILL_ClearAll(). New helper that drops every active skill
    in one shot; called by CCREPL_StateImport before re-activating the
    loaded skill list so the restored set takes over from whatever was
    active.

v0.8.16 — /goal turns into "keep working until the condition is met": auto-continue loop + GOAL COMPLETE sentinel.

New since v0.8.15

  • /goal redesigned around "keep working until the condition is met".
    Setting a goal now arms an auto-continue loop in the main REPL:
    after every user-initiated turn the loop scans the last assistant
    reply for a literal GOAL COMPLETE sentinel. If absent it auto-
    feeds Continue toward the goal. ...reply with ONLY the literal sentinel... as the next user message and runs another turn.
  • GOAL COMPLETE sentinel. The injected system note teaches the
    model to emit GOAL COMPLETE on its own line when the condition
    is met. CCREPL_GoalDone( cReply ) checks the substring.
  • CC_GOAL_AUTO_CAP = 25. Hard cap on auto-iterations per user
    turn so a stubborn model cannot loop forever; the REPL prints
    [goal auto-continue cap (25) hit ...] when it trips.
  • Esc pauses the loop. CCREPL_RunGoalLoop drains the
    CCPROMPT_Interrupted flag and disarms s_lGoalLooping without
    dropping the goal text -- [goal auto-continue paused by Esc -- /goal <text> or a new message to restart].
  • /goal stop. New sub-command that pauses the auto-continue
    loop without clearing the goal text (so the badge stays on).
    /goal clear still drops the goal entirely and disarms the loop.
  • Per-iteration progress line. [goal auto-continue N/25] prints
    before each automatic turn so the user can see the loop ticking.

v0.8.15 — /goal slash command: pin a session-wide objective the agent carries through every turn.

New since v0.8.14

  • /goal slash command. Pins a session-wide objective the agent
    carries through every subsequent turn until it is changed or
    cleared:
    • /goal — show the current goal (or (none)).
    • /goal <text> — store the goal AND inject it into the
      conversation as a system note, so the model sees the intent on
      the very next request without re-sending the goal on every
      turn.
    • /goal clear (alias /goal off) — drop the goal and tell the
      model to stop treating it as a constraint.
  • [goal] badge. When a goal is set, the status line under the
    input box shows a [goal] tag alongside [plan-mode] / [lean].
  • /clear resets the goal too. Resetting the conversation also
    clears the session goal and the session-turn timer accumulator, so
    the next session starts blank.

v0.8.14 — Shell countdown lands above the box, diff bars equal width + bright-white text.

New since v0.8.13

  • Shell command countdown no longer painted inside the input box.
    CCTool_ShowCountdown / CCTool_ClearCountdown route through the
    CCREPL_OverwriteAtAnchor helper when the persistent box is
    mounted, so timeout 300s · 252s left lands on the scroll-region
    anchor above the box and a trailing CCREPL_Out( Chr(10) ) bakes
    the final value in for the result summary. The plain-CR fallback
    is kept for cooked / non-VT terminals.
  • Diff bars are all the same width. CCUI_ResultBlock scans the
    diff once for the widest added/removed line (floor 110), then pads
    every coloured bar to that width via CCUI_DiffPad( cLine, nWidth )
    -- no more ragged edges when one line is longer than the rest.
  • Diff text rendered in bright white. Added lines go from SGR
    37;42 to 97;42, removed from 48;5;52 to 97;48;5;52 -- the
    red bar now matches the green bar's contrast.

v0.8.13 — Dynamic-box paint hardening, live timing in the spinner / token bar, /provider key picked up on the next turn.

New since v0.8.12

  • Banner anchored at row 1. CCREPL_Run emits ESC[H ESC[2J
    before printing the banner so it is always at rows 1..N and the
    CCPROMPT_Activate( nHeaderRows + 1 ) anchor lands exactly below it.
    Previously the banner started at the cursor's row (often row 2 after
    the shell cc line), so subsequent writes overwrote the banner's
    bottom border.
  • Box paint uses absolute cursor jumps. CCPROMPT_Redraw now
    positions every row of the four-row box with an absolute ESC[<row>;1H
    instead of chaining CRLFs. The CRLF chain scrolled the screen up by
    one row each time the box sat near the terminal bottom, which is how
    pressing Esc at the idle prompt could stack 10+ leftover frames
    above the box.
  • Wipe rule rewritten. The old-box-frame wipe in CCPROMPT_Redraw
    is now [oldBoxTop .. min(oldBoxTop+3, newBoxTop-1)] minus the rows just written. CCREPL_Out stashes last_write_start and a trailing
    -LF flag so Redraw knows where the chunk actually wrote. Fixes the
    FlushPending bullet ("\n + glyph + 2sp", no trailing LF) being
    wiped right after it was painted, and the stale top-frame left
    behind by multi-line writes (paragraph breaks in the streamed reply).
  • Banner scrolls when the box pins. CCPROMPT_Region sets
    scroll_top to 1 once box_top == nFloor, so the VT scroll region
    expands up to the top of the screen and the banner finally rolls off
    the top edge as new content arrives. While the box is still
    travelling the banner is still pinned (current behaviour).
  • Spinner shows elapsed seconds. iteration_start stamps a wall-
    clock in oRender[ "spinnerStartMs" ]; CCREPL_SpinnerShow appends
    Ns to the spinner line (e.g. ⠦ Thinking... [32 tok] 7s).
  • Token bar shows turn / session seconds. CCREPL_RunTurn times
    each turn with hb_MilliSeconds(), accumulates i...
Read more

v0.8.18 — background subagents + /tasks slash command

25 May 06:50

Choose a tag to compare

CCHarbour v0.8.18 — Background subagents: dispatch_agent_background tool + /tasks slash command.

New since v0.8.17

  • dispatch_agent_background tool. Fire-and-forget variant of
    dispatch_agent. Returns a task-id (bg1, bg2, ...) IMMEDIATELY
    without blocking the parent. A fresh hb_threadStart worker runs
    CC_AgentRun in the background and writes progress into an in-
    memory registry; the parent agent can chain its next step right
    away.
  • Background-task registry (src/ccbg.prg). Mutex-protected
    hash keyed by task id. Each record carries id, type, prompt,
    timeout, status (queued / running / done / failed /
    cancelled / timed_out), started_ms, ended_ms,
    iterations, reply, error, cancel_requested. Public API:
    CCBG_NextId / Add / Update / Get / List / Kill / CancelRequested / ClearFinished. Workers MUST NOT touch the terminal (that would
    corrupt the dynamic input box); the main REPL polls the registry.
  • /tasks slash command. The user's only window into the
    registry:
    • /tasks -- tabular list (id, status, elapsed, type, prompt
      summary).
    • /tasks view <id> -- full record including reply / error.
    • /tasks kill <id> -- request cancel; worker exits at next
      agent-loop boundary.
    • /tasks clear -- drop every finished / failed / cancelled
      / timed-out record.
  • Subagent filter widened. CCTOOLS_FilterForAgent removes BOTH
    dispatch_agent and dispatch_agent_background from a subagent's
    registry, so a subagent cannot spawn its own subagents (no
    unbounded recursion).
  • Help, README and pages/commands.md updated with the new
    command rows.

v0.8.17 — /save and /load now round-trip the full session state: goal, modes, skills, timer, and the pending suggestion.

New since v0.8.16

  • /save / /load preserve every REPL-level static, not just the
    conversation.
    Saved JSON now carries a new state block plus a
    suggest string in addition to model / usage / messages.
    /load restores them on top of the conversation so a reload is
    truly a full snapshot.
  • state block. CCREPL_StateExport() packs the current
    goal, goal_looping, session_turn_ms, plan_mode, lean_mode,
    and skills (active skill names) into a primitive hash.
    CCREPL_StateImport( hState ) reapplies them, silently skipping
    missing keys so legacy session files still load cleanly.
  • suggest field. The pending "Suggested next:" prompt that the
    model emitted on its last turn is persisted alongside the messages
    and re-seeded into the editor on the first idle frame after
    /load, so the green Tab-acceptable preview survives a restart.
  • CCSKILL_ClearAll(). New helper that drops every active skill
    in one shot; called by CCREPL_StateImport before re-activating the
    loaded skill list so the restored set takes over from whatever was
    active.

v0.8.16 — /goal turns into "keep working until the condition is met": auto-continue loop + GOAL COMPLETE sentinel.

New since v0.8.15

  • /goal redesigned around "keep working until the condition is met".
    Setting a goal now arms an auto-continue loop in the main REPL:
    after every user-initiated turn the loop scans the last assistant
    reply for a literal GOAL COMPLETE sentinel. If absent it auto-
    feeds Continue toward the goal. ...reply with ONLY the literal sentinel... as the next user message and runs another turn.
  • GOAL COMPLETE sentinel. The injected system note teaches the
    model to emit GOAL COMPLETE on its own line when the condition
    is met. CCREPL_GoalDone( cReply ) checks the substring.
  • CC_GOAL_AUTO_CAP = 25. Hard cap on auto-iterations per user
    turn so a stubborn model cannot loop forever; the REPL prints
    [goal auto-continue cap (25) hit ...] when it trips.
  • Esc pauses the loop. CCREPL_RunGoalLoop drains the
    CCPROMPT_Interrupted flag and disarms s_lGoalLooping without
    dropping the goal text -- [goal auto-continue paused by Esc -- /goal <text> or a new message to restart].
  • /goal stop. New sub-command that pauses the auto-continue
    loop without clearing the goal text (so the badge stays on).
    /goal clear still drops the goal entirely and disarms the loop.
  • Per-iteration progress line. [goal auto-continue N/25] prints
    before each automatic turn so the user can see the loop ticking.

v0.8.15 — /goal slash command: pin a session-wide objective the agent carries through every turn.

New since v0.8.14

  • /goal slash command. Pins a session-wide objective the agent
    carries through every subsequent turn until it is changed or
    cleared:
    • /goal — show the current goal (or (none)).
    • /goal <text> — store the goal AND inject it into the
      conversation as a system note, so the model sees the intent on
      the very next request without re-sending the goal on every
      turn.
    • /goal clear (alias /goal off) — drop the goal and tell the
      model to stop treating it as a constraint.
  • [goal] badge. When a goal is set, the status line under the
    input box shows a [goal] tag alongside [plan-mode] / [lean].
  • /clear resets the goal too. Resetting the conversation also
    clears the session goal and the session-turn timer accumulator, so
    the next session starts blank.

v0.8.14 — Shell countdown lands above the box, diff bars equal width + bright-white text.

New since v0.8.13

  • Shell command countdown no longer painted inside the input box.
    CCTool_ShowCountdown / CCTool_ClearCountdown route through the
    CCREPL_OverwriteAtAnchor helper when the persistent box is
    mounted, so timeout 300s · 252s left lands on the scroll-region
    anchor above the box and a trailing CCREPL_Out( Chr(10) ) bakes
    the final value in for the result summary. The plain-CR fallback
    is kept for cooked / non-VT terminals.
  • Diff bars are all the same width. CCUI_ResultBlock scans the
    diff once for the widest added/removed line (floor 110), then pads
    every coloured bar to that width via CCUI_DiffPad( cLine, nWidth )
    -- no more ragged edges when one line is longer than the rest.
  • Diff text rendered in bright white. Added lines go from SGR
    37;42 to 97;42, removed from 48;5;52 to 97;48;5;52 -- the
    red bar now matches the green bar's contrast.

v0.8.13 — Dynamic-box paint hardening, live timing in the spinner / token bar, /provider key picked up on the next turn.

New since v0.8.12

  • Banner anchored at row 1. CCREPL_Run emits ESC[H ESC[2J
    before printing the banner so it is always at rows 1..N and the
    CCPROMPT_Activate( nHeaderRows + 1 ) anchor lands exactly below it.
    Previously the banner started at the cursor's row (often row 2 after
    the shell cc line), so subsequent writes overwrote the banner's
    bottom border.
  • Box paint uses absolute cursor jumps. CCPROMPT_Redraw now
    positions every row of the four-row box with an absolute ESC[<row>;1H
    instead of chaining CRLFs. The CRLF chain scrolled the screen up by
    one row each time the box sat near the terminal bottom, which is how
    pressing Esc at the idle prompt could stack 10+ leftover frames
    above the box.
  • Wipe rule rewritten. The old-box-frame wipe in CCPROMPT_Redraw
    is now [oldBoxTop .. min(oldBoxTop+3, newBoxTop-1)] minus the rows just written. CCREPL_Out stashes last_write_start and a trailing
    -LF flag so Redraw knows where the chunk actually wrote. Fixes the
    FlushPending bullet ("\n + glyph + 2sp", no trailing LF) being
    wiped right after it was painted, and the stale top-frame left
    behind by multi-line writes (paragraph breaks in the streamed reply).
  • Banner scrolls when the box pins. CCPROMPT_Region sets
    scroll_top to 1 once box_top == nFloor, so the VT scroll region
    expands up to the top of the screen and the banner finally rolls off
    the top edge as new content arrives. While the box is still
    travelling the banner is still pinned (current behaviour).
  • Spinner shows elapsed seconds. iteration_start stamps a wall-
    clock in oRender[ "spinnerStartMs" ]; CCREPL_SpinnerShow appends
    Ns to the spinner line (e.g. ⠦ Thinking... [32 tok] 7s).
  • Token bar shows turn / session seconds. CCREPL_RunTurn times
    each turn with hb_MilliSeconds(), accumulates into a session-wide
    static, and passes the per-turn ms to CCREPL_ShowTokenBar. The bar
    now reads ▒ tokens in: 3670 out: 83 total: 3753 turn: 1.4s session: 7.2s. /clear resets the session counter.
  • dispatch_agent timer ticks down. The opening Agent block prints
    the separator / header / prompt and then drops a live elapsed-time
    line via the new CCREPL_OverwriteAtAnchor helper. The
    interrupt_check callback refreshes the line at ~2 Hz so the user
    sees Ns elapsed / Ms timeout · press Esc on the input box to cancel
    tick in place. A final CCREPL_Out bakes the value in and lets the
    "Agent done in X.Xs" line land below.
  • /provider key picked up on the next turn. CCCFG_Resolve now
    falls back to $CCHARBOUR_CONFIG (or .ccharbour/settings.json)
    when the env vars are empty, so a freshly-saved api_key reaches the
    next chat call without rebuilding the client.

v0.8.12 — Start without an API key, configure the backend interactively with /provider.

New since v0.8.11

  • Starts even with no API key configured. The session no longer
    exits with an error when DEEPSEEK_API_KEY is missing; the banner
    and the input box come up normally and a yellow warning under the
    banner tells the user to set up a backend.
  • /provider slash command — configure the backend at runtime:
    • /provider — show current base_url...
Read more

v0.8.17 — /save round-trips full session state

25 May 06:20

Choose a tag to compare

CCHarbour v0.8.17 — /save and /load now round-trip the full session state: goal, modes, skills, timer, and the pending suggestion.

New since v0.8.16

  • /save / /load preserve every REPL-level static, not just the
    conversation.
    Saved JSON now carries a new state block plus a
    suggest string in addition to model / usage / messages.
    /load restores them on top of the conversation so a reload is
    truly a full snapshot.
  • state block. CCREPL_StateExport() packs the current
    goal, goal_looping, session_turn_ms, plan_mode, lean_mode,
    and skills (active skill names) into a primitive hash.
    CCREPL_StateImport( hState ) reapplies them, silently skipping
    missing keys so legacy session files still load cleanly.
  • suggest field. The pending "Suggested next:" prompt that the
    model emitted on its last turn is persisted alongside the messages
    and re-seeded into the editor on the first idle frame after
    /load, so the green Tab-acceptable preview survives a restart.
  • CCSKILL_ClearAll(). New helper that drops every active skill
    in one shot; called by CCREPL_StateImport before re-activating the
    loaded skill list so the restored set takes over from whatever was
    active.

v0.8.16 — /goal turns into "keep working until the condition is met": auto-continue loop + GOAL COMPLETE sentinel.

New since v0.8.15

  • /goal redesigned around "keep working until the condition is met".
    Setting a goal now arms an auto-continue loop in the main REPL:
    after every user-initiated turn the loop scans the last assistant
    reply for a literal GOAL COMPLETE sentinel. If absent it auto-
    feeds Continue toward the goal. ...reply with ONLY the literal sentinel... as the next user message and runs another turn.
  • GOAL COMPLETE sentinel. The injected system note teaches the
    model to emit GOAL COMPLETE on its own line when the condition
    is met. CCREPL_GoalDone( cReply ) checks the substring.
  • CC_GOAL_AUTO_CAP = 25. Hard cap on auto-iterations per user
    turn so a stubborn model cannot loop forever; the REPL prints
    [goal auto-continue cap (25) hit ...] when it trips.
  • Esc pauses the loop. CCREPL_RunGoalLoop drains the
    CCPROMPT_Interrupted flag and disarms s_lGoalLooping without
    dropping the goal text -- [goal auto-continue paused by Esc -- /goal <text> or a new message to restart].
  • /goal stop. New sub-command that pauses the auto-continue
    loop without clearing the goal text (so the badge stays on).
    /goal clear still drops the goal entirely and disarms the loop.
  • Per-iteration progress line. [goal auto-continue N/25] prints
    before each automatic turn so the user can see the loop ticking.

v0.8.15 — /goal slash command: pin a session-wide objective the agent carries through every turn.

New since v0.8.14

  • /goal slash command. Pins a session-wide objective the agent
    carries through every subsequent turn until it is changed or
    cleared:
    • /goal — show the current goal (or (none)).
    • /goal <text> — store the goal AND inject it into the
      conversation as a system note, so the model sees the intent on
      the very next request without re-sending the goal on every
      turn.
    • /goal clear (alias /goal off) — drop the goal and tell the
      model to stop treating it as a constraint.
  • [goal] badge. When a goal is set, the status line under the
    input box shows a [goal] tag alongside [plan-mode] / [lean].
  • /clear resets the goal too. Resetting the conversation also
    clears the session goal and the session-turn timer accumulator, so
    the next session starts blank.

v0.8.14 — Shell countdown lands above the box, diff bars equal width + bright-white text.

New since v0.8.13

  • Shell command countdown no longer painted inside the input box.
    CCTool_ShowCountdown / CCTool_ClearCountdown route through the
    CCREPL_OverwriteAtAnchor helper when the persistent box is
    mounted, so timeout 300s · 252s left lands on the scroll-region
    anchor above the box and a trailing CCREPL_Out( Chr(10) ) bakes
    the final value in for the result summary. The plain-CR fallback
    is kept for cooked / non-VT terminals.
  • Diff bars are all the same width. CCUI_ResultBlock scans the
    diff once for the widest added/removed line (floor 110), then pads
    every coloured bar to that width via CCUI_DiffPad( cLine, nWidth )
    -- no more ragged edges when one line is longer than the rest.
  • Diff text rendered in bright white. Added lines go from SGR
    37;42 to 97;42, removed from 48;5;52 to 97;48;5;52 -- the
    red bar now matches the green bar's contrast.

v0.8.13 — Dynamic-box paint hardening, live timing in the spinner / token bar, /provider key picked up on the next turn.

New since v0.8.12

  • Banner anchored at row 1. CCREPL_Run emits ESC[H ESC[2J
    before printing the banner so it is always at rows 1..N and the
    CCPROMPT_Activate( nHeaderRows + 1 ) anchor lands exactly below it.
    Previously the banner started at the cursor's row (often row 2 after
    the shell cc line), so subsequent writes overwrote the banner's
    bottom border.
  • Box paint uses absolute cursor jumps. CCPROMPT_Redraw now
    positions every row of the four-row box with an absolute ESC[<row>;1H
    instead of chaining CRLFs. The CRLF chain scrolled the screen up by
    one row each time the box sat near the terminal bottom, which is how
    pressing Esc at the idle prompt could stack 10+ leftover frames
    above the box.
  • Wipe rule rewritten. The old-box-frame wipe in CCPROMPT_Redraw
    is now [oldBoxTop .. min(oldBoxTop+3, newBoxTop-1)] minus the rows just written. CCREPL_Out stashes last_write_start and a trailing
    -LF flag so Redraw knows where the chunk actually wrote. Fixes the
    FlushPending bullet ("\n + glyph + 2sp", no trailing LF) being
    wiped right after it was painted, and the stale top-frame left
    behind by multi-line writes (paragraph breaks in the streamed reply).
  • Banner scrolls when the box pins. CCPROMPT_Region sets
    scroll_top to 1 once box_top == nFloor, so the VT scroll region
    expands up to the top of the screen and the banner finally rolls off
    the top edge as new content arrives. While the box is still
    travelling the banner is still pinned (current behaviour).
  • Spinner shows elapsed seconds. iteration_start stamps a wall-
    clock in oRender[ "spinnerStartMs" ]; CCREPL_SpinnerShow appends
    Ns to the spinner line (e.g. ⠦ Thinking... [32 tok] 7s).
  • Token bar shows turn / session seconds. CCREPL_RunTurn times
    each turn with hb_MilliSeconds(), accumulates into a session-wide
    static, and passes the per-turn ms to CCREPL_ShowTokenBar. The bar
    now reads ▒ tokens in: 3670 out: 83 total: 3753 turn: 1.4s session: 7.2s. /clear resets the session counter.
  • dispatch_agent timer ticks down. The opening Agent block prints
    the separator / header / prompt and then drops a live elapsed-time
    line via the new CCREPL_OverwriteAtAnchor helper. The
    interrupt_check callback refreshes the line at ~2 Hz so the user
    sees Ns elapsed / Ms timeout · press Esc on the input box to cancel
    tick in place. A final CCREPL_Out bakes the value in and lets the
    "Agent done in X.Xs" line land below.
  • /provider key picked up on the next turn. CCCFG_Resolve now
    falls back to $CCHARBOUR_CONFIG (or .ccharbour/settings.json)
    when the env vars are empty, so a freshly-saved api_key reaches the
    next chat call without rebuilding the client.

v0.8.12 — Start without an API key, configure the backend interactively with /provider.

New since v0.8.11

  • Starts even with no API key configured. The session no longer
    exits with an error when DEEPSEEK_API_KEY is missing; the banner
    and the input box come up normally and a yellow warning under the
    banner tells the user to set up a backend.
  • /provider slash command — configure the backend at runtime:
    • /provider — show current base_url / model / key state and
      list the four presets.
    • /provider deepseek|glm|moonshot|openai — apply the preset's
      base_url and default model, persist to settings.json, and
      rebuild the API client in place.
    • /provider key <secret> — store the API key in settings.json.
    • /provider model <name> — switch the model only.
    • /provider clear — wipe the stored API key.
  • Turn skipped (not crashed) when no key. Submitting a message
    before a key is configured prints the warning again instead of
    erroring out.
  • CCSETTINGS_Save is now public so /provider (and any future
    runtime configuration) can persist updates without poking the file
    directly.

v0.8.11 — Dynamic input box stability fixes.

New since v0.8.10

  • Scroll region spans the full band regardless of where the dynamic
    box currently sits (scroll_bottom = nFloor - 1 always), so an early
    write between banner and box does not scroll content out of the
    banner.
  • Interactive selectors force-pin the box before painting. ask_user
    and propose_agents now call a new CCPROMPT_ForcePin that drops the
    box to the floor first, giving the selector a stable position right
    above it and avoiding overlap with a still-travelling box.
  • Wipe never erases the just-written content. The old-box-frame
    wipe in CCPROMPT_Redraw is now clamped to
    [max(oldBoxTop, contentRow) .. newBoxTop - 1], so the rows that
    hold the new user echo or the streamed reply are preserved.
  • Visual-row counting (auto-wrap). CCREPL_Out now advances
    content_row by the visual rows a chunk consumes (LFs + wrapped
    printable runs + ANSI sequences skipped), ...
Read more