Rustyline's \x01...\x02 markers for ANSI codes didn't work correctly,
causing cursor positioning issues and breaking line editing.
New approach: build_prompt() returns (prefix, prompt) tuple where:
- prefix: colored text printed before readline (contains ANSI codes)
- prompt: plain text passed to readline (no ANSI codes)
This ensures rustyline correctly calculates line length while still
showing the colored project name.
When a project is loaded via /project, the prompt now shows:
agent_name |[project_name]>
where the |[project_name]> part is displayed in blue.
Examples:
- Default: g3>
- With project: g3 |[myapp]>
- Agent mode: butler>
- Agent + project: butler |[myapp]>
The prompt automatically resets when /unproject is called.
Added build_prompt() function with 7 unit tests covering all prompt states.
Remove duplicate logging initialization in agent_mode.rs. Logging is already
initialized in run() before agent mode is dispatched. The duplicate
tracing_subscriber::fmt::layer() was interfering with rustyline's terminal
state, breaking tab completion.
Rename all references from "Project Memory" to "Workspace Memory" to avoid
future conflation if a "project" concept is introduced later.
Changes:
- Rename read_project_memory() -> read_workspace_memory()
- Update all prompts, tool descriptions, and comments
- Update header parsing in memory.rs to use "# Workspace Memory"
- Update display detection for "=== Workspace Memory ==="
- Update documentation and analysis/memory.md
11 files changed, ~36 occurrences updated.
Warnings fixed:
- Remove unused 'warn' import from retry.rs
- Prefix unused 'output' param with underscore
- Prefix unused 'rel_start' with underscore
- Add #[allow(dead_code)] to G3Status::info()
Message format tweaked per feedback:
- 'g3: model overloaded [error]' (no attempt info)
- 'g3: retrying in 2.2s (1/3) ... [done]' (attempt info moved here)
- Handle empty error message in Status::Error to show just '[error]'
Agent prompt files (both workspace agents/<name>.md and embedded)
now support template variables like {{today}}.
This allows agent definitions to include dynamic content:
# My Agent
Today is {{today}}. Your mission is...
Replace '📄 Context dumped to: <filename>' with 'g3: context dumped to <filename> [done]'
where g3: is bold green, filename is cyan, and [done] is bold green.
Add G3Status::complete_with_path() method for status messages with highlighted paths.
Supports {{var}} syntax for variable substitution in included prompt files.
Currently supported variables:
- {{today}}: Current date in ISO format (YYYY-MM-DD)
Unknown variables trigger a warning and are left unchanged.
- Add template.rs module with process_template() function
- Integrate template processing into read_include_prompt()
- Add comprehensive tests for template processing
- Extract handle_command() from interactive.rs to new commands.rs module
(320 lines, 15 match arms for /help, /compact, /thinnify, etc.)
- Fix orphaned tests in completion.rs that were outside mod tests block
- Add #[allow(dead_code)] to with_include_prompt_filename() (used in tests)
- interactive.rs reduced from 595 to 290 lines
Agent: fowler
Created display.rs module with shared display functions:
- format_workspace_path() / print_workspace_path()
- LoadedContent struct for tracking loaded project files
- print_loaded_status() for status line display
- print_project_heading() for README heading
Updated interactive.rs and agent_mode.rs to use the new module,
eliminating duplicated workspace path formatting and loaded items
status line logic.
Results:
- interactive.rs: 641 → 595 lines (-46)
- agent_mode.rs: 312 → 288 lines (-24)
- New display.rs: 197 lines with 5 unit tests
Agent: fowler
The --acd flag was being checked AFTER the agent mode early return,
so it was never applied when running with --agent.
Fix: Pass acd_enabled parameter to run_agent_mode() and call
agent.set_acd_enabled(true) when the flag is set.
Always shows at most 8 sessions in tab completion, sorted by newest first.
This applies whether the user types /resume <TAB> or /resume abc<TAB>.
Implementation:
- list_sessions() returns all sessions sorted by mtime (newest first)
- Completion filters by prefix, then takes first 8 matches
Phase 2 of tab completion: semantic completion for session IDs.
Features:
- /resume <TAB> lists all available sessions from .g3/sessions/
- /resume abc<TAB> filters to sessions starting with 'abc'
- Gracefully returns empty if .g3/sessions/ doesn't exist
Implementation:
- Added list_sessions() helper method to G3Helper
- Added Case 4 in complete() for /resume command
- Updated module docs to reflect new capability
Tests:
- test_resume_completion_lists_sessions - verifies listing and filtering
- test_resume_completion_graceful_no_panic - verifies no crash without sessions dir
Verifies that tab completion correctly ignores:
- Bare quotes: "<TAB> - no path prefix, no completion
- Quoted non-paths: "hello world<TAB> - not a path, no completion
- Quoted text without path prefix: "foo<TAB> - no completion
Also fixes test placement (moved tests inside mod tests block)
Edge cases now handled:
1. Unclosed quotes: "~/My <TAB> - completes paths inside quotes
2. Backslash escapes: ~/My\ <TAB> - unescapes before completing
3. Closed quotes: "~/My Files/"<TAB> - works correctly
Key changes:
- extract_word() now tracks backslash escapes (prev_was_backslash)
- is_path_prefix() strips leading quotes before checking
- Added strip_quotes() and unescape_path() helper methods
- complete() now:
- Strips quotes and unescapes paths before calling FilenameCompleter
- Re-wraps completions in quotes or escapes as appropriate
- Preserves user's quoting style (double vs single quotes)
- Uses backslash escapes if user was already using them
Tests added:
- test_actual_completion_with_quotes - verifies all three edge cases
Path completion now works for:
- ./<TAB> - current directory
- ../<TAB> - parent directory
- ~/<TAB> - home directory
- /<TAB> (not at start of line) - root directory
Command completion (/<TAB>) only triggers at the start of the line.
If no command matches, falls through to path completion (e.g., /etc).
Quote-aware word extraction handles paths with spaces:
- "~/My Files/<TAB>" works correctly
Added tests for:
- Path prefix detection
- Word extraction with quotes
- Command vs path disambiguation
New interactive command: /run <file-path>
- Reads the specified file and executes its content as a prompt
- Supports tilde expansion for home directory paths
- Behaves exactly like pasting the file content into the g3> prompt
- Shows helpful error messages for missing files or empty content
Extract a new g3_status module in g3-cli that provides consistent formatting
for all 'g3:' prefixed system status messages.
Key changes:
- Add G3Status struct with methods for progress, done, failed, error, etc.
- Add Status enum with Done, Failed, Error, Resolved, Insufficient, NoChanges
- Add ThinResult struct in g3-core for semantic thinning data
- Update UiWriter trait with print_thin_result() method
- Refactor context thinning to return ThinResult instead of formatted strings
- Update all callers to use the new centralized formatting
- Session resume/decline messages now use G3Status
- Compaction status messages now use G3Status
This maintains clean separation of concerns: g3-core emits semantic data,
g3-cli handles all terminal formatting and colors.
Two cosmetic bugs fixed:
1. JSON inside code fences was being filtered - now tracks fence state
and passes through all content inside ``` ... ``` blocks
2. Indented JSON was being filtered - now recognizes that real tool
calls are never indented, so indented JSON is always documentation
Changes:
- Added in_code_fence and fence_buffer fields to FilterState
- Added track_code_fence() to detect ``` markers (with/without language)
- Added pass_through_char() for content inside code fences
- Modified '{' handling to only filter when no leading whitespace
- Added 4 new unit tests for code fence and indentation cases
- Updated 3 stress tests to expect new (correct) behavior
All 16 filter_json unit tests and 59 stress tests pass.
Output is now a single line:
Session number to resume (Enter to cancel): 1 ... resuming scout_88871653e8e5f4f7 [done]
- Session ID displayed in cyan
- [done] displayed in bold green
- [error: ...] displayed in bold red on failure
- Added print_inline() to SimpleOutput for inline prompts
- print_g3_progress now uses print! instead of println!
- print_g3_status completes the line with just the status
- Result: 'g3: compacting session ... [done]' on one line
- Combine session info and resume prompt on one line
- Show result inline after user input (y/n)
- Green '... resuming ... [done]' on successful resume
- Dark grey '... starting fresh' when declining
- Yellow '... failed: <error>' on restore failure
Changes the startup status line to only display items that were
actually loaded, instead of showing dots for missing items.
Before: " · README · AGENTS.md ✓ Memory"
After: " ✓ Memory"
Also adds include prompt to the status line when specified:
" ✓ prompt.md ✓ Memory"
The order matches the load order: README → AGENTS.md → include prompt → Memory
Adds a flag to disable the automatic memory update reminder that runs
at the end of agent mode. Useful when running agents that should not
modify project memory.
- Add read_include_prompt() function to read prompt content from a file
- Update combine_project_content() to accept include_prompt parameter
- Change prompt order: cwd → agents → readme → language → include_prompt → memory
- Add section markers around Project Memory for clearer boundaries
- Add comprehensive tests for include prompt functionality and ordering
Updates lib.rs and agent_mode.rs to read the include prompt file
and pass it through to combine_project_content(). The include prompt
is placed after language prompts but before project memory.
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.