Research - Single MD Prompt Migration
Date: 2026-01-26 Owner: agent Phase: Research
Goal
Research migrating from the complex multi-section XML prompt system back to a single MD file for the agent system prompt, while keeping tool prompts separate (they are already independent).
IMPORTANT: Local mode is being deleted in this change, so only ONE prompt file is needed (system_prompt.md), not two.
Additional Search
grep -ri "section" /home/tuna/tunacode/.claude/ 2>/dev/null | head -20
Findings
Current Architecture Summary
Tunacode uses a two-layer prompt composition system:
- Agent System Prompt: Built from 11 modular XML sections composed via templates
- Tool Prompts: Separate XML files loaded independently via
@base_tooldecorator
Tool prompts are already separate from agent system prompts and require NO changes.
Current Prompt Flow
load_system_prompt() [agent_config.py:182]
│
├──> SectionLoader.__init__(sections_dir) [loader.py:17]
│
├──> loader.load_section(each SystemPromptSection) [loader.py:21]
│ └──> Check {section_name}.xml/.md/.txt in prompts/sections/
│ └──> _read_with_cache(path) with mtime caching
│
├──> compose_prompt(template, sections) [prompting_engine.py:82]
│ └──> Replace {{SECTION_NAME}} with section content
│
└──> resolve_prompt(prompt) [prompting_engine.py:77]
└──> Replace {{CWD}}, {{OS}}, {{DATE}} with runtime values
Files to DELETE (6 files + local_prompt.md)
| File | Lines | Purpose |
|---|---|---|
src/tunacode/core/prompting/loader.py |
67 | SectionLoader class - loads section files |
src/tunacode/core/prompting/sections.py |
51 | SystemPromptSection enum - defines 12 sections |
src/tunacode/core/prompting/templates.py |
86 | Template definitions (MAIN, LOCAL, RESEARCH) |
src/tunacode/prompts/sections/ |
dir | 11 XML section files (~26,710 chars total) |
src/tunacode/core/prompting/local_prompt.md |
72 | Local mode prompt (local mode being deleted) |
src/tunacode/prompts/sections/agent_role.xml |
9 | Agent identity |
src/tunacode/prompts/sections/critical_rules.xml |
36 | Behavior rules |
src/tunacode/prompts/sections/tool_use.xml |
81 | Tool access rules |
src/tunacode/prompts/sections/search_pattern.xml |
101 | GLOB->GREP->READ funnel |
src/tunacode/prompts/sections/completion.xml |
10 | Submit tool signaling |
src/tunacode/prompts/sections/parallel_exec.xml |
104 | Parallel execution rules |
src/tunacode/prompts/sections/output_style.xml |
94 | Communication style |
src/tunacode/prompts/sections/examples.xml |
186 | Few-shot examples |
src/tunacode/prompts/sections/advanced_patterns.xml |
217 | Advanced workflows |
src/tunacode/prompts/sections/system_info.xml |
7 | Dynamic placeholders |
src/tunacode/prompts/sections/user_instructions.xml |
4 | User context placeholder |
Files to MODIFY (Core Layer - 3 files)
| File | Lines | Changes |
|---|---|---|
src/tunacode/core/prompting/__init__.py |
30 | Remove exports for deleted modules |
src/tunacode/core/prompting/prompting_engine.py |
99 | Keep resolve_prompt() for {{CWD}}, {{OS}}, {{DATE}} |
src/tunacode/core/agents/agent_components/agent_config.py |
475 | Replace load_system_prompt() with simple file read |
Files to CREATE (1 file)
| File | Purpose |
|---|---|
src/tunacode/prompts/system_prompt.md |
Single MD file with all agent prompt content |
Files to MODIFY (Documentation - 13 files)
| File | Lines | Impact |
|---|---|---|
docs/codebase-map/modules/core-prompting.md |
112 | Rewrite - section composition removed |
docs/codebase-map/modules/prompts.md |
145 | Rewrite - modular sections removed |
docs/codebase-map/modules/templates.md |
113 | Delete or rewrite - templates deprecated |
docs/codebase-map/architecture/architecture.md |
426+ | Update - modular prompts references |
docs/codebase-map/MAP.md |
756 | Update - SectionLoader references |
docs/codebase-map/modules/core-agents.md |
154 | Update - template selection logic |
docs/codebase-map/state/state.md |
80 | Update - SectionLoader caching note |
docs/codebase-map/modules/utils-limits.md |
24 | DELETE or update - local mode being removed |
docs/codebase-map/modules/INDEX.md |
107 | Update - module descriptions |
docs/codebase-map/modules/00-overview.md |
38 | Update - prompts/ directory reference |
docs/codebase-map/structure/tree-structure.txt |
163 | Update - directory structure |
docs/codebase-map/modules/tools-overview.md |
230 | Update - XML prompt loading |
.claude/JOURNAL.md |
161 | Update - LOCAL_TEMPLATE references |
Tests (Mostly Stable - 1 file)
| File | Status |
|---|---|
tests/unit/core/test_prompting_engine.py |
KEEP - tests {{placeholder}} resolution which is still needed |
Tool Prompts - NO CHANGES NEEDED
Tool prompts are already separate from agent system prompts:
Tool Prompt Flow (Independent - No Changes)
Tool function decorated with @base_tool [decorators.py:89]
│
├──> load_prompt_from_xml(func.__name__) [decorators.py:119]
│ └──> Load tools/prompts/{func_name}_prompt.xml
│ └──> Parse <description> tag, return text
│
└──> wrapper.__doc__ = xml_prompt [decorators.py:121]
└──> pydantic-ai reads __doc__ when Tool() wraps function
Tool Prompt Files (Keep Unchanged)
All files in src/tunacode/tools/prompts/ remain unchanged:
bash_prompt.xmlglob_prompt.xmlgrep_prompt.xmllist_dir_prompt.xmlread_file_prompt.xmlwrite_file_prompt.xmlupdate_file_prompt.xmlweb_fetch_prompt.xmlsubmit_prompt.xml
Related Files (No Changes)
src/tunacode/tools/xml_helper.py-load_prompt_from_xml()functionsrc/tunacode/tools/decorators.py-@base_tooldecorator (line 119-121)
Key Patterns / Solutions Found
Reference Implementation: local_prompt.md (BEING DELETED)
The file src/tunacode/core/prompting/local_prompt.md (72 lines) was the reference implementation for the single-file approach:
# Current local mode loading (agent_config.py:228-232) - BEING REMOVED
prompting_dir = Path(__file__).parent.parent.parent / "prompting"
tunacode_path = prompting_dir / "local_prompt.md"
tunacode_content = tunacode_path.read_text(encoding="utf-8")
This demonstrates the pattern to follow:
- Single MD file with all content inline
- Uses
{{USER_INSTRUCTIONS}}placeholder for context injection - Direct file loading, no SectionLoader, no compose_prompt
- Simple
Path.read_text()approach
NOTE: local_prompt.md itself will be deleted as part of local mode removal, but it serves as the structural reference for system_prompt.md.
Proposed New load_system_prompt()
def load_system_prompt(base_path: Path, model: str | None = None) -> str:
"""Load the system prompt from a single MD file.
Local mode is being deleted - only one prompt file needed.
Args:
base_path: Base path to the tunacode package
model: Optional model name (for future per-model prompts)
Returns:
System prompt with dynamic placeholders resolved
"""
prompt_file = base_path / "prompts" / "system_prompt.md"
if not prompt_file.exists():
raise FileNotFoundError(
f"Required prompt file not found: {prompt_file}"
)
# Read single file and resolve dynamic placeholders
content = prompt_file.read_text(encoding="utf-8")
return resolve_prompt(content) # Handles {{CWD}}, {{OS}}, {{DATE}}
NOTE: Local mode is being deleted - no conditional logic needed. Just ONE prompt file.
Placeholder Resolution - KEEP
The {{CWD}}, {{OS}}, {{DATE}} placeholders are still needed and should be preserved:
# prompting_engine.py - KEEP THIS
def resolve_prompt(template: str) -> str:
"""Resolve {{CWD}}, {{OS}}, {{DATE}} placeholders."""
# ... existing implementation ...
What Goes Into system_prompt.md
Content from the 11 section files, in this order (from MAIN_TEMPLATE):
## AGENT_ROLE- Content fromagent_role.xml## SEARCH_PATTERN- Content fromsearch_pattern.xml## CRITICAL_RULES- Content fromcritical_rules.xml## TOOL_USE- Content fromtool_use.xml## COMPLETION- Content fromcompletion.xml## PARALLEL_EXEC- Content fromparallel_exec.xml## OUTPUT_STYLE- Content fromoutput_style.xml## EXAMPLES- Content fromexamples.xml## ADVANCED_PATTERNS- Content fromadvanced_patterns.xml## SYSTEM_INFO- Content fromsystem_info.xml{{USER_INSTRUCTIONS}}- Placeholder for AGENTS.md context
Knowledge Gaps
RESEARCH_TEMPLATE deletion: Current research shows
RESEARCH_TEMPLATEis being removed (ticket tun-5a52). Need to verify this is complete before single MD migration.Template override system:
TEMPLATE_OVERRIDESdict allows model-specific templates. Need to decide if this is kept with single MD approach (would require separate files per model).Section dependencies: Verify no external code depends on specific section names (e.g., tests that mock sections).
Migration verification: Need to confirm the composed single MD produces identical output to current section-based composition.
Deletion Strategy (4 Phases)
Phase 1: Create Single MD File
- Create
src/tunacode/prompts/system_prompt.mdwith all 11 sections - Verify content matches current composed output
- Keep section files for now (A/B testing)
Phase 2: Modify Core Loading
- Update
load_system_prompt()to read single file - Remove
SectionLoaderimport and usage - Keep
resolve_prompt()for dynamic placeholders
Phase 3: Delete Unused Files
- Delete
src/tunacode/core/prompting/loader.py - Delete
src/tunacode/core/prompting/sections.py - Delete
src/tunacode/core/prompting/templates.py - Delete
src/tunacode/prompts/sections/directory - Update
src/tunacode/core/prompting/__init__.pyexports
Phase 4: Update Documentation
- Rewrite
core-prompting.mdandprompts.md - Update all 13 documentation files
- Update
tree-structure.txt
References
Core Implementation Files
src/tunacode/core/prompting/__init__.py:1-30- Public API exportssrc/tunacode/core/prompting/loader.py:1-67- SectionLoader classsrc/tunacode/core/prompting/sections.py:1-51- SystemPromptSection enumsrc/tunacode/core/prompting/templates.py:1-86- Template definitionssrc/tunacode/core/prompting/prompting_engine.py:82-98- compose_prompt functionsrc/tunacode/core/prompting/prompting_engine.py:77-79- resolve_prompt functionsrc/tunacode/core/agents/agent_components/agent_config.py:182-217- load_system_prompt functionsrc/tunacode/core/prompting/local_prompt.md:1-72- Reference implementation (BEING DELETED with local mode)
Tool Prompt Files (Separate - No Changes)
src/tunacode/tools/xml_helper.py:10-34- load_prompt_from_xml functionsrc/tunacode/tools/decorators.py:119-121- Tool prompt attachment
Test Files
tests/unit/core/test_prompting_engine.py:1-90- Placeholder resolution tests
Documentation Files
docs/codebase-map/modules/core-prompting.md- Core module documentationdocs/codebase-map/modules/prompts.md- Prompt system overviewdocs/codebase-map/modules/templates.md- Template documentation