Adds a new CLI flag that allows users to include additional prompt
content from a file. The content is appended to the system prompt
before project memory is loaded.
When --safari was passed, Chrome diagnostics were still running because
--chrome-headless defaults to true. This caused the CLI to hang while
running diagnostics for a browser that wouldn't be used.
Now skip Chrome diagnostics when --safari is explicitly set.
Simplify print_context_thinning to just print the message directly.
The message already contains proper ANSI formatting from context_window.rs.
Removes the flash animation and 'Context optimized successfully' footer.
The response was being printed twice: once during streaming and again
after task completion. Removed the redundant print_smart() call since
streaming already displays the response in real-time.
When running g3 --agent butler, the process title is now "g3 [butler]"
which shows up in ps, Activity Monitor, top, etc.
Uses the proctitle crate for cross-platform support.
When running g3 --agent <name> --chat:
- Skip per-turn memory checkpoint calls (too onerous)
- Call memory checkpoint once when exiting (Ctrl-D)
When running g3 --agent <name> (single-shot):
- Preserve existing behavior: call memory checkpoint after each turn
This keeps the auto-memory feature useful without being intrusive
in interactive agent sessions.
When running g3 --agent <name> --chat, the output is now minimal:
- Workspace path (-> ~/path)
- Status line (README/AGENTS.md/Memory)
- Context progress bar
- Prompt (g3>)
Skipped in this mode:
- Session resume prompts
- "agent mode | name (source)" header
- "g3 programming agent" welcome
- Provider info display
- Language guidance messages
Added from_agent_mode parameter to run_interactive() to control
whether verbose welcome and session resume are shown.
The JSON filter only suppresses tool calls at line boundaries. When
"Memory checkpoint: " was printed without a trailing newline, the LLM
response `{"tool": "remember", ...}` appeared on the same line and
leaked through to the UI.
Fix:
- Add trailing newline to "Memory checkpoint:" message
- Reset JSON filter state before streaming the response
Added test: test_tool_call_not_at_line_start_passes_through
Documents the filter behavior and references the fix location.
- Remove chat from conflicts_with_all for --agent flag
- Add chat parameter to run_agent_mode()
- Run interactive loop instead of single task when --chat is passed
Usage: g3 --agent <name> --chat
The print_todo_compact() function was missing the call to clear the
streaming hint line before printing the final tool output. This caused
the tool name to appear twice when the hint line wasn't cleared:
● todo_read ● todo_read | empty
Added the missing handle_hint(ToolParsingHint::Complete) call to match
the behavior of print_tool_compact().
Agent: carmack
Changes:
- streaming_parser.rs: Unified find_first/last_tool_call_start into single
find_tool_call_start with SearchDirection enum, reducing duplication.
Simplified is_json_invalidated from 45 to 20 lines with clearer logic.
Fixed redundant !escape_next check in find_complete_json_object_end.
- filter_json.rs: Simplified check_tool_pattern from 40 to 24 lines.
Replaced repetitive prefix checks with loop over ["t", "to", "too", "tool"].
Reduced trailing return statements with direct expression returns.
- ui_writer_impl.rs: Added ansi module for duration color constants.
Simplified duration_color function by removing redundant comments.
- language_prompts.rs: Fixed test assertions to match actual prompt content
("obvious, readable Racket" instead of "RACKET-SPECIFIC GUIDANCE").
All 174+ tests pass. No behavior changes.
- Add ToolParsingHint enum (Detected/Active/Complete) for UI feedback
- New UiWriter methods: print_tool_streaming_hint(), print_tool_streaming_active()
- Refactor ConsoleUiWriter state to use atomics in ParsingHintState
- Add tool_call_streaming field to CompletionChunk for provider hints
- Anthropic provider sends streaming hints when tool name detected
- New streaming helpers: make_tool_streaming_hint(), make_tool_streaming_active()
Parser improvements:
- Add is_json_invalidated() to detect false positive tool patterns
- Fix tool result poisoning when file contents contain partial JSON
- Unescaped newlines in strings or prose after JSON invalidates detection
User sees ' ● tool_name |' immediately when tool call starts streaming,
with blinking indicator while args are received.
Rust-specific readability guidance for the carmack agent including:
- let...else example for shallow control flow
- Async: don't block the runtime (tokio::fs, spawn_blocking, Send)
- Visibility: prefer pub(crate), private fields with accessors
- Generics: impl Trait over explicit params, avoid complex where clauses
- Improved iterator guidance: if you need a comment, use a loop
- UTF-8 string slicing warnings
- Ownership/lifetime pragmatism
- Anti-patterns: no macros/typestate/proc-macros unless already in repo
Also adds Rust detection to LANGUAGE_PROMPTS (empty base prompt,
agent-specific prompts handle the guidance).
When running in agent mode (e.g., --agent carmack) in a workspace with
detected languages, inject agent+language-specific prompts from
prompts/langs/<agent>.<lang>.md at the end of the system prompt.
Changes:
- Add AGENT_LANGUAGE_PROMPTS static array for compile-time embedding
- Add get_agent_language_prompt() to look up specific agent+lang combos
- Add get_agent_language_prompts_for_workspace_with_langs() that returns
both content and matched languages for display
- Update agent_mode.rs to inject prompts and show which languages loaded
- Display format: '✓ carmack: racket language guidance'
- Add tests for new functionality
Uses the same detect_languages() mechanism as regular language prompts
to avoid code-path aliasing.
Use try_init() instead of init() for tracing subscriber setup to
gracefully handle cases where a global subscriber is already set.
This fixes a panic in the scout agent subprocess when spawned by the
research tool, where a dependency may have already initialized tracing.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Move initialize_logging() call to run immediately after CLI parsing,
before any mode checks. This ensures the --verbose flag works correctly
in planning mode, which previously bypassed logging initialization.
Previously, planning mode would return early before initialize_logging()
was called, causing verbose output to be silently ignored.
- Add language_prompts module that auto-detects programming languages in workspace
- Scan for language files with depth limit (2) to inject relevant toolchain prompts
- Add prompts/langs/ directory for language-specific markdown files
- Include Racket/raco toolchain guidance as first language prompt
- Update combine_project_content() to accept language_content parameter
- Integrate language detection into main CLI flow and agent mode
- Update project memory with new feature documentation
• Agent prompts are now embedded within the g3 binary
• README.md - Added new "Agent Mode" section documenting:
• All 7 built-in agents with their focus areas
• Usage examples (--list-agents, --agent <name>)
• How to create custom workspace agents
Behavior
1. Workspace agents take priority - If agents/<name>.md exists in the workspace, it's used
2. Embedded fallback - If no workspace agent exists, the embedded version is used
3. Portability - g3 binary now works on any repo without needing the agents/ directory
4. Discoverability - g3 --list-agents shows all available agents and their source
When users explicitly pass --new-session, they want a fresh session.
Previously g3 would still prompt to resume an existing session.
Now the resume check is skipped entirely when the flag is set.
- Rename take_screenshot -> screenshot, code_coverage -> coverage (shorter names)
- Align | character across all compact tools (pad to 11 chars for str_replace)
- Make code_search a compact tool with summary display
- Show language and search name in code_search output (e.g., rust:"find structs")
- Add format_code_search_summary() to extract match/file counts from JSON response
- webdriver flag now defaults to true (tools always available)
- chrome_headless flag now defaults to true (Chrome is default browser)
- Use --safari flag to override and use Safari instead
- Updated README documentation to reflect new defaults
When the LLM reads the same file multiple times in sequence (scrolling
through a large file), instead of showing each as a separate line:
● read_file | path [0..2000] | 50 lines | 100 ◉ 5ms
● read_file | path [2000..4000] | 50 lines | 100 ◉ 5ms
● read_file | path [4000..6000] | 50 lines | 100 ◉ 5ms
Now shows a cleaner continuation format:
● read_file | path [0..2000] | 50 lines | 100 ◉ 5ms
└─ reading further [2000..4000] | 50 lines | 100 ◉ 5ms
└─ reading further [4000..6000] | 50 lines | 100 ◉ 5ms
This makes it visually clear that the agent is scrolling through
a single file rather than reading multiple different files.
Implementation:
- Added last_read_file_path field to ConsoleUiWriter
- Detect when consecutive read_file calls target the same file
- Print continuation format for subsequent reads
- Reset tracking when:
- A different tool is executed (shell, write_file, etc.)
- A different file is read
- Text is output between tool calls
1. architecture.md: Fixed diagram to show 'studio' instead of 'g3-console'
(the crate was renamed during development)
2. analysis/memory.md: Removed reference to non-existent machine_ui_writer.rs
3. theme.rs: Clarified that 'retro' is a theme option (the default theme),
not a separate TUI mode. No --retro CLI flag exists.
Adds blank line separation between text and tool calls for better readability:
- Text → Tool: blank line before tool call
- Tool → Text: blank line before text
- Tool → Tool: no gap (stays tight)
Implemented via two state tracking flags in ConsoleUiWriter:
- last_output_was_text
- last_output_was_tool
Updated print_tool_output_header(), print_tool_compact(), and
print_agent_response() to check and set these flags appropriately.
- Move run_flock_mode() to autonomous.rs (parallel execution mode belongs with autonomous code)
- Move initialize_logging() to utils.rs (utility function with simple bool parameter)
- lib.rs reduced from 274 to 216 lines
No behavior changes. All 28 unit tests pass.
Agent: fowler
The LLM often hallucinates incorrect paths like /Users/jnbrymn/GitHub/g3
when the actual working directory is different. This causes wasted tokens
and failed commands as the LLM tries cd commands that fail.
Fix: Add the current working directory to the combined project content
that gets injected into the context at startup. This appears as:
📂 Working Directory: /actual/path/to/workspace
This is prepended before AGENTS.md, README.md, and project memory,
so the LLM knows the correct path from the start.
This change removes the legacy logs/ directory and consolidates all
session data, error logs, and discovery files under the .g3/ directory.
New directory structure:
- .g3/sessions/<session_id>/session.json - session logs
- .g3/errors/ - error logs (was logs/errors/)
- .g3/background_processes/ - background process logs
- .g3/discovery/ - planner discovery files (was workspace/logs/)
Changes:
- paths.rs: Remove get_logs_dir()/logs_dir(), add get_errors_dir(),
get_background_processes_dir(), get_discovery_dir()
- session.rs: Anonymous sessions now use .g3/sessions/anonymous_<ts>/
- error_handling.rs: Errors now saved to .g3/errors/
- project.rs: Remove logs_dir() and ensure_logs_dir() methods
- feedback_extraction.rs: Remove logs_dir field and fallback logic
- planner: Use .g3/ for workspace data and .g3/discovery/ for reports
- flock.rs: Look for session metrics in .g3/sessions/
- coach_feedback.rs: Remove fallback to logs/ path
- Update all tests to use new paths
- Update README.md and .gitignore
Implement compact display format for read_file, write_file, str_replace, and shell:
- read_file/write_file/str_replace: Single line with dimmed summary and timing
Format: ● tool_name | path [range] | summary | tokens ◉ time
- shell: Two-line format with command header and dimmed output
Format: ● shell | command
└─ output (N lines) | tokens ◉ time
Changes:
- Add print_tool_compact() method to UiWriter trait
- Add is_shell_compact state tracking in ConsoleUiWriter
- Add format_write_file_summary() and format_str_replace_summary() helpers
- Fix duplicate response output by checking if response is empty before printing
- Add finish_streaming_markdown() call before return to flush markdown buffer
Add ANSI clear-to-end-of-line escape sequence (\x1b[K]) after the
reset code in the context thinning animation. This prevents leftover
background color artifacts when the carriage return overwrites the
line during the flash animation.
Project memory is now stored at analysis/memory.md instead of .g3/memory.md.
This change enables:
- Shared memory across git worktrees (studio agent sessions)
- Version-controlled memory that persists across clones
- Memory changes tracked in git history and reviewable in PRs
Changes:
- crates/g3-core/src/tools/memory.rs: Update get_memory_path() to use analysis/
- crates/g3-cli/src/project_files.rs: Update read_project_memory() path
- crates/g3-core/src/prompts.rs: Update documentation references (2 occurrences)
- analysis/memory.md: Add memory file (copied from .g3/memory.md)
Consolidate duplicated logic into canonical shared functions:
- Extract load_config_with_cli_overrides() to utils.rs
- Was duplicated in lib.rs and accumulative.rs with subtle differences
- lib.rs version had Chrome diagnostics + provider validation
- accumulative.rs version was missing both
- Now all callers use the complete canonical implementation
- Extract combine_project_content() to project_files.rs
- Was duplicated inline in lib.rs and agent_mode.rs
- Simplified implementation using iterator flatten
- Added unit tests for all cases
This eliminates drift risk where the duplicated implementations
could diverge over time (accumulative.rs was already missing
Chrome diagnostics and provider validation).
Agent: fowler