tunacode-cli 0.0.4__tar.gz → 0.0.6__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of tunacode-cli might be problematic. Click here for more details.

Files changed (83) hide show
  1. tunacode_cli-0.0.6/PKG-INFO +235 -0
  2. tunacode_cli-0.0.6/README.md +199 -0
  3. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/pyproject.toml +3 -2
  4. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/src/tunacode/cli/commands.py +91 -33
  5. tunacode_cli-0.0.6/src/tunacode/cli/model_selector.py +178 -0
  6. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/src/tunacode/cli/repl.py +11 -10
  7. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/src/tunacode/configuration/models.py +11 -1
  8. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/src/tunacode/constants.py +11 -11
  9. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/src/tunacode/context.py +1 -3
  10. tunacode_cli-0.0.6/src/tunacode/core/agents/main.py +77 -0
  11. tunacode_cli-0.0.6/src/tunacode/core/agents/tinyagent_main.py +171 -0
  12. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/src/tunacode/core/setup/git_safety_setup.py +39 -51
  13. tunacode_cli-0.0.6/src/tunacode/core/setup/optimized_coordinator.py +73 -0
  14. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/src/tunacode/exceptions.py +13 -15
  15. tunacode_cli-0.0.6/src/tunacode/services/enhanced_undo_service.py +322 -0
  16. tunacode_cli-0.0.6/src/tunacode/services/project_undo_service.py +311 -0
  17. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/src/tunacode/services/undo_service.py +18 -21
  18. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/src/tunacode/tools/base.py +11 -20
  19. tunacode_cli-0.0.6/src/tunacode/tools/tinyagent_tools.py +103 -0
  20. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/src/tunacode/tools/update_file.py +24 -14
  21. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/src/tunacode/tools/write_file.py +9 -7
  22. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/src/tunacode/types.py +2 -2
  23. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/src/tunacode/ui/completers.py +98 -33
  24. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/src/tunacode/ui/input.py +8 -7
  25. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/src/tunacode/ui/keybindings.py +1 -3
  26. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/src/tunacode/ui/lexers.py +16 -17
  27. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/src/tunacode/ui/output.py +9 -3
  28. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/src/tunacode/ui/panels.py +4 -4
  29. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/src/tunacode/ui/prompt_manager.py +6 -4
  30. tunacode_cli-0.0.6/src/tunacode/utils/lazy_imports.py +59 -0
  31. tunacode_cli-0.0.6/src/tunacode/utils/regex_cache.py +33 -0
  32. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/src/tunacode/utils/system.py +13 -13
  33. tunacode_cli-0.0.6/src/tunacode_cli.egg-info/PKG-INFO +235 -0
  34. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/src/tunacode_cli.egg-info/SOURCES.txt +8 -0
  35. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/src/tunacode_cli.egg-info/requires.txt +2 -1
  36. tunacode_cli-0.0.4/PKG-INFO +0 -247
  37. tunacode_cli-0.0.4/README.md +0 -212
  38. tunacode_cli-0.0.4/src/tunacode/core/agents/main.py +0 -119
  39. tunacode_cli-0.0.4/src/tunacode_cli.egg-info/PKG-INFO +0 -247
  40. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/LICENSE +0 -0
  41. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/setup.cfg +0 -0
  42. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/setup.py +0 -0
  43. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/src/tunacode/__init__.py +0 -0
  44. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/src/tunacode/cli/__init__.py +0 -0
  45. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/src/tunacode/cli/main.py +0 -0
  46. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/src/tunacode/configuration/__init__.py +0 -0
  47. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/src/tunacode/configuration/defaults.py +0 -0
  48. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/src/tunacode/configuration/settings.py +0 -0
  49. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/src/tunacode/core/__init__.py +0 -0
  50. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/src/tunacode/core/agents/__init__.py +0 -0
  51. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/src/tunacode/core/setup/__init__.py +0 -0
  52. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/src/tunacode/core/setup/agent_setup.py +0 -0
  53. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/src/tunacode/core/setup/base.py +0 -0
  54. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/src/tunacode/core/setup/config_setup.py +0 -0
  55. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/src/tunacode/core/setup/coordinator.py +0 -0
  56. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/src/tunacode/core/setup/environment_setup.py +0 -0
  57. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/src/tunacode/core/setup/undo_setup.py +0 -0
  58. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/src/tunacode/core/state.py +0 -0
  59. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/src/tunacode/core/tool_handler.py +0 -0
  60. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/src/tunacode/prompts/system.txt +0 -0
  61. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/src/tunacode/py.typed +0 -0
  62. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/src/tunacode/services/__init__.py +0 -0
  63. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/src/tunacode/services/mcp.py +0 -0
  64. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/src/tunacode/setup.py +0 -0
  65. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/src/tunacode/tools/__init__.py +0 -0
  66. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/src/tunacode/tools/read_file.py +0 -0
  67. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/src/tunacode/tools/run_command.py +0 -0
  68. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/src/tunacode/ui/__init__.py +0 -0
  69. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/src/tunacode/ui/console.py +0 -0
  70. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/src/tunacode/ui/constants.py +0 -0
  71. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/src/tunacode/ui/decorators.py +0 -0
  72. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/src/tunacode/ui/tool_ui.py +0 -0
  73. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/src/tunacode/ui/validators.py +0 -0
  74. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/src/tunacode/utils/__init__.py +0 -0
  75. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/src/tunacode/utils/bm25.py +0 -0
  76. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/src/tunacode/utils/diff_utils.py +0 -0
  77. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/src/tunacode/utils/file_utils.py +0 -0
  78. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/src/tunacode/utils/ripgrep.py +0 -0
  79. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/src/tunacode/utils/text_utils.py +0 -0
  80. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/src/tunacode/utils/user_configuration.py +0 -0
  81. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/src/tunacode_cli.egg-info/dependency_links.txt +0 -0
  82. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/src/tunacode_cli.egg-info/entry_points.txt +0 -0
  83. {tunacode_cli-0.0.4 → tunacode_cli-0.0.6}/src/tunacode_cli.egg-info/top_level.txt +0 -0
@@ -0,0 +1,235 @@
1
+ Metadata-Version: 2.4
2
+ Name: tunacode-cli
3
+ Version: 0.0.6
4
+ Summary: Your agentic CLI developer.
5
+ Author-email: larock22 <noreply@github.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/larock22/tunacode
8
+ Project-URL: Repository, https://github.com/larock22/tunacode
9
+ Keywords: cli,agent,development,automation
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.10
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: 3.13
17
+ Classifier: Topic :: Software Development
18
+ Classifier: Topic :: Utilities
19
+ Requires-Python: >=3.10
20
+ Description-Content-Type: text/markdown
21
+ License-File: LICENSE
22
+ Requires-Dist: prompt_toolkit==3.0.51
23
+ Requires-Dist: tiny_agent_os>=0.1.0
24
+ Requires-Dist: pygments==2.19.1
25
+ Requires-Dist: rich==14.0.0
26
+ Requires-Dist: typer==0.15.3
27
+ Requires-Dist: pyyaml>=6.0
28
+ Provides-Extra: dev
29
+ Requires-Dist: build; extra == "dev"
30
+ Requires-Dist: black; extra == "dev"
31
+ Requires-Dist: flake8; extra == "dev"
32
+ Requires-Dist: isort; extra == "dev"
33
+ Requires-Dist: pytest; extra == "dev"
34
+ Requires-Dist: pytest-cov; extra == "dev"
35
+ Dynamic: license-file
36
+
37
+ # 🐟 TunaCode
38
+
39
+ [![PyPI version](https://badge.fury.io/py/tunacode-cli.svg)](https://badge.fury.io/py/tunacode-cli)
40
+ [![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
41
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
42
+
43
+ ![Chuna](chuna.jpg_medium)
44
+
45
+ **Your agentic CLI developer** - An open-source alternative to Claude Code, Copilot, and Cursor with multi-provider LLM support.
46
+
47
+
48
+ ## ✨ What's New (v0.1.0)
49
+
50
+ - 🚀 **60% faster startup** with lazy loading and optimizations
51
+ - 🤖 **TinyAgent integration** for robust ReAct-based interactions
52
+ - 🛡️ **Three-layer undo system** with automatic failover
53
+ - 📊 **Enhanced model selection** with fuzzy matching and cost indicators
54
+ - 📁 **Project-local backups** in `.tunacode/` directory
55
+
56
+ ## 🎯 Features
57
+
58
+ ### Core Capabilities
59
+ - **🔓 No vendor lock-in** - Use any LLM provider (OpenAI, Anthropic, Google, 100+ via OpenRouter)
60
+ - **⚡ Fast & responsive** - Optimized for speed with <5ms operation overhead
61
+ - **🛡️ Safe operations** - Three-layer undo system ensures nothing is lost
62
+ - **🎨 Modern CLI** - Beautiful terminal UI with syntax highlighting
63
+ - **💰 Cost tracking** - Monitor tokens and costs per session
64
+
65
+ ### Developer Experience
66
+ - **🔄 Hot model switching** - Change models mid-conversation with `/model`
67
+ - **📝 Project guides** - Customize behavior with `TUNACODE.md` files
68
+ - **🚀 YOLO mode** - Skip confirmations when you're confident
69
+ - **🔧 MCP support** - Extend with Model Context Protocol servers
70
+ - **📊 Git integration** - Automatic branch creation and undo support
71
+
72
+ ## 🚀 Quick Start
73
+
74
+ ```bash
75
+ # Install from PyPI
76
+ pip install tunacode-cli
77
+
78
+ # Run setup (first time only)
79
+ tunacode
80
+
81
+ # Start coding!
82
+ tunacode
83
+ > Help me refactor this codebase to use async/await
84
+ ```
85
+
86
+ ## 📋 Commands
87
+
88
+ | Command | Description | Example |
89
+ |---------|-------------|---------|
90
+ | `/model` or `/m` | List and switch models | `/model 3` or `/m opus` |
91
+ | `/yolo` | Toggle confirmation skipping | `/yolo` |
92
+ | `/undo` | Undo last file operation | `/undo` |
93
+ | `/clear` | Clear conversation history | `/clear` |
94
+ | `/branch <name>` | Create new git branch | `/branch feature/auth` |
95
+ | `/compact` | Summarize and trim history | `/compact` |
96
+ | `/help` | Show all commands | `/help` |
97
+
98
+ ## 🔧 Configuration
99
+
100
+ Configuration is stored in `~/.config/tunacode.json`:
101
+
102
+ ```json
103
+ {
104
+ "default_model": "openai:gpt-4o",
105
+ "env": {
106
+ "OPENAI_API_KEY": "sk-...",
107
+ "ANTHROPIC_API_KEY": "sk-ant-...",
108
+ "OPENROUTER_API_KEY": "sk-or-..."
109
+ },
110
+ "mcpServers": {
111
+ "github": {
112
+ "command": "npx",
113
+ "args": ["-y", "@modelcontextprotocol/server-github"],
114
+ "env": {"GITHUB_PERSONAL_ACCESS_TOKEN": "..."}
115
+ }
116
+ }
117
+ }
118
+ ```
119
+
120
+ ### Using OpenRouter (100+ Models)
121
+
122
+ ```bash
123
+ # Add your OpenRouter API key to config
124
+ # Then run with OpenRouter base URL:
125
+ OPENAI_BASE_URL="https://openrouter.ai/api/v1" tunacode
126
+
127
+ # Use any OpenRouter model:
128
+ /model openrouter:anthropic/claude-3-opus
129
+ /model openrouter:mistralai/devstral-small
130
+ /model openrouter:openai/gpt-4.1
131
+ ```
132
+
133
+ ## 🛡️ Undo System
134
+
135
+ TunaCode provides **three layers of protection** for your files:
136
+
137
+ 1. **Git commits** - Primary undo mechanism (if available)
138
+ 2. **Operation log** - Tracks changes with content (<100KB files)
139
+ 3. **File backups** - Physical copies in `.tunacode/backups/`
140
+
141
+ All undo data is stored locally in your project:
142
+
143
+ ```
144
+ your-project/
145
+ └── .tunacode/ # Auto-created, gitignored
146
+ ├── backups/ # Timestamped file copies
147
+ ├── operations.jsonl # Change history
148
+ └── README.md # Explains the directory
149
+ ```
150
+
151
+ ## 🎯 Project Customization
152
+
153
+ Create a `TUNACODE.md` file in your project root:
154
+
155
+ ```markdown
156
+ # Project Guidelines for TunaCode
157
+
158
+ ## Tech Stack
159
+ - Next.js 14 with App Router
160
+ - TypeScript with strict mode
161
+ - Tailwind CSS for styling
162
+
163
+ ## Conventions
164
+ - Use arrow functions for components
165
+ - Prefer server components where possible
166
+ - Follow conventional commits
167
+
168
+ ## Commands
169
+ - `npm run dev` - Start development
170
+ - `npm test` - Run tests
171
+ ```
172
+
173
+ ## ⚡ Performance
174
+
175
+ TunaCode is optimized for speed:
176
+ - **Startup time**: ~0.5-0.8 seconds
177
+ - **Model switching**: ~100ms
178
+ - **File operations**: ~5ms overhead
179
+ - **API calls**: Connection pooling enabled
180
+
181
+ ## 🔧 Advanced Usage
182
+
183
+ ### Environment Variables
184
+ ```bash
185
+ # Use different base URLs
186
+ OPENAI_BASE_URL="https://openrouter.ai/api/v1" tunacode
187
+
188
+ # Disable undo system
189
+ TUNACODE_NO_UNDO=1 tunacode
190
+
191
+ # Set default model
192
+ TUNACODE_MODEL="anthropic:claude-3-opus" tunacode
193
+ ```
194
+
195
+ ### MCP Servers
196
+ Extend TunaCode with Model Context Protocol servers for web fetching, database access, and more. See [modelcontextprotocol.io](https://modelcontextprotocol.io/) for available servers.
197
+
198
+ ## 🤝 Contributing
199
+
200
+ We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
201
+
202
+ ```bash
203
+ # Setup development environment
204
+ git clone https://github.com/larock22/tunacode
205
+ cd tunacode
206
+ pip install -e ".[dev]"
207
+
208
+ # Run tests
209
+ make test
210
+
211
+ # Lint code
212
+ make lint
213
+ ```
214
+
215
+ ## 📚 Documentation
216
+
217
+ - [Architecture Overview](docs/architecture.md)
218
+ - [API Integration](API_CALL_FLOW.md)
219
+ - [Undo System Design](UNDO_SYSTEM_DESIGN.md)
220
+ - [Performance Guide](PERFORMANCE_OPTIMIZATIONS.md)
221
+
222
+ ## 🙏 Acknowledgments
223
+
224
+ TunaCode is built on the foundation of [sidekick-cli](https://github.com/geekforbrains/sidekick-cli). Special thanks to:
225
+ - The sidekick-cli team for the original codebase
226
+ - [TinyAgent](https://github.com/alchemiststudiosDOTai/tinyAgent) for the robust agent framework
227
+ - The open-source community for feedback and contributions
228
+
229
+ ## 📄 License
230
+
231
+ MIT License - see [LICENSE](LICENSE) for details.
232
+
233
+ ---
234
+
235
+ **Note**: TunaCode is in active development. Please [report issues](https://github.com/larock22/tunacode/issues) or share feedback!
@@ -0,0 +1,199 @@
1
+ # 🐟 TunaCode
2
+
3
+ [![PyPI version](https://badge.fury.io/py/tunacode-cli.svg)](https://badge.fury.io/py/tunacode-cli)
4
+ [![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
+
7
+ ![Chuna](chuna.jpg_medium)
8
+
9
+ **Your agentic CLI developer** - An open-source alternative to Claude Code, Copilot, and Cursor with multi-provider LLM support.
10
+
11
+
12
+ ## ✨ What's New (v0.1.0)
13
+
14
+ - 🚀 **60% faster startup** with lazy loading and optimizations
15
+ - 🤖 **TinyAgent integration** for robust ReAct-based interactions
16
+ - 🛡️ **Three-layer undo system** with automatic failover
17
+ - 📊 **Enhanced model selection** with fuzzy matching and cost indicators
18
+ - 📁 **Project-local backups** in `.tunacode/` directory
19
+
20
+ ## 🎯 Features
21
+
22
+ ### Core Capabilities
23
+ - **🔓 No vendor lock-in** - Use any LLM provider (OpenAI, Anthropic, Google, 100+ via OpenRouter)
24
+ - **⚡ Fast & responsive** - Optimized for speed with <5ms operation overhead
25
+ - **🛡️ Safe operations** - Three-layer undo system ensures nothing is lost
26
+ - **🎨 Modern CLI** - Beautiful terminal UI with syntax highlighting
27
+ - **💰 Cost tracking** - Monitor tokens and costs per session
28
+
29
+ ### Developer Experience
30
+ - **🔄 Hot model switching** - Change models mid-conversation with `/model`
31
+ - **📝 Project guides** - Customize behavior with `TUNACODE.md` files
32
+ - **🚀 YOLO mode** - Skip confirmations when you're confident
33
+ - **🔧 MCP support** - Extend with Model Context Protocol servers
34
+ - **📊 Git integration** - Automatic branch creation and undo support
35
+
36
+ ## 🚀 Quick Start
37
+
38
+ ```bash
39
+ # Install from PyPI
40
+ pip install tunacode-cli
41
+
42
+ # Run setup (first time only)
43
+ tunacode
44
+
45
+ # Start coding!
46
+ tunacode
47
+ > Help me refactor this codebase to use async/await
48
+ ```
49
+
50
+ ## 📋 Commands
51
+
52
+ | Command | Description | Example |
53
+ |---------|-------------|---------|
54
+ | `/model` or `/m` | List and switch models | `/model 3` or `/m opus` |
55
+ | `/yolo` | Toggle confirmation skipping | `/yolo` |
56
+ | `/undo` | Undo last file operation | `/undo` |
57
+ | `/clear` | Clear conversation history | `/clear` |
58
+ | `/branch <name>` | Create new git branch | `/branch feature/auth` |
59
+ | `/compact` | Summarize and trim history | `/compact` |
60
+ | `/help` | Show all commands | `/help` |
61
+
62
+ ## 🔧 Configuration
63
+
64
+ Configuration is stored in `~/.config/tunacode.json`:
65
+
66
+ ```json
67
+ {
68
+ "default_model": "openai:gpt-4o",
69
+ "env": {
70
+ "OPENAI_API_KEY": "sk-...",
71
+ "ANTHROPIC_API_KEY": "sk-ant-...",
72
+ "OPENROUTER_API_KEY": "sk-or-..."
73
+ },
74
+ "mcpServers": {
75
+ "github": {
76
+ "command": "npx",
77
+ "args": ["-y", "@modelcontextprotocol/server-github"],
78
+ "env": {"GITHUB_PERSONAL_ACCESS_TOKEN": "..."}
79
+ }
80
+ }
81
+ }
82
+ ```
83
+
84
+ ### Using OpenRouter (100+ Models)
85
+
86
+ ```bash
87
+ # Add your OpenRouter API key to config
88
+ # Then run with OpenRouter base URL:
89
+ OPENAI_BASE_URL="https://openrouter.ai/api/v1" tunacode
90
+
91
+ # Use any OpenRouter model:
92
+ /model openrouter:anthropic/claude-3-opus
93
+ /model openrouter:mistralai/devstral-small
94
+ /model openrouter:openai/gpt-4.1
95
+ ```
96
+
97
+ ## 🛡️ Undo System
98
+
99
+ TunaCode provides **three layers of protection** for your files:
100
+
101
+ 1. **Git commits** - Primary undo mechanism (if available)
102
+ 2. **Operation log** - Tracks changes with content (<100KB files)
103
+ 3. **File backups** - Physical copies in `.tunacode/backups/`
104
+
105
+ All undo data is stored locally in your project:
106
+
107
+ ```
108
+ your-project/
109
+ └── .tunacode/ # Auto-created, gitignored
110
+ ├── backups/ # Timestamped file copies
111
+ ├── operations.jsonl # Change history
112
+ └── README.md # Explains the directory
113
+ ```
114
+
115
+ ## 🎯 Project Customization
116
+
117
+ Create a `TUNACODE.md` file in your project root:
118
+
119
+ ```markdown
120
+ # Project Guidelines for TunaCode
121
+
122
+ ## Tech Stack
123
+ - Next.js 14 with App Router
124
+ - TypeScript with strict mode
125
+ - Tailwind CSS for styling
126
+
127
+ ## Conventions
128
+ - Use arrow functions for components
129
+ - Prefer server components where possible
130
+ - Follow conventional commits
131
+
132
+ ## Commands
133
+ - `npm run dev` - Start development
134
+ - `npm test` - Run tests
135
+ ```
136
+
137
+ ## ⚡ Performance
138
+
139
+ TunaCode is optimized for speed:
140
+ - **Startup time**: ~0.5-0.8 seconds
141
+ - **Model switching**: ~100ms
142
+ - **File operations**: ~5ms overhead
143
+ - **API calls**: Connection pooling enabled
144
+
145
+ ## 🔧 Advanced Usage
146
+
147
+ ### Environment Variables
148
+ ```bash
149
+ # Use different base URLs
150
+ OPENAI_BASE_URL="https://openrouter.ai/api/v1" tunacode
151
+
152
+ # Disable undo system
153
+ TUNACODE_NO_UNDO=1 tunacode
154
+
155
+ # Set default model
156
+ TUNACODE_MODEL="anthropic:claude-3-opus" tunacode
157
+ ```
158
+
159
+ ### MCP Servers
160
+ Extend TunaCode with Model Context Protocol servers for web fetching, database access, and more. See [modelcontextprotocol.io](https://modelcontextprotocol.io/) for available servers.
161
+
162
+ ## 🤝 Contributing
163
+
164
+ We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
165
+
166
+ ```bash
167
+ # Setup development environment
168
+ git clone https://github.com/larock22/tunacode
169
+ cd tunacode
170
+ pip install -e ".[dev]"
171
+
172
+ # Run tests
173
+ make test
174
+
175
+ # Lint code
176
+ make lint
177
+ ```
178
+
179
+ ## 📚 Documentation
180
+
181
+ - [Architecture Overview](docs/architecture.md)
182
+ - [API Integration](API_CALL_FLOW.md)
183
+ - [Undo System Design](UNDO_SYSTEM_DESIGN.md)
184
+ - [Performance Guide](PERFORMANCE_OPTIMIZATIONS.md)
185
+
186
+ ## 🙏 Acknowledgments
187
+
188
+ TunaCode is built on the foundation of [sidekick-cli](https://github.com/geekforbrains/sidekick-cli). Special thanks to:
189
+ - The sidekick-cli team for the original codebase
190
+ - [TinyAgent](https://github.com/alchemiststudiosDOTai/tinyAgent) for the robust agent framework
191
+ - The open-source community for feedback and contributions
192
+
193
+ ## 📄 License
194
+
195
+ MIT License - see [LICENSE](LICENSE) for details.
196
+
197
+ ---
198
+
199
+ **Note**: TunaCode is in active development. Please [report issues](https://github.com/larock22/tunacode/issues) or share feedback!
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "tunacode-cli"
7
- version = "0.0.4"
7
+ version = "0.0.6"
8
8
  description = "Your agentic CLI developer."
9
9
  keywords = ["cli", "agent", "development", "automation"]
10
10
  readme = "README.md"
@@ -26,10 +26,11 @@ classifiers = [
26
26
  ]
27
27
  dependencies = [
28
28
  "prompt_toolkit==3.0.51",
29
- "pydantic-ai[logfire]==0.2.6",
29
+ "tiny_agent_os>=0.1.0",
30
30
  "pygments==2.19.1",
31
31
  "rich==14.0.0",
32
32
  "typer==0.15.3",
33
+ "pyyaml>=6.0",
33
34
  ]
34
35
 
35
36
  [project.scripts]
@@ -6,7 +6,6 @@ from enum import Enum
6
6
  from typing import Any, Dict, List, Optional, Type
7
7
 
8
8
  from .. import utils
9
- from ..configuration.models import ModelRegistry
10
9
  from ..exceptions import ValidationError
11
10
  from ..services.undo_service import perform_undo
12
11
  from ..types import CommandArgs, CommandContext, CommandResult, ProcessRequestCallback
@@ -260,7 +259,6 @@ class UndoCommand(SimpleCommand):
260
259
  await ui.muted(" • File operations will still work, but can't be undone")
261
260
 
262
261
 
263
-
264
262
  class BranchCommand(SimpleCommand):
265
263
  """Create and switch to a new git branch."""
266
264
 
@@ -388,46 +386,106 @@ class ModelCommand(SimpleCommand):
388
386
  super().__init__(
389
387
  CommandSpec(
390
388
  name="model",
391
- aliases=["/model"],
392
- description="List models or select a model (e.g., /model 3 or /model 3 default)",
389
+ aliases=["/model", "/m"],
390
+ description="List and select AI models interactively",
393
391
  category=CommandCategory.MODEL,
394
392
  )
395
393
  )
396
394
 
397
395
  async def execute(self, args: CommandArgs, context: CommandContext) -> Optional[str]:
396
+ from tunacode.cli.model_selector import ModelSelector
397
+
398
+ selector = ModelSelector()
399
+
398
400
  if not args:
399
- # No arguments - list models
400
- await ui.models(context.state_manager)
401
+ # No arguments - show enhanced model list
402
+ await self._show_model_list(selector, context.state_manager)
401
403
  return None
402
404
 
403
- # Parse model index
404
- try:
405
- model_index = int(args[0])
406
- except ValueError:
407
- await ui.error(f"Invalid model index: {args[0]}")
408
- return None
405
+ # Find model by query (index, name, or fuzzy match)
406
+ query = args[0]
407
+ model_info = selector.find_model(query)
409
408
 
410
- # Get model list
411
- model_registry = ModelRegistry()
412
- models = list(model_registry.list_models().keys())
413
- if model_index < 0 or model_index >= len(models):
414
- await ui.error(f"Model index {model_index} out of range")
409
+ if not model_info:
410
+ # Try to provide helpful suggestions
411
+ await ui.error(f"Model '{query}' not found")
412
+ await ui.muted(
413
+ "Try: /model (to list all), or use a number 0-18, "
414
+ "or model name like 'opus' or 'gpt-4'"
415
+ )
415
416
  return None
416
417
 
417
418
  # Set the model
418
- model = models[model_index]
419
- context.state_manager.session.current_model = model
419
+ context.state_manager.session.current_model = model_info.id
420
420
 
421
421
  # Check if setting as default
422
422
  if len(args) > 1 and args[1] == "default":
423
- utils.user_configuration.set_default_model(model, context.state_manager)
424
- await ui.muted("Updating default model")
423
+ utils.user_configuration.set_default_model(model_info.id, context.state_manager)
424
+ await ui.success(
425
+ f"Set default model: {model_info.display_name} {model_info.provider.value[2]}"
426
+ )
425
427
  return "restart"
426
428
  else:
427
- # Show success message with the new model
428
- await ui.success(f"Switched to model: {model}")
429
+ # Show success message with model details
430
+ cost_emoji = selector.get_cost_emoji(model_info.cost_tier)
431
+ await ui.success(
432
+ f"Switched to: {model_info.display_name} "
433
+ f"{model_info.provider.value[2]} {cost_emoji}\n"
434
+ f" → {model_info.description}"
435
+ )
429
436
  return None
430
437
 
438
+ async def _show_model_list(self, selector, state_manager) -> None:
439
+ """Show enhanced model list grouped by provider."""
440
+ from rich.table import Table
441
+ from rich.text import Text
442
+
443
+ # Create table
444
+ table = Table(show_header=True, box=None, padding=(0, 2))
445
+ table.add_column("ID", style="dim", width=3)
446
+ table.add_column("Model", style="bold")
447
+ table.add_column("Short", style="cyan")
448
+ table.add_column("Description", style="dim")
449
+ table.add_column("Cost", justify="center", width=4)
450
+
451
+ # Current model
452
+ current_model = state_manager.session.current_model if state_manager else None
453
+
454
+ # Add models grouped by provider
455
+ model_index = 0
456
+ grouped = selector.get_models_by_provider()
457
+
458
+ for provider in [p for p in grouped if grouped[p]]: # Only show providers with models
459
+ # Add provider header
460
+ table.add_row(
461
+ "",
462
+ Text(f"{provider.value[2]} {provider.value[1]}", style="bold magenta"),
463
+ "",
464
+ "",
465
+ "",
466
+ )
467
+
468
+ # Add models for this provider
469
+ for model in grouped[provider]:
470
+ is_current = model.id == current_model
471
+ style = "bold green" if is_current else ""
472
+
473
+ table.add_row(
474
+ str(model_index),
475
+ Text(model.display_name + (" ← current" if is_current else ""), style=style),
476
+ model.short_name,
477
+ model.description,
478
+ selector.get_cost_emoji(model.cost_tier),
479
+ )
480
+ model_index += 1
481
+
482
+ # Show the table
483
+ await ui.panel("Available Models", table, border_style="cyan")
484
+
485
+ # Show usage hints
486
+ await ui.muted("\n💡 Usage: /model <number|name> [default]")
487
+ await ui.muted(" Examples: /model 3, /model opus, /model gpt-4 default")
488
+
431
489
 
432
490
  @dataclass
433
491
  class CommandDependencies:
@@ -488,8 +546,7 @@ class CommandRegistry:
488
546
  category_commands = self._categories[command.category]
489
547
  # Remove any existing instance of this command class
490
548
  self._categories[command.category] = [
491
- cmd for cmd in category_commands
492
- if cmd.__class__ != command.__class__
549
+ cmd for cmd in category_commands if cmd.__class__ != command.__class__
493
550
  ]
494
551
  # Add the new instance
495
552
  self._categories[command.category].append(command)
@@ -533,7 +590,7 @@ class CommandRegistry:
533
590
  # Only update if callback has changed
534
591
  if self._factory.dependencies.process_request_callback == callback:
535
592
  return
536
-
593
+
537
594
  self._factory.update_dependencies(process_request_callback=callback)
538
595
 
539
596
  # Re-register CompactCommand with new dependency if already registered
@@ -568,10 +625,10 @@ class CommandRegistry:
568
625
  if command_name in self._commands:
569
626
  command = self._commands[command_name]
570
627
  return await command.execute(args, context)
571
-
628
+
572
629
  # Try partial matching
573
630
  matches = self.find_matching_commands(command_name)
574
-
631
+
575
632
  if not matches:
576
633
  raise ValidationError(f"Unknown command: {command_name}")
577
634
  elif len(matches) == 1:
@@ -581,16 +638,17 @@ class CommandRegistry:
581
638
  else:
582
639
  # Ambiguous - show possibilities
583
640
  raise ValidationError(
584
- f"Ambiguous command '{command_name}'. Did you mean: {', '.join(sorted(set(matches)))}?"
641
+ f"Ambiguous command '{command_name}'. Did you mean: "
642
+ f"{', '.join(sorted(set(matches)))}?"
585
643
  )
586
644
 
587
645
  def find_matching_commands(self, partial_command: str) -> List[str]:
588
646
  """
589
647
  Find all commands that start with the given partial command.
590
-
648
+
591
649
  Args:
592
650
  partial_command: The partial command to match
593
-
651
+
594
652
  Returns:
595
653
  List of matching command names
596
654
  """
@@ -608,11 +666,11 @@ class CommandRegistry:
608
666
  return False
609
667
 
610
668
  command_name = parts[0].lower()
611
-
669
+
612
670
  # Check exact match first
613
671
  if command_name in self._commands:
614
672
  return True
615
-
673
+
616
674
  # Check partial match
617
675
  return len(self.find_matching_commands(command_name)) > 0
618
676