
Claude Skills by tools-only
github.com/tools-onlyPR #244 centralized panel width calculations into a single module (`panel_widths.py`) and removed redundant width logic from 9+ tool renderers. This refactoring applies Gate 5 (Indirection Requires Verification) by replacing `expand=True` indirection with explicit `width=` parameters.
When a user aborted mid-tool-call (Ctrl+C or tool denial), the conversation history was left with a `ModelResponse` containing tool calls but no corresponding `ToolReturn` messages. The next API request failed because the provider expected tool returns for pending calls.
Fixed a bug where `retry-prompt` parts were left orphaned in message history after their corresponding `tool-call` parts were pruned during dangling tool call cleanup. The fix generalizes the filter to remove ANY part with a `tool_call_id` matching a dangling ID, not just `tool-call` parts.
Boundary contracts between UI, core, and tools are partially implicit: several callbacks and tool entry points are typed as `Any` or use broad protocols, so the contract is not enforced by typing or tests. This makes boundary drift harder to detect and allows accidental coupling across layers.
Moved the app-level ESC cancellation cascade into a dedicated `ui/esc` module and delegated `action_cancel_request()` to an explicit handler. This isolates ESC logic from app internals and makes the dependency inputs explicit.
Reduced redundant token estimation in tool-output pruning while preserving pruning behavior. The pruning loop in `prune_old_tool_outputs()` was estimating token counts twice for pruned parts and recalculating placeholder tokens for every mutation. - Added `PRUNE_PLACEHOLDER_TOKENS` to cache placeholder token counts. - Introduced `get_part_content_text()` to normalize part content before estimation/pruning. - Passed precomputed token counts into `prune_part_content()` to avoid re-estimation. -...
Removed the temporary `tunacode.cli` package shim so the only supported CLI entrypoint is `tunacode.ui.main`, aligning code and docs on a single import path.
The agent run flow no longer recomputes token totals by iterating over message history. This removes the slow heuristic `update_token_count` path in favor of usage totals as the canonical source for token display.
Removed the unused ToolBuffer shim from the agent loop and strengthened the system prompt to demand batched read-only tool calls during discovery, aligning the runtime with actual parallel tool execution capabilities.
The resource bar now reads token totals from accumulated usage metrics rather than heuristic message counts, keeping the UI aligned with provider-reported usage.
Tool calls with leading/trailing whitespace in `tool_name` failed to dispatch (e.g., " glob"), resulting in unknown-tool errors instead of retries. We now normalize tool names before registration and dispatch to avoid whitespace-induced failures.
from tunacode.tools.authorization import ToolHandler __all__ = ["ToolHandler"] from tunacode.tools.authorization.handler import ToolHandler # Direct import ``` The `__all__` export suggests `ToolHandler` should be imported via `tunacode.core`, but nothing actually uses it that way.
Removed global mutable cache state from the user configuration module. The previous implementation used module-level `_config_fingerprint` and `_config_cache` variables for a fast-path optimization that was likely premature for configuration file handling.
The canonical token total for UI display is the accumulated pydantic-ai usage totals (prompt + completion) from `usage.session_total_usage`, not heuristic message counting. This aligns the UI with billed API usage and avoids slow per-message estimation.
When extracting changes from a messy PR, I blindly copied a fix to `retry.py` without questioning whether it was needed.
grep -n "_gitignore_patterns" src/tunacode/tools/glob.py ``` If all references are writes, it's dead.
| Phase | Status | Branch | |-------|--------|--------| | P1 (Messaging) | ✓ Complete | `types-architect` | | P2 (Tooling) | ✓ Complete | `types-architect` |
These are another layer to prevent slop, not pre-commit hooks.
These are another layer to prevent slop, not pre-commit hooks.
**Generated:** 2026-01-04 **Project:** TunaCode - TUI Code Agent **Source Directory:** src/tunacode/ **Version:** 0.1.20 **Python Version:** 3.11-3.13 ---
**Status**: Draft **Created**: 2026-01-25 **Branch**: `claude/refactor-tunacode-architecture-Ox6gl` ---
**Status**: Draft **Created**: 2026-01-25 **Branch**: `claude/refactor-tunacode-architecture-Ox6gl` ---
This document traces message handling from entry to exit, documenting the single source of truth pattern.
The Tunacode TUI (Terminal User Interface) is built upon a strong design philosophy heavily inspired by the classic **NeXTSTEP** operating system. This is not merely an aesthetic choice, but a functional one aimed at maximizing user clarity and control.
**Date:** 2025-12-06 **Scope:** UI / Tooling **Status:** Canonical
**Date:** 2026-01-07 **Scope:** UI / Renderers **Status:** Canonical
Removed direct dependencies on `pydantic-ai` from the `src/tunacode/tools/` directory (specifically `ModelRetry`). Tools now raise a domain-specific `ToolRetryError`, which is intercepted by the tool decorator and translated to `ModelRetry` for the framework. Previously, 8 tool files imported `ModelRetry` from `pydantic_ai.exceptions`. This coupled the business logic of the tools directly to the specific agent framework we are using. - **Added `ToolRetryError`** to `src/tunacode/exceptions.py...
**Date:** 2026-01-27 **Branch:** lsp-index-cleanup **Start commit:** b4e34261 **End commit:** 690c4760
**Remove the planning feature entirely from tunacode.** The feature (a read-only mode restricting agent to information gathering before code modifications) is not actively used and adds maintenance burden across 9 layers.
uv run python -c " from pathlib import Path from tunacode.core.agents.agent_components.agent_config import load_system_prompt prompt = load_system_prompt(Path('src/tunacode')) assert '{{USER_INSTRUCTIONS}}' in prompt assert '{{CWD}}' not in prompt # Should be resolved print('OK') " ``` - `tests/unit/core/test_prompting_engine.py` - KEEP, tests `resolve_prompt()` which is unchanged - No new tests needed for simple file read operation ---
Delete the disabled `research_codebase` sub-agent feature completely from the codebase. This is a cleanup task—the feature is already disabled in production (commented out in agent_config.py).
self.mount(widget, before=self._current_stream) elif self._insertion_anchor is not None: self.mount(widget, before=self._insertion_anchor) else: self.mount(widget) if self._auto_scroll: self.scroll_end(animate=False) ``` **Acceptance Test:** Tool panel arriving after `end_stream()` appears before the finalized agent response, not at bottom. **Dependencies:** Task 1 **Milestone:** M2 --- **Summary:** Reset anchor when starting a new stream to prevent stale positioning. **Files:** `src/tunacode...
**SINGULAR FOCUS:** Eliminate all 24 direct imports from `tunacode.utils` in `tunacode.core` by either: 1. Moving modules to foundation layers (`configuration/`, `types/`) 2. Inlining tiny utilities 3. Re-routing through Layer 2 (`tools/`)
Eliminate all lateral coupling violations between Layer 2 peer modules (`tools`, `indexing`, `lsp`, `infrastructure`). These modules should only depend downward to foundation layers (`utils`, `types`, `configuration`), never sideways to each other.
grep -r "from tunacode.indexing" src/tunacode/ grep -r "CodeIndex" src/tunacode/ grep -r "IndexingService" src/tunacode/ uv run pytest grep -r "indexing" docs/ | grep -v ".git" ```
- **ONE outcome:** Replace dual-display streaming architecture (RichLog + streaming_output Static) with a unified ChatContainer using individual MessageWidget components that stream in-place.
Remove the direct dependency on `pydantic-ai` from `src/tunacode/tools/`. Tools should raise domain-specific exceptions, not framework-specific exceptions.
Refactor 4 D-grade complexity hotspots to improve maintainability and reduce cognitive load. Target: reduce McCabe complexity scores below threshold (25) for all functions.
Make ESC handling clearer and more maintainable by extracting ESC logic into a dedicated, independent module under `src/tunacode/ui/esc/`. The ESC node (handler) should be independent of app internals and depend only on explicit inputs passed in.
Reduce message canonicalization overhead in `run_cleanup_loop()` by caching canonical messages per iteration: 1N conversions when no mutations occur, and 2N conversions in iterations that mutate messages (recompute after mutation).
Reduce pruning overhead in `src/tunacode/core/agents/resume/prune.py` by eliminating redundant token estimation, while preserving current pruning behavior.
**Date:** 2026-01-26 **Owner:** agent **Phase:** Research
**Date:** 2026-01-26 **Owner:** tunacode **Phase:** Research **git_commit:** b6eb3990
**Date:** 2026-01-26 17:34:12 **Owner:** Claude (research agent) **Phase:** Research **Git commit:** 48071e33c62516b5a9018bfb2b20c42a48215640 **Git branch:** master **Repo:** alchemiststudiosDOTai/tunacode ---
**Date:** 2026-01-26 **Owner:** Claude (research agent) **Phase:** Research **Git commit:** 84ce4ff3 **Git branch:** master **Repo:** alchemiststudiosDOTai/tunacode ---
**Date:** 2026-01-26 **Owner:** Agent **Phase:** Research
**Date:** 2026-01-27 **Owner:** claude-agent **Phase:** Research **Issue:** https://github.com/alchemiststudiosDOTai/tunacode/issues/311
**Date:** 2026-01-27 **Owner:** Claude (research agent) **Phase:** Research **Issue:** [#313 Layer violation: core → utils (18 imports, skips Layer 2)](https://github.com/alchemiststudiosDOTai/tunacode/issues/313)
**Date:** 2026-01-27 **Owner:** claude-agent **Phase:** Research **Git Commit:** 1de46c7bba8a7a322fc00b878eb918cf224bd9ae
**Date:** 2026-01-27 17:28:01 **Owner:** agent **Phase:** Research