tunacode-cli 0.0.7__tar.gz → 0.0.8__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 (80) hide show
  1. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/PKG-INFO +64 -5
  2. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/README.md +62 -3
  3. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/pyproject.toml +2 -2
  4. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/cli/main.py +31 -2
  5. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/constants.py +1 -1
  6. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/core/agents/tinyagent_main.py +21 -0
  7. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/core/setup/config_setup.py +61 -53
  8. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/ui/input.py +3 -0
  9. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/ui/prompt_manager.py +2 -0
  10. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode_cli.egg-info/PKG-INFO +64 -5
  11. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode_cli.egg-info/requires.txt +1 -1
  12. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/LICENSE +0 -0
  13. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/setup.cfg +0 -0
  14. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/setup.py +0 -0
  15. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/__init__.py +0 -0
  16. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/cli/__init__.py +0 -0
  17. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/cli/commands.py +0 -0
  18. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/cli/model_selector.py +0 -0
  19. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/cli/repl.py +0 -0
  20. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/configuration/__init__.py +0 -0
  21. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/configuration/defaults.py +0 -0
  22. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/configuration/models.py +0 -0
  23. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/configuration/settings.py +0 -0
  24. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/context.py +0 -0
  25. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/core/__init__.py +0 -0
  26. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/core/agents/__init__.py +0 -0
  27. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/core/agents/main.py +0 -0
  28. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/core/setup/__init__.py +0 -0
  29. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/core/setup/agent_setup.py +0 -0
  30. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/core/setup/base.py +0 -0
  31. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/core/setup/coordinator.py +0 -0
  32. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/core/setup/environment_setup.py +0 -0
  33. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/core/setup/git_safety_setup.py +0 -0
  34. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/core/setup/optimized_coordinator.py +0 -0
  35. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/core/setup/undo_setup.py +0 -0
  36. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/core/state.py +0 -0
  37. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/core/tool_handler.py +0 -0
  38. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/exceptions.py +0 -0
  39. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/prompts/system.txt +0 -0
  40. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/py.typed +0 -0
  41. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/services/__init__.py +0 -0
  42. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/services/enhanced_undo_service.py +0 -0
  43. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/services/mcp.py +0 -0
  44. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/services/project_undo_service.py +0 -0
  45. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/services/undo_service.py +0 -0
  46. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/setup.py +0 -0
  47. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/tools/__init__.py +0 -0
  48. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/tools/base.py +0 -0
  49. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/tools/read_file.py +0 -0
  50. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/tools/run_command.py +0 -0
  51. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/tools/tinyagent_tools.py +0 -0
  52. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/tools/update_file.py +0 -0
  53. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/tools/write_file.py +0 -0
  54. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/types.py +0 -0
  55. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/ui/__init__.py +0 -0
  56. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/ui/completers.py +0 -0
  57. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/ui/console.py +0 -0
  58. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/ui/constants.py +0 -0
  59. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/ui/decorators.py +0 -0
  60. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/ui/keybindings.py +0 -0
  61. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/ui/lexers.py +0 -0
  62. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/ui/output.py +0 -0
  63. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/ui/panels.py +0 -0
  64. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/ui/tool_ui.py +0 -0
  65. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/ui/validators.py +0 -0
  66. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/utils/__init__.py +0 -0
  67. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/utils/bm25.py +0 -0
  68. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/utils/diff_utils.py +0 -0
  69. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/utils/file_utils.py +0 -0
  70. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/utils/lazy_imports.py +0 -0
  71. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/utils/regex_cache.py +0 -0
  72. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/utils/ripgrep.py +0 -0
  73. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/utils/system.py +0 -0
  74. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/utils/text_utils.py +0 -0
  75. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode/utils/user_configuration.py +0 -0
  76. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode_cli.egg-info/SOURCES.txt +0 -0
  77. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode_cli.egg-info/dependency_links.txt +0 -0
  78. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode_cli.egg-info/entry_points.txt +0 -0
  79. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/src/tunacode_cli.egg-info/top_level.txt +0 -0
  80. {tunacode_cli-0.0.7 → tunacode_cli-0.0.8}/tests/test_import.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tunacode-cli
3
- Version: 0.0.7
3
+ Version: 0.0.8
4
4
  Summary: Your agentic CLI developer.
5
5
  Author-email: larock22 <noreply@github.com>
6
6
  License-Expression: MIT
@@ -23,7 +23,7 @@ Requires-Dist: prompt_toolkit==3.0.51
23
23
  Requires-Dist: tiny_agent_os>=0.1.0
24
24
  Requires-Dist: pygments==2.19.1
25
25
  Requires-Dist: rich==14.0.0
26
- Requires-Dist: typer==0.15.3
26
+ Requires-Dist: typer==0.12.5
27
27
  Requires-Dist: pyyaml>=6.0
28
28
  Provides-Extra: dev
29
29
  Requires-Dist: build; extra == "dev"
@@ -107,6 +107,12 @@ tunacode
107
107
 
108
108
  # Update to latest version
109
109
  tunacode --update
110
+
111
+ # Start with a specific model
112
+ tunacode --model openrouter:openai/gpt-4o-mini
113
+
114
+ # Use a custom OpenAI-compatible API endpoint
115
+ tunacode --base-url https://your-api.com/v1 --model custom:gpt-4
110
116
  ```
111
117
 
112
118
  ## 📋 Commands
@@ -144,19 +150,72 @@ Configuration is stored in `~/.config/tunacode.json`:
144
150
  }
145
151
  ```
146
152
 
153
+ ### Environment Variables
154
+
155
+ TunaCode automatically loads environment variables from a `.env` file in your current directory:
156
+
157
+ ```bash
158
+ # .env file
159
+ OPENAI_API_KEY=sk-...
160
+ OPENROUTER_API_KEY=sk-or-v1-...
161
+ ANTHROPIC_API_KEY=sk-ant-...
162
+ ```
163
+
164
+ Environment variables take precedence over config file values.
165
+
166
+ ### TinyAgent Configuration
167
+
168
+ TunaCode uses [TinyAgent](https://github.com/alchemiststudiosDOTai/tiny_agent_os) under the hood. Advanced configuration is stored in `~/.config/tunacode_config.yml`:
169
+
170
+ ```yaml
171
+ # Model and API configuration
172
+ base_url: ${OPENAI_BASE_URL:-https://api.openai.com/v1}
173
+ model:
174
+ default: "gpt-4o" # Overridden by TunaCode's model selection
175
+
176
+ # File operations
177
+ file_operations:
178
+ max_file_size: 10_485_760 # 10 MB
179
+ allow_overwrite: true
180
+
181
+ # Retry configuration
182
+ retries:
183
+ max_attempts: 3
184
+ temperature: { initial: 0.2, increment: 0.3, max: 0.8 }
185
+ ```
186
+
187
+ This file is automatically created during installation. Most users won't need to modify it.
188
+
147
189
  ### Using OpenRouter (100+ Models)
148
190
 
149
191
  ```bash
150
- # Add your OpenRouter API key to config
151
- # Then run with OpenRouter base URL:
152
- OPENAI_BASE_URL="https://openrouter.ai/api/v1" tunacode
192
+ # Add your OpenRouter API key to config or .env file
193
+ # TunaCode automatically sets the correct base URL for OpenRouter models
153
194
 
154
195
  # Use any OpenRouter model:
196
+ tunacode --model openrouter:openai/gpt-4o-mini
197
+ tunacode --model openrouter:anthropic/claude-3.5-sonnet
198
+
199
+ # Or switch models inside TunaCode:
155
200
  /model openrouter:anthropic/claude-3-opus
156
201
  /model openrouter:mistralai/devstral-small
157
202
  /model openrouter:openai/gpt-4.1
158
203
  ```
159
204
 
205
+ ### OpenAI-Compatible APIs
206
+
207
+ TunaCode supports any OpenAI-compatible API endpoint. The `--base-url` flag overrides the API endpoint for providers that use the OpenAI API format:
208
+
209
+ ```bash
210
+ # Use a local LLM server
211
+ tunacode --base-url http://localhost:8080/v1 --model local:llama2
212
+
213
+ # Use alternative OpenAI-compatible services
214
+ tunacode --base-url https://api.together.ai/v1 --model together:llama-2-70b
215
+ ```
216
+
217
+ **Note**: The base URL override only works with OpenAI-compatible APIs that follow the same request/response format as OpenAI's API.
218
+
160
219
  ## 🛡️ Undo System
161
220
 
162
221
  TunaCode provides **three layers of protection** for your files:
@@ -71,6 +71,12 @@ tunacode
71
71
 
72
72
  # Update to latest version
73
73
  tunacode --update
74
+
75
+ # Start with a specific model
76
+ tunacode --model openrouter:openai/gpt-4o-mini
77
+
78
+ # Use a custom OpenAI-compatible API endpoint
79
+ tunacode --base-url https://your-api.com/v1 --model custom:gpt-4
74
80
  ```
75
81
 
76
82
  ## 📋 Commands
@@ -108,19 +114,72 @@ Configuration is stored in `~/.config/tunacode.json`:
108
114
  }
109
115
  ```
110
116
 
117
+ ### Environment Variables
118
+
119
+ TunaCode automatically loads environment variables from a `.env` file in your current directory:
120
+
121
+ ```bash
122
+ # .env file
123
+ OPENAI_API_KEY=sk-...
124
+ OPENROUTER_API_KEY=sk-or-v1-...
125
+ ANTHROPIC_API_KEY=sk-ant-...
126
+ ```
127
+
128
+ Environment variables take precedence over config file values.
129
+
130
+ ### TinyAgent Configuration
131
+
132
+ TunaCode uses [TinyAgent](https://github.com/alchemiststudiosDOTai/tiny_agent_os) under the hood. Advanced configuration is stored in `~/.config/tunacode_config.yml`:
133
+
134
+ ```yaml
135
+ # Model and API configuration
136
+ base_url: ${OPENAI_BASE_URL:-https://api.openai.com/v1}
137
+ model:
138
+ default: "gpt-4o" # Overridden by TunaCode's model selection
139
+
140
+ # File operations
141
+ file_operations:
142
+ max_file_size: 10_485_760 # 10 MB
143
+ allow_overwrite: true
144
+
145
+ # Retry configuration
146
+ retries:
147
+ max_attempts: 3
148
+ temperature: { initial: 0.2, increment: 0.3, max: 0.8 }
149
+ ```
150
+
151
+ This file is automatically created during installation. Most users won't need to modify it.
152
+
111
153
  ### Using OpenRouter (100+ Models)
112
154
 
113
155
  ```bash
114
- # Add your OpenRouter API key to config
115
- # Then run with OpenRouter base URL:
116
- OPENAI_BASE_URL="https://openrouter.ai/api/v1" tunacode
156
+ # Add your OpenRouter API key to config or .env file
157
+ # TunaCode automatically sets the correct base URL for OpenRouter models
117
158
 
118
159
  # Use any OpenRouter model:
160
+ tunacode --model openrouter:openai/gpt-4o-mini
161
+ tunacode --model openrouter:anthropic/claude-3.5-sonnet
162
+
163
+ # Or switch models inside TunaCode:
119
164
  /model openrouter:anthropic/claude-3-opus
120
165
  /model openrouter:mistralai/devstral-small
121
166
  /model openrouter:openai/gpt-4.1
122
167
  ```
123
168
 
169
+ ### OpenAI-Compatible APIs
170
+
171
+ TunaCode supports any OpenAI-compatible API endpoint. The `--base-url` flag overrides the API endpoint for providers that use the OpenAI API format:
172
+
173
+ ```bash
174
+ # Use a local LLM server
175
+ tunacode --base-url http://localhost:8080/v1 --model local:llama2
176
+
177
+ # Use alternative OpenAI-compatible services
178
+ tunacode --base-url https://api.together.ai/v1 --model together:llama-2-70b
179
+ ```
180
+
181
+ **Note**: The base URL override only works with OpenAI-compatible APIs that follow the same request/response format as OpenAI's API.
182
+
124
183
  ## 🛡️ Undo System
125
184
 
126
185
  TunaCode provides **three layers of protection** for your files:
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "tunacode-cli"
7
- version = "0.0.7"
7
+ version = "0.0.8"
8
8
  description = "Your agentic CLI developer."
9
9
  keywords = ["cli", "agent", "development", "automation"]
10
10
  readme = "README.md"
@@ -29,7 +29,7 @@ dependencies = [
29
29
  "tiny_agent_os>=0.1.0",
30
30
  "pygments==2.19.1",
31
31
  "rich==14.0.0",
32
- "typer==0.15.3",
32
+ "typer==0.12.5",
33
33
  "pyyaml>=6.0",
34
34
  ]
35
35
 
@@ -6,6 +6,8 @@ Manages application startup, version checking, and REPL initialization.
6
6
  """
7
7
 
8
8
  import asyncio
9
+ import os
10
+ from pathlib import Path
9
11
 
10
12
  import typer
11
13
 
@@ -17,16 +19,26 @@ from tunacode.ui import console as ui
17
19
  from tunacode.utils.system import check_for_updates
18
20
 
19
21
  app_settings = ApplicationSettings()
20
- app = typer.Typer(help=app_settings.name)
21
22
  state_manager = StateManager()
22
23
 
23
24
 
24
- @app.command()
25
25
  def main(
26
26
  version: bool = typer.Option(False, "--version", "-v", help="Show version and exit."),
27
27
  run_setup: bool = typer.Option(False, "--setup", help="Run setup process."),
28
28
  update: bool = typer.Option(False, "--update", "--upgrade", help="Update TunaCode to the latest version."),
29
+ model: str = typer.Option(None, "--model", "-m", help="Set the model to use (e.g., 'openai:gpt-4o', 'openrouter:anthropic/claude-3.5-sonnet')."),
30
+ base_url: str = typer.Option(None, "--base-url", help="Override the API base URL for OpenAI-compatible endpoints (e.g., 'https://openrouter.ai/api/v1')."),
29
31
  ):
32
+ """TunaCode - Your agentic CLI developer."""
33
+ # Load .env file if it exists
34
+ env_file = Path(".env")
35
+ if env_file.exists():
36
+ try:
37
+ from dotenv import load_dotenv
38
+ load_dotenv()
39
+ except ImportError:
40
+ # dotenv not installed, skip loading
41
+ pass
30
42
  if version:
31
43
  asyncio.run(ui.version())
32
44
  return
@@ -36,6 +48,15 @@ def main(
36
48
  asyncio.run(update_tunacode())
37
49
  return
38
50
 
51
+ # Apply CLI overrides to state manager before setup
52
+ if model:
53
+ state_manager.session.model = model
54
+ state_manager.session.user_config["default_model"] = model
55
+
56
+ if base_url:
57
+ import os
58
+ os.environ["OPENAI_BASE_URL"] = base_url
59
+
39
60
  asyncio.run(ui.banner())
40
61
 
41
62
  has_update, latest_version = check_for_updates()
@@ -49,5 +70,13 @@ def main(
49
70
  asyncio.run(ui.error(str(e)))
50
71
 
51
72
 
73
+ app = typer.Typer(
74
+ name="tunacode",
75
+ help="TunaCode - Your agentic CLI developer",
76
+ add_completion=False,
77
+ )
78
+
79
+ app.command()(main)
80
+
52
81
  if __name__ == "__main__":
53
82
  app()
@@ -7,7 +7,7 @@ Centralizes all magic strings, UI text, error messages, and application constant
7
7
 
8
8
  # Application info
9
9
  APP_NAME = "TunaCode"
10
- APP_VERSION = "0.1.0"
10
+ APP_VERSION = "0.0.8"
11
11
 
12
12
  # File patterns
13
13
  GUIDE_FILE_PATTERN = "{name}.md"
@@ -1,7 +1,9 @@
1
1
  """TinyAgent-based agent implementation."""
2
2
 
3
+ import os
3
4
  from contextlib import asynccontextmanager
4
5
  from datetime import datetime, timezone
6
+ from pathlib import Path
5
7
  from typing import Any, Dict, Optional
6
8
 
7
9
  from tinyagent import ReactAgent
@@ -10,6 +12,25 @@ from tunacode.core.state import StateManager
10
12
  from tunacode.tools.tinyagent_tools import read_file, run_command, update_file, write_file
11
13
  from tunacode.types import ModelName, ToolCallback
12
14
 
15
+ # Set up tinyagent configuration
16
+ # First check if config exists in the package directory
17
+ _package_dir = Path(__file__).parent.parent.parent.parent # Navigate to tunacode root
18
+ _config_candidates = [
19
+ _package_dir / "tunacode_config.yml", # In package root
20
+ Path.home() / ".config" / "tunacode_config.yml", # In user config dir
21
+ Path.cwd() / "tunacode_config.yml", # In current directory
22
+ ]
23
+
24
+ # Find the first existing config file
25
+ for config_path in _config_candidates:
26
+ if config_path.exists():
27
+ os.environ["TINYAGENT_CONFIG"] = str(config_path)
28
+ break
29
+ else:
30
+ # If no config found, we'll rely on tinyagent to handle it
31
+ # This prevents the immediate error on import
32
+ pass
33
+
13
34
 
14
35
  def get_or_create_react_agent(model: ModelName, state_manager: StateManager) -> ReactAgent:
15
36
  """
@@ -65,14 +65,14 @@ class ConfigSetup(BaseSetup):
65
65
  # Check if the configured model still exists
66
66
  default_model = self.state_manager.session.user_config["default_model"]
67
67
  if not self.model_registry.get_model(default_model):
68
+ # If model not found, run the onboarding again
68
69
  await ui.panel(
69
70
  "Model Not Found",
70
71
  f"The configured model '[bold]{default_model}[/bold]' is no longer available.\n"
71
- "Please select a new default model.",
72
+ "Let's reconfigure your setup.",
72
73
  border_style=UI_COLORS["warning"],
73
74
  )
74
- await self._step2_default_model()
75
- user_configuration.save_config(self.state_manager)
75
+ await self._onboarding()
76
76
 
77
77
  self.state_manager.session.current_model = self.state_manager.session.user_config[
78
78
  "default_model"
@@ -114,66 +114,74 @@ class ConfigSetup(BaseSetup):
114
114
  """Run the onboarding process for new users."""
115
115
  initial_config = json.dumps(self.state_manager.session.user_config, sort_keys=True)
116
116
 
117
- await self._step1_api_keys()
118
-
119
- # Only continue if at least one API key was provided
120
- env = self.state_manager.session.user_config.get("env", {})
121
- has_api_key = any(key.endswith("_API_KEY") and env.get(key) for key in env)
117
+ # Welcome message
118
+ message = (
119
+ f"Welcome to {APP_NAME}!\n\n"
120
+ "Let's configure your AI provider. TunaCode supports:\n"
121
+ "• OpenAI (api.openai.com)\n"
122
+ "• OpenRouter (openrouter.ai) - Access 100+ models\n"
123
+ "• Any OpenAI-compatible API\n"
124
+ )
125
+ await ui.panel("Setup", message, border_style=UI_COLORS["primary"])
122
126
 
123
- if has_api_key:
124
- if not self.state_manager.session.user_config.get("default_model"):
125
- await self._step2_default_model()
127
+ # Step 1: Ask for base URL
128
+ base_url = await ui.input(
129
+ "step1",
130
+ pretext=" API Base URL (press Enter for OpenAI): ",
131
+ default="https://api.openai.com/v1",
132
+ state_manager=self.state_manager,
133
+ )
134
+ base_url = base_url.strip()
135
+ if not base_url:
136
+ base_url = "https://api.openai.com/v1"
137
+
138
+ # Step 2: Ask for API key
139
+ if "openrouter.ai" in base_url.lower():
140
+ key_prompt = " OpenRouter API Key: "
141
+ key_name = "OPENROUTER_API_KEY"
142
+ default_model = "openrouter:openai/gpt-4o-mini"
143
+ else:
144
+ key_prompt = " API Key: "
145
+ key_name = "OPENAI_API_KEY"
146
+ default_model = "openai:gpt-4o"
126
147
 
127
- # Compare configs to see if anything changed
148
+ api_key = await ui.input(
149
+ "step2",
150
+ pretext=key_prompt,
151
+ is_password=True,
152
+ state_manager=self.state_manager,
153
+ )
154
+ api_key = api_key.strip()
155
+
156
+ if api_key:
157
+ # Set the environment variable
158
+ self.state_manager.session.user_config["env"][key_name] = api_key
159
+
160
+ # Set base URL in environment for OpenRouter
161
+ if "openrouter.ai" in base_url.lower():
162
+ import os
163
+ os.environ["OPENAI_BASE_URL"] = base_url
164
+
165
+ # Set default model
166
+ self.state_manager.session.user_config["default_model"] = default_model
167
+
168
+ # Save configuration
128
169
  current_config = json.dumps(self.state_manager.session.user_config, sort_keys=True)
129
170
  if initial_config != current_config:
130
171
  if user_configuration.save_config(self.state_manager):
131
- message = f"Config saved to: [bold]{self.config_file}[/bold]"
132
- await ui.panel("Finished", message, top=0, border_style=UI_COLORS["success"])
172
+ message = (
173
+ f" Configuration saved!\n\n"
174
+ f"Default model: {default_model}\n"
175
+ f"Config file: {self.config_file}\n\n"
176
+ f"You can change models anytime with /model"
177
+ )
178
+ await ui.panel("Setup Complete", message, top=0, border_style=UI_COLORS["success"])
133
179
  else:
134
180
  await ui.error("Failed to save configuration.")
135
181
  else:
136
182
  await ui.panel(
137
183
  "Setup canceled",
138
- "At least one API key is required.",
184
+ "An API key is required to use TunaCode.",
139
185
  border_style=UI_COLORS["warning"],
140
186
  )
141
187
 
142
- async def _step1_api_keys(self):
143
- """Onboarding step 1: Collect API keys."""
144
- message = (
145
- f"Welcome to {APP_NAME}!\n"
146
- "Let's get you setup. First, we'll need to set some environment variables.\n"
147
- "Skip the ones you don't need."
148
- )
149
- await ui.panel("Setup", message, border_style=UI_COLORS["primary"])
150
- env_keys = self.state_manager.session.user_config["env"].copy()
151
- for key in env_keys:
152
- provider = key_to_title(key)
153
- val = await ui.input(
154
- "step1",
155
- pretext=f" {provider}: ",
156
- is_password=True,
157
- state_manager=self.state_manager,
158
- )
159
- val = val.strip()
160
- if val:
161
- self.state_manager.session.user_config["env"][key] = val
162
-
163
- async def _step2_default_model(self):
164
- """Onboarding step 2: Select default model."""
165
- message = "Which model would you like to use by default?\n\n"
166
-
167
- model_ids = self.model_registry.list_model_ids()
168
- for index, model_id in enumerate(model_ids):
169
- message += f" {index} - {model_id}\n"
170
- message = message.strip()
171
-
172
- await ui.panel("Default Model", message, border_style=UI_COLORS["primary"])
173
- choice = await ui.input(
174
- "step2",
175
- pretext=" Default model (#): ",
176
- validator=ui.ModelValidator(len(model_ids)),
177
- state_manager=self.state_manager,
178
- )
179
- self.state_manager.session.user_config["default_model"] = model_ids[int(choice)]
@@ -32,6 +32,7 @@ async def input(
32
32
  lexer=None,
33
33
  timeoutlen: float = 0.05,
34
34
  state_manager: Optional[StateManager] = None,
35
+ default: str = "",
35
36
  ) -> str:
36
37
  """
37
38
  Prompt for user input using simplified prompt management.
@@ -48,6 +49,7 @@ async def input(
48
49
  lexer: Optional lexer for syntax highlighting
49
50
  timeoutlen: Timeout length for input
50
51
  state_manager: The state manager for session storage
52
+ default: Default value to pre-fill in the input
51
53
 
52
54
  Returns:
53
55
  User input string
@@ -62,6 +64,7 @@ async def input(
62
64
  completer=completer,
63
65
  lexer=lexer,
64
66
  timeoutlen=timeoutlen,
67
+ default=default,
65
68
  )
66
69
 
67
70
  # Create prompt manager
@@ -28,6 +28,7 @@ class PromptConfig:
28
28
  completer: Optional[Completer] = None
29
29
  lexer: Optional[Lexer] = None
30
30
  timeoutlen: float = 0.05
31
+ default: str = ""
31
32
 
32
33
 
33
34
  class PromptManager:
@@ -107,6 +108,7 @@ class PromptManager:
107
108
  is_password=config.is_password,
108
109
  validator=config.validator,
109
110
  multiline=config.multiline,
111
+ default=config.default,
110
112
  )
111
113
 
112
114
  # Clean up response
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tunacode-cli
3
- Version: 0.0.7
3
+ Version: 0.0.8
4
4
  Summary: Your agentic CLI developer.
5
5
  Author-email: larock22 <noreply@github.com>
6
6
  License-Expression: MIT
@@ -23,7 +23,7 @@ Requires-Dist: prompt_toolkit==3.0.51
23
23
  Requires-Dist: tiny_agent_os>=0.1.0
24
24
  Requires-Dist: pygments==2.19.1
25
25
  Requires-Dist: rich==14.0.0
26
- Requires-Dist: typer==0.15.3
26
+ Requires-Dist: typer==0.12.5
27
27
  Requires-Dist: pyyaml>=6.0
28
28
  Provides-Extra: dev
29
29
  Requires-Dist: build; extra == "dev"
@@ -107,6 +107,12 @@ tunacode
107
107
 
108
108
  # Update to latest version
109
109
  tunacode --update
110
+
111
+ # Start with a specific model
112
+ tunacode --model openrouter:openai/gpt-4o-mini
113
+
114
+ # Use a custom OpenAI-compatible API endpoint
115
+ tunacode --base-url https://your-api.com/v1 --model custom:gpt-4
110
116
  ```
111
117
 
112
118
  ## 📋 Commands
@@ -144,19 +150,72 @@ Configuration is stored in `~/.config/tunacode.json`:
144
150
  }
145
151
  ```
146
152
 
153
+ ### Environment Variables
154
+
155
+ TunaCode automatically loads environment variables from a `.env` file in your current directory:
156
+
157
+ ```bash
158
+ # .env file
159
+ OPENAI_API_KEY=sk-...
160
+ OPENROUTER_API_KEY=sk-or-v1-...
161
+ ANTHROPIC_API_KEY=sk-ant-...
162
+ ```
163
+
164
+ Environment variables take precedence over config file values.
165
+
166
+ ### TinyAgent Configuration
167
+
168
+ TunaCode uses [TinyAgent](https://github.com/alchemiststudiosDOTai/tiny_agent_os) under the hood. Advanced configuration is stored in `~/.config/tunacode_config.yml`:
169
+
170
+ ```yaml
171
+ # Model and API configuration
172
+ base_url: ${OPENAI_BASE_URL:-https://api.openai.com/v1}
173
+ model:
174
+ default: "gpt-4o" # Overridden by TunaCode's model selection
175
+
176
+ # File operations
177
+ file_operations:
178
+ max_file_size: 10_485_760 # 10 MB
179
+ allow_overwrite: true
180
+
181
+ # Retry configuration
182
+ retries:
183
+ max_attempts: 3
184
+ temperature: { initial: 0.2, increment: 0.3, max: 0.8 }
185
+ ```
186
+
187
+ This file is automatically created during installation. Most users won't need to modify it.
188
+
147
189
  ### Using OpenRouter (100+ Models)
148
190
 
149
191
  ```bash
150
- # Add your OpenRouter API key to config
151
- # Then run with OpenRouter base URL:
152
- OPENAI_BASE_URL="https://openrouter.ai/api/v1" tunacode
192
+ # Add your OpenRouter API key to config or .env file
193
+ # TunaCode automatically sets the correct base URL for OpenRouter models
153
194
 
154
195
  # Use any OpenRouter model:
196
+ tunacode --model openrouter:openai/gpt-4o-mini
197
+ tunacode --model openrouter:anthropic/claude-3.5-sonnet
198
+
199
+ # Or switch models inside TunaCode:
155
200
  /model openrouter:anthropic/claude-3-opus
156
201
  /model openrouter:mistralai/devstral-small
157
202
  /model openrouter:openai/gpt-4.1
158
203
  ```
159
204
 
205
+ ### OpenAI-Compatible APIs
206
+
207
+ TunaCode supports any OpenAI-compatible API endpoint. The `--base-url` flag overrides the API endpoint for providers that use the OpenAI API format:
208
+
209
+ ```bash
210
+ # Use a local LLM server
211
+ tunacode --base-url http://localhost:8080/v1 --model local:llama2
212
+
213
+ # Use alternative OpenAI-compatible services
214
+ tunacode --base-url https://api.together.ai/v1 --model together:llama-2-70b
215
+ ```
216
+
217
+ **Note**: The base URL override only works with OpenAI-compatible APIs that follow the same request/response format as OpenAI's API.
218
+
160
219
  ## 🛡️ Undo System
161
220
 
162
221
  TunaCode provides **three layers of protection** for your files:
@@ -2,7 +2,7 @@ prompt_toolkit==3.0.51
2
2
  tiny_agent_os>=0.1.0
3
3
  pygments==2.19.1
4
4
  rich==14.0.0
5
- typer==0.15.3
5
+ typer==0.12.5
6
6
  pyyaml>=6.0
7
7
 
8
8
  [dev]
File without changes
File without changes
File without changes