termux-ai 0.2.0__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.
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Istiak Ahmmed Soyeb
4
+ Copyright (c) 2026 attajak (https://github.com/attajak)
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
@@ -0,0 +1,207 @@
1
+ Metadata-Version: 2.4
2
+ Name: termux-ai
3
+ Version: 0.2.0
4
+ Summary: A lightweight CLI tool for AI integration in your terminal.
5
+ Author-email: estiaksoyeb <estiakahamed122@gmail.com>, attajak <janrak@gmail.com>
6
+ License: MIT License
7
+
8
+ Copyright (c) 2025 Istiak Ahmmed Soyeb
9
+ Copyright (c) 2026 attajak (https://github.com/attajak)
10
+
11
+ Permission is hereby granted, free of charge, to any person obtaining a copy
12
+ of this software and associated documentation files (the "Software"), to deal
13
+ in the Software without restriction, including without limitation the rights
14
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15
+ copies of the Software, and to permit persons to whom the Software is
16
+ furnished to do so, subject to the following conditions:
17
+
18
+ The above copyright notice and this permission notice shall be included in all
19
+ copies or substantial portions of the Software.
20
+
21
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27
+ SOFTWARE.
28
+
29
+ Project-URL: Homepage, https://github.com/attajak/termai
30
+ Project-URL: Bug Reports, https://github.com/attajak/termai/issues
31
+ Project-URL: Funding, https://paypal.me/attajak
32
+ Project-URL: Source, https://github.com/attajak/termai
33
+ Keywords: termai,termux-ai,cli,ai,termux
34
+ Requires-Python: >=3.8
35
+ Description-Content-Type: text/markdown
36
+ License-File: LICENSE
37
+ Requires-Dist: requests
38
+ Dynamic: license-file
39
+
40
+ ## Termai
41
+ Termai is a lightweight, zero-dependency CLI wrapper for Google's Gemini AI, built for Termux on Android and general Linux environments.
42
+ It brings the power of Large Language Models (LLMs) directly to your command line, following the Unix philosophy of piping and standard streams.
43
+
44
+ ## โšก Features
45
+ * **๐Ÿš€ Lightweight:** Uses standard Python requests. No heavy SDKs or complex dependencies.
46
+ * **๐ŸŸข Unix Compatible:** Supports piping (stdin). Feed logs, code, or text files directly into the AI.
47
+ * **๐Ÿ›  Configurable:** Built-in JSON configuration system (ai --config) to edit System Prompts, Temperature, and Models.
48
+ * **โšก Fast:** Defaults to gemini-2.5-flash for instant responses.
49
+ * **๐ŸŽจ Clean UI:** Minimalist output with syntax-highlighted green text.
50
+ * **๐Ÿงน Auto-Cleanup:** The installer sets everything up and deletes the repository to save space.
51
+
52
+ ## ๐Ÿ“ฅ Installation
53
+ ### Method 1: Global Install (Recommended)
54
+ You can install Termai directly using `pip` or `pipx`:
55
+ ```bash
56
+ # Using pip
57
+ pip install .
58
+
59
+ # Using pipx (cleanest)
60
+ pipx install .
61
+ ```
62
+ This will make the `ai` command available globally.
63
+
64
+ ### Method 2: Manual Setup (for Development)
65
+ If you want to contribute or run Termai in a development environment:
66
+ ## ๐Ÿ”‘ Setup
67
+ On the very first run, Termai will ask for your Google Gemini API Key.
68
+ * Get a free API key here: Google AI Studio
69
+ * Run the command:
70
+ ```bash
71
+ ai "hello"
72
+ ```
73
+
74
+ * Paste your key when prompted. It will be saved locally.
75
+ ## ๐Ÿ’ป Usage
76
+ 1. Basic Questions
77
+ Ask anything directly from the terminal.
78
+ ai "How do I untar a file in Linux?"
79
+
80
+ 2. Piping (The Power Move)
81
+ Feed output from other commands into Termai.
82
+ Debug an error log:
83
+ ```bash
84
+ cat error.log | ai "Explain what caused this crash"
85
+ ```
86
+
87
+ Explain a script:
88
+ ```bash
89
+ cat install.sh | ai "What does this script do?"
90
+ ```
91
+
92
+ Generate code and save it:
93
+ ```bash
94
+ ai "Write a Python hello world script" > hello.py
95
+ ```
96
+
97
+ ## โš™๏ธ Configuration
98
+ Termai comes with a built-in configuration editor. You can change the AI provider, model, and personality.
99
+ Run:
100
+ ```bash
101
+ ai --config
102
+ ```
103
+
104
+ This opens `config.json` in your preferred editor. The editor is chosen based on the following priority:
105
+ 1. The `$EDITOR` environment variable.
106
+ 2. `vim` (if installed).
107
+ 3. `nano` (as a fallback).
108
+
109
+ The configuration file looks like this:
110
+ ```json
111
+ {
112
+ "provider": "gemini",
113
+ "proxy": "http://user:pass@127.0.0.1:1080",
114
+ "gemini_config": {
115
+ "api_key": "YOUR_GEMINI_KEY",
116
+ "model_name": "gemini-2.5-flash",
117
+ "system_instruction": "You are a CLI assistant for Termux...",
118
+ "generation_config": {
119
+ "temperature": 0.7,
120
+ "maxOutputTokens": 1024
121
+ }
122
+ },
123
+ "openai_config": {
124
+ "api_key": "YOUR_OPENAI_KEY",
125
+ "model_name": "gpt-4o",
126
+ "system_instruction": "You are a helpful assistant.",
127
+ "temperature": 0.7,
128
+ "max_tokens": 1024
129
+ }
130
+ }
131
+ ```
132
+
133
+ * **`provider`**: Set to `"gemini"` or `"openai"` to choose your AI provider.
134
+ * **`proxy`**: (Optional) Set an HTTP or HTTPS proxy for all requests.
135
+ * **`gemini_config`**: Settings for when `provider` is `"gemini"`.
136
+ * `model_name`: Change to `gemini-2.5-pro` or other available models.
137
+ * `system_instruction`: Give the AI a persona.
138
+ * `temperature`: Set to `1.0` for creative answers, `0.1` for precise logic.
139
+ * **`openai_config`**: Settings for when `provider` is `"openai"`.
140
+ * `model_name`: Change to `gpt-3.5-turbo`, etc.
141
+ * `system_instruction`: A different persona for ChatGPT.
142
+ * `temperature`: Controls randomness.
143
+ * `max_tokens`: The maximum number of tokens to generate.
144
+
145
+ ## ๐Ÿ›  Development
146
+ If you want to contribute or run Termai in a development environment:
147
+
148
+ 1. **Clone and set up a virtual environment:**
149
+ ```bash
150
+ git clone https://github.com/estiaksoyeb/termai
151
+ cd termai
152
+ python -m venv .venv
153
+ source .venv/bin/activate
154
+ ```
155
+
156
+ 2. **Install dependencies:**
157
+ ```bash
158
+ pip install -r requirements.txt
159
+ ```
160
+
161
+ 3. **Run in development mode:**
162
+ ```bash
163
+ pip install -e .
164
+ # Now the 'ai' command will use your local development version.
165
+ ```
166
+
167
+ ## โ“ Help & Troubleshooting
168
+ **Command List:**
169
+ ```bash
170
+ ai --help
171
+ ```
172
+
173
+ **Re-configure API Keys:**
174
+
175
+ To reset and re-enter your API keys, use the `--reinstall` flag.
176
+ ```bash
177
+ ai --reinstall
178
+ ```
179
+
180
+ **Debug Mode:**
181
+
182
+ If the AI isn't responding or you are getting errors, run:
183
+ ```bash
184
+ ai --debug "your question"
185
+ ```
186
+ This will print the raw server response and error codes.
187
+
188
+ **Debug Configuration:**
189
+ If you are having issues with your configuration, you can use the `--debug-config` flag to print the loaded configuration. API keys will be redacted for security.
190
+ ```bash
191
+ ai --debug-config
192
+ ```
193
+
194
+ ## ๐Ÿ—‘ Uninstallation
195
+ ### If installed via pip/pipx:
196
+ ```bash
197
+ pip uninstall termai
198
+ # or
199
+ pipx uninstall termai
200
+ ```
201
+
202
+ ## ๐Ÿ“„ License
203
+ This project is licensed under the MIT License.
204
+ You are free to use, modify, and distribute this software. See the LICENSE file for more details.
205
+ <p align="center">
206
+ Made with โค๏ธ for CLI enthusiasts
207
+ </p>
@@ -0,0 +1,168 @@
1
+ ## Termai
2
+ Termai is a lightweight, zero-dependency CLI wrapper for Google's Gemini AI, built for Termux on Android and general Linux environments.
3
+ It brings the power of Large Language Models (LLMs) directly to your command line, following the Unix philosophy of piping and standard streams.
4
+
5
+ ## โšก Features
6
+ * **๐Ÿš€ Lightweight:** Uses standard Python requests. No heavy SDKs or complex dependencies.
7
+ * **๐ŸŸข Unix Compatible:** Supports piping (stdin). Feed logs, code, or text files directly into the AI.
8
+ * **๐Ÿ›  Configurable:** Built-in JSON configuration system (ai --config) to edit System Prompts, Temperature, and Models.
9
+ * **โšก Fast:** Defaults to gemini-2.5-flash for instant responses.
10
+ * **๐ŸŽจ Clean UI:** Minimalist output with syntax-highlighted green text.
11
+ * **๐Ÿงน Auto-Cleanup:** The installer sets everything up and deletes the repository to save space.
12
+
13
+ ## ๐Ÿ“ฅ Installation
14
+ ### Method 1: Global Install (Recommended)
15
+ You can install Termai directly using `pip` or `pipx`:
16
+ ```bash
17
+ # Using pip
18
+ pip install .
19
+
20
+ # Using pipx (cleanest)
21
+ pipx install .
22
+ ```
23
+ This will make the `ai` command available globally.
24
+
25
+ ### Method 2: Manual Setup (for Development)
26
+ If you want to contribute or run Termai in a development environment:
27
+ ## ๐Ÿ”‘ Setup
28
+ On the very first run, Termai will ask for your Google Gemini API Key.
29
+ * Get a free API key here: Google AI Studio
30
+ * Run the command:
31
+ ```bash
32
+ ai "hello"
33
+ ```
34
+
35
+ * Paste your key when prompted. It will be saved locally.
36
+ ## ๐Ÿ’ป Usage
37
+ 1. Basic Questions
38
+ Ask anything directly from the terminal.
39
+ ai "How do I untar a file in Linux?"
40
+
41
+ 2. Piping (The Power Move)
42
+ Feed output from other commands into Termai.
43
+ Debug an error log:
44
+ ```bash
45
+ cat error.log | ai "Explain what caused this crash"
46
+ ```
47
+
48
+ Explain a script:
49
+ ```bash
50
+ cat install.sh | ai "What does this script do?"
51
+ ```
52
+
53
+ Generate code and save it:
54
+ ```bash
55
+ ai "Write a Python hello world script" > hello.py
56
+ ```
57
+
58
+ ## โš™๏ธ Configuration
59
+ Termai comes with a built-in configuration editor. You can change the AI provider, model, and personality.
60
+ Run:
61
+ ```bash
62
+ ai --config
63
+ ```
64
+
65
+ This opens `config.json` in your preferred editor. The editor is chosen based on the following priority:
66
+ 1. The `$EDITOR` environment variable.
67
+ 2. `vim` (if installed).
68
+ 3. `nano` (as a fallback).
69
+
70
+ The configuration file looks like this:
71
+ ```json
72
+ {
73
+ "provider": "gemini",
74
+ "proxy": "http://user:pass@127.0.0.1:1080",
75
+ "gemini_config": {
76
+ "api_key": "YOUR_GEMINI_KEY",
77
+ "model_name": "gemini-2.5-flash",
78
+ "system_instruction": "You are a CLI assistant for Termux...",
79
+ "generation_config": {
80
+ "temperature": 0.7,
81
+ "maxOutputTokens": 1024
82
+ }
83
+ },
84
+ "openai_config": {
85
+ "api_key": "YOUR_OPENAI_KEY",
86
+ "model_name": "gpt-4o",
87
+ "system_instruction": "You are a helpful assistant.",
88
+ "temperature": 0.7,
89
+ "max_tokens": 1024
90
+ }
91
+ }
92
+ ```
93
+
94
+ * **`provider`**: Set to `"gemini"` or `"openai"` to choose your AI provider.
95
+ * **`proxy`**: (Optional) Set an HTTP or HTTPS proxy for all requests.
96
+ * **`gemini_config`**: Settings for when `provider` is `"gemini"`.
97
+ * `model_name`: Change to `gemini-2.5-pro` or other available models.
98
+ * `system_instruction`: Give the AI a persona.
99
+ * `temperature`: Set to `1.0` for creative answers, `0.1` for precise logic.
100
+ * **`openai_config`**: Settings for when `provider` is `"openai"`.
101
+ * `model_name`: Change to `gpt-3.5-turbo`, etc.
102
+ * `system_instruction`: A different persona for ChatGPT.
103
+ * `temperature`: Controls randomness.
104
+ * `max_tokens`: The maximum number of tokens to generate.
105
+
106
+ ## ๐Ÿ›  Development
107
+ If you want to contribute or run Termai in a development environment:
108
+
109
+ 1. **Clone and set up a virtual environment:**
110
+ ```bash
111
+ git clone https://github.com/estiaksoyeb/termai
112
+ cd termai
113
+ python -m venv .venv
114
+ source .venv/bin/activate
115
+ ```
116
+
117
+ 2. **Install dependencies:**
118
+ ```bash
119
+ pip install -r requirements.txt
120
+ ```
121
+
122
+ 3. **Run in development mode:**
123
+ ```bash
124
+ pip install -e .
125
+ # Now the 'ai' command will use your local development version.
126
+ ```
127
+
128
+ ## โ“ Help & Troubleshooting
129
+ **Command List:**
130
+ ```bash
131
+ ai --help
132
+ ```
133
+
134
+ **Re-configure API Keys:**
135
+
136
+ To reset and re-enter your API keys, use the `--reinstall` flag.
137
+ ```bash
138
+ ai --reinstall
139
+ ```
140
+
141
+ **Debug Mode:**
142
+
143
+ If the AI isn't responding or you are getting errors, run:
144
+ ```bash
145
+ ai --debug "your question"
146
+ ```
147
+ This will print the raw server response and error codes.
148
+
149
+ **Debug Configuration:**
150
+ If you are having issues with your configuration, you can use the `--debug-config` flag to print the loaded configuration. API keys will be redacted for security.
151
+ ```bash
152
+ ai --debug-config
153
+ ```
154
+
155
+ ## ๐Ÿ—‘ Uninstallation
156
+ ### If installed via pip/pipx:
157
+ ```bash
158
+ pip uninstall termai
159
+ # or
160
+ pipx uninstall termai
161
+ ```
162
+
163
+ ## ๐Ÿ“„ License
164
+ This project is licensed under the MIT License.
165
+ You are free to use, modify, and distribute this software. See the LICENSE file for more details.
166
+ <p align="center">
167
+ Made with โค๏ธ for CLI enthusiasts
168
+ </p>
@@ -0,0 +1,28 @@
1
+ [build-system]
2
+ requires = ["setuptools", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "termux-ai"
7
+ version = "0.2.0"
8
+ description = "A lightweight CLI tool for AI integration in your terminal."
9
+ keywords = ["termai", "termux-ai", "cli", "ai", "termux"]
10
+ readme = "README.md"
11
+ license = {file = "LICENSE"}
12
+ authors = [
13
+ {name = "estiaksoyeb", email = "estiakahamed122@gmail.com"},
14
+ {name = "attajak", email = "janrak@gmail.com"},
15
+ ]
16
+ requires-python = ">=3.8"
17
+ dependencies = [
18
+ "requests",
19
+ ]
20
+
21
+ [project.urls]
22
+ "Homepage" = "https://github.com/attajak/termai"
23
+ "Bug Reports" = "https://github.com/attajak/termai/issues"
24
+ "Funding" = "https://paypal.me/attajak"
25
+ "Source" = "https://github.com/attajak/termai"
26
+
27
+ [project.scripts]
28
+ ai = "termai.cli:main"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1 @@
1
+ # Termai package initialization
@@ -0,0 +1,4 @@
1
+ from .cli import main
2
+
3
+ if __name__ == "__main__":
4
+ main()
@@ -0,0 +1,24 @@
1
+ from .providers.gemini import GeminiProvider
2
+ from .providers.openai import OpenAIProvider
3
+
4
+ PROVIDERS = {
5
+ "gemini": GeminiProvider(),
6
+ "openai": OpenAIProvider()
7
+ }
8
+
9
+ def send_request(config, user_input, debug_mode):
10
+ provider_name = config.get("provider", "gemini")
11
+ provider = PROVIDERS.get(provider_name)
12
+
13
+ if not provider:
14
+ print(f"[Error] Provider '{provider_name}' is not supported.")
15
+ return 1
16
+
17
+ return provider.send_request(config, user_input, debug_mode)
18
+
19
+ # Keep these for backward compatibility if needed in other parts of the code
20
+ def send_gemini_request(config, user_input, debug_mode):
21
+ return GeminiProvider().send_request(config, user_input, debug_mode)
22
+
23
+ def send_openai_request(config, user_input, debug_mode):
24
+ return OpenAIProvider().send_request(config, user_input, debug_mode)
@@ -0,0 +1,65 @@
1
+ import sys
2
+ import json
3
+ import copy
4
+ from .constants import APP_NAME, CONFIG_FILE
5
+ from .config import load_config, open_editor
6
+ from .api import send_request
7
+ from .ui import print_help
8
+
9
+ def cli_entry_point():
10
+ # Handle --reinstall flag first
11
+ if "--reinstall" in sys.argv:
12
+ if CONFIG_FILE.exists():
13
+ print(f"[{APP_NAME}] Deleting existing config for reinstall...")
14
+ CONFIG_FILE.unlink()
15
+ else:
16
+ print(f"[{APP_NAME}] No existing config found. Starting first-time setup...")
17
+
18
+ config = load_config()
19
+
20
+ if "--reinstall" in sys.argv:
21
+ print(f"[{APP_NAME}] Reinstall complete.")
22
+ return 0
23
+
24
+ # Handle --debug-config flag
25
+ if "--debug-config" in sys.argv:
26
+ if not config:
27
+ print("[Error] No configuration file found. Run `ai --reinstall` to create one.")
28
+ return 1
29
+
30
+ debug_config = copy.deepcopy(config)
31
+ if "gemini_config" in debug_config and "api_key" in debug_config["gemini_config"]:
32
+ key = debug_config["gemini_config"]["api_key"]
33
+ debug_config["gemini_config"]["api_key"] = f"***{key[-4:]}" if key else ""
34
+ if "openai_config" in debug_config and "api_key" in debug_config["openai_config"]:
35
+ key = debug_config["openai_config"]["api_key"]
36
+ debug_config["openai_config"]["api_key"] = f"***{key[-4:]}" if key else ""
37
+
38
+ print(json.dumps(debug_config, indent=4))
39
+ return 0
40
+
41
+ if config is None and not sys.stdin.isatty():
42
+ return 1
43
+
44
+ if "--help" in sys.argv or "-h" in sys.argv:
45
+ return print_help()
46
+
47
+ if "--config" in sys.argv:
48
+ return open_editor()
49
+
50
+ debug_mode = "--debug" in sys.argv
51
+ args = [arg for arg in sys.argv[1:] if arg not in ["--debug", "--config", "--help", "-h", "--reinstall", "--debug-config"]]
52
+
53
+ user_input = ""
54
+ if not sys.stdin.isatty():
55
+ user_input = sys.stdin.read().strip()
56
+ if args: user_input += "\n" + " ".join(args)
57
+ elif args:
58
+ user_input = " ".join(args)
59
+ else:
60
+ return print_help()
61
+
62
+ return send_request(config, user_input, debug_mode)
63
+
64
+ def main():
65
+ sys.exit(cli_entry_point())
@@ -0,0 +1,151 @@
1
+ import os
2
+ import sys
3
+ import json
4
+ import subprocess
5
+ import copy
6
+ import shutil
7
+ from .constants import APP_NAME, DATA_DIR, CONFIG_FILE, OLD_KEY_FILE
8
+
9
+ # --- Default Settings ---
10
+ DEFAULT_CONFIG = {
11
+ "provider": "gemini",
12
+ "proxy": "",
13
+ "gemini_config": {
14
+ "api_key": "",
15
+ "model_name": "gemini-2.5-flash",
16
+ "system_instruction": "You are a CLI assistant for command-line users. Do NOT use Markdown. Do NOT use backticks. Do NOT use bolding. Just write plain text. Keep answers concise.",
17
+ "generation_config": {
18
+ "temperature": 0.7,
19
+ "top_p": 0.9,
20
+ "top_k": 40,
21
+ "maxOutputTokens": 1024
22
+ }
23
+ },
24
+ "openai_config": {
25
+ "api_key": "",
26
+ "model_name": "gpt-4o",
27
+ "system_instruction": "You are a CLI assistant for command-line users. Do NOT use Markdown. Do NOT use backticks. Do NOT use bolding. Just write plain text. Keep answers concise.",
28
+ "temperature": 0.7,
29
+ "max_tokens": 1024
30
+ }
31
+ }
32
+
33
+ def load_config():
34
+ """
35
+ Loads config.json.
36
+ Handles migration from old 'key' file and old flat config structure if needed.
37
+ Creates default file if missing.
38
+ """
39
+ # Ensure directory exists
40
+ if not DATA_DIR.exists():
41
+ DATA_DIR.mkdir(parents=True, exist_ok=True)
42
+
43
+ config = {}
44
+ # 1. Check for Config File
45
+ if CONFIG_FILE.exists():
46
+ try:
47
+ with open(CONFIG_FILE, "r") as f:
48
+ config = json.load(f)
49
+ except json.JSONDecodeError:
50
+ print(f"[Error] Your config file ({CONFIG_FILE}) is invalid JSON.")
51
+ print("Please fix it or delete it to reset defaults.")
52
+ sys.exit(1)
53
+
54
+ # Migration from old flat structure to new nested structure
55
+ if "api_key" in config:
56
+ print(f"[{APP_NAME}] Migrating config to new nested structure...")
57
+ new_config = copy.deepcopy(DEFAULT_CONFIG)
58
+ # Preserve old top-level keys
59
+ new_config["proxy"] = config.get("proxy", "")
60
+
61
+ # Move gemini-specific keys
62
+ new_config["gemini_config"]["api_key"] = config.get("api_key", "")
63
+ new_config["gemini_config"]["model_name"] = config.get("model_name", DEFAULT_CONFIG["gemini_config"]["model_name"])
64
+ new_config["gemini_config"]["system_instruction"] = config.get("system_instruction", DEFAULT_CONFIG["gemini_config"]["system_instruction"])
65
+ new_config["gemini_config"]["generation_config"] = config.get("generation_config", DEFAULT_CONFIG["gemini_config"]["generation_config"])
66
+
67
+ with open(CONFIG_FILE, "w") as f:
68
+ json.dump(new_config, f, indent=4)
69
+ print("Migration complete.")
70
+ return new_config
71
+
72
+ return config
73
+
74
+ # If no config file exists, proceed with first run setup
75
+ # 2. Migration: If no config, check for old key file
76
+ gemini_api_key = ""
77
+ backup_file = DATA_DIR / "key.bak"
78
+ if OLD_KEY_FILE.exists():
79
+ print(f"[{APP_NAME}] Migrating legacy key file to new config format...")
80
+ with open(OLD_KEY_FILE, "r") as f:
81
+ gemini_api_key = f.read().strip()
82
+ OLD_KEY_FILE.rename(backup_file)
83
+
84
+ # 3. First Run Setup
85
+ new_config = copy.deepcopy(DEFAULT_CONFIG)
86
+ if sys.stdin.isatty():
87
+ print(f"[{APP_NAME}] First run! Choose your primary AI provider.")
88
+ provider = ""
89
+ while provider not in ["1", "2"]:
90
+ provider = input("Enter 1 for Gemini or 2 for OpenAI: ").strip()
91
+
92
+ if provider == "1":
93
+ new_config["provider"] = "gemini"
94
+ if not gemini_api_key:
95
+ print(f"[{APP_NAME}] Enter your Gemini API Key. Get it from aistudio.google.com")
96
+ gemini_api_key = input("Gemini API Key: ").strip()
97
+ if not gemini_api_key:
98
+ print("Error: Gemini key cannot be empty.")
99
+ sys.exit(1)
100
+ new_config["gemini_config"]["api_key"] = gemini_api_key
101
+
102
+ elif provider == "2":
103
+ new_config["provider"] = "openai"
104
+ print(f"[{APP_NAME}] Enter your OpenAI API Key. Get it from platform.openai.com")
105
+ openai_api_key = input("OpenAI API Key: ").strip()
106
+ if not openai_api_key:
107
+ print("Error: OpenAI key cannot be empty.")
108
+ sys.exit(1)
109
+ new_config["openai_config"]["api_key"] = openai_api_key
110
+ else:
111
+ # Default to Gemini if non-interactive and no config exists
112
+ # This part might need adjustment based on desired non-interactive behavior
113
+ if not gemini_api_key:
114
+ return None # Cannot proceed without an API key
115
+ new_config["gemini_config"]["api_key"] = gemini_api_key
116
+
117
+ # Save the new configuration
118
+ with open(CONFIG_FILE, "w") as f:
119
+ json.dump(new_config, f, indent=4)
120
+
121
+ print(f"Configuration saved to {CONFIG_FILE}\n")
122
+
123
+ # Clean up the legacy key backup file if it exists after migration
124
+ if backup_file.exists():
125
+ backup_file.unlink()
126
+
127
+ return new_config
128
+
129
+ def open_editor():
130
+ """
131
+ Opens the config file in the user's preferred editor with a fallback mechanism.
132
+ Priority: $EDITOR > vim > nano
133
+ """
134
+ # 1. Prioritize the user's explicit choice
135
+ editor = os.getenv('EDITOR')
136
+
137
+ # 2. If no $EDITOR, try to find 'vim'
138
+ if not editor and shutil.which('vim'):
139
+ editor = 'vim'
140
+
141
+ # 3. If still no editor, fall back to 'nano'
142
+ if not editor:
143
+ editor = 'nano'
144
+
145
+ print(f"Opening config in {editor}...")
146
+ try:
147
+ subprocess.call([editor, str(CONFIG_FILE)])
148
+ except FileNotFoundError:
149
+ print(f"[Error] Editor '{editor}' not found. Please install it or set the $EDITOR environment variable.")
150
+ return 1
151
+ return 0 # Return 0 for success
@@ -0,0 +1,15 @@
1
+ from pathlib import Path
2
+
3
+ # --- Configuration Paths ---
4
+ APP_NAME = "termai"
5
+ DATA_DIR = Path.home() / ".local/share" / APP_NAME
6
+ # We now use a JSON file for all settings
7
+ CONFIG_FILE = DATA_DIR / "config.json"
8
+ # Legacy file path for migration
9
+ OLD_KEY_FILE = DATA_DIR / "key"
10
+
11
+ # --- Colors ---
12
+ GREEN = "\033[92m"
13
+ CYAN = "\033[96m"
14
+ YELLOW = "\033[93m"
15
+ RESET = "\033[0m"
File without changes
@@ -0,0 +1,7 @@
1
+ from abc import ABC, abstractmethod
2
+
3
+ class BaseProvider(ABC):
4
+ @abstractmethod
5
+ def send_request(self, config, user_input, debug_mode):
6
+ """Send a request to the AI model."""
7
+ pass
@@ -0,0 +1,50 @@
1
+ import requests
2
+ from ..constants import GREEN, RESET
3
+ from .base import BaseProvider
4
+
5
+ class GeminiProvider(BaseProvider):
6
+ def send_request(self, config, user_input, debug_mode):
7
+ gemini_config = config.get("gemini_config", {})
8
+ api_key = gemini_config.get("api_key")
9
+ model_name = gemini_config.get("model_name", "gemini-2.5-flash")
10
+ system_instr = gemini_config.get("system_instruction", "")
11
+ gen_config = gemini_config.get("generation_config", {})
12
+ proxy = config.get("proxy", "")
13
+ api_url = f"https://generativelanguage.googleapis.com/v1beta/models/{model_name}:generateContent?key={api_key}"
14
+ payload = {
15
+ "contents": [{"parts": [{"text": user_input}]}],
16
+ "systemInstruction": {"parts": [{"text": system_instr}]},
17
+ "generationConfig": gen_config
18
+ }
19
+ if debug_mode: print(f"[Debug] Provider: Gemini | Model: {model_name} | Temp: {gen_config.get('temperature')} | Proxy: {proxy if proxy else 'None'}")
20
+ try:
21
+ proxies = {"http": proxy, "https": proxy} if proxy else None
22
+ response = requests.post(api_url, json=payload, proxies=proxies)
23
+ if debug_mode:
24
+ print(f"[Debug] Status: {response.status_code}")
25
+ if response.status_code != 200:
26
+ if response.status_code == 429:
27
+ print(f"\n[Error 429] You have exceeded your Gemini API quota.")
28
+ print("Please check your usage and billing details at aistudio.google.com.")
29
+ else:
30
+ print(f"\n[Error {response.status_code}]")
31
+ print(response.text)
32
+ return 1
33
+ data = response.json()
34
+ if "promptFeedback" in data and "blockReason" in data["promptFeedback"]:
35
+ print(f"[Blocked] Reason: {data['promptFeedback']['blockReason']}")
36
+ return 0
37
+ if "candidates" in data and data["candidates"]:
38
+ cand = data["candidates"][0]
39
+ if "content" in cand and "parts" in cand["content"] and cand["content"]["parts"]:
40
+ print(f"{GREEN}{cand['content']['parts'][0]['text'].strip()}{RESET}")
41
+ else:
42
+ print("[No content returned]")
43
+ if debug_mode: print(data)
44
+ else:
45
+ print("[Error] Invalid response format from Gemini")
46
+ if debug_mode: print(data)
47
+ return 0
48
+ except Exception as e:
49
+ print(f"\n[Connection Error] {e}")
50
+ return 1
@@ -0,0 +1,57 @@
1
+ import requests
2
+ from ..constants import GREEN, RESET
3
+ from .base import BaseProvider
4
+
5
+ class OpenAIProvider(BaseProvider):
6
+ def send_request(self, config, user_input, debug_mode):
7
+ openai_config = config.get("openai_config", {})
8
+ api_key = openai_config.get("api_key")
9
+ model_name = openai_config.get("model_name", "gpt-4o")
10
+ system_instr = openai_config.get("system_instruction", "")
11
+ temperature = openai_config.get("temperature", 0.7)
12
+ max_tokens = openai_config.get("max_tokens", 1024)
13
+ proxy = config.get("proxy", "")
14
+ api_url = "https://api.openai.com/v1/chat/completions"
15
+ headers = {
16
+ "Content-Type": "application/json",
17
+ "Authorization": f"Bearer {api_key}"
18
+ }
19
+ payload = {
20
+ "model": model_name,
21
+ "messages": [
22
+ {"role": "system", "content": system_instr},
23
+ {"role": "user", "content": user_input}
24
+ ],
25
+ "temperature": temperature,
26
+ "max_tokens": max_tokens
27
+ }
28
+ if debug_mode: print(f"[Debug] Provider: OpenAI | Model: {model_name} | Temp: {temperature} | Proxy: {proxy if proxy else 'None'}")
29
+ try:
30
+ proxies = {"http": proxy, "https": proxy} if proxy else None
31
+ response = requests.post(api_url, headers=headers, json=payload, proxies=proxies)
32
+ if debug_mode:
33
+ print(f"[Debug] Status: {response.status_code}")
34
+ if response.status_code != 200:
35
+ if response.status_code == 429:
36
+ print(f"\n[Error 429] You have exceeded your OpenAI API quota.")
37
+ print("Please check your usage and billing details at platform.openai.com.")
38
+ else:
39
+ print(f"\n[Error {response.status_code}]")
40
+ print(response.text)
41
+ return 1
42
+ data = response.json()
43
+ if "choices" in data and data["choices"]:
44
+ message = data["choices"][0].get("message", {})
45
+ content = message.get("content", "")
46
+ if content:
47
+ print(f"{GREEN}{content.strip()}{RESET}")
48
+ else:
49
+ print("[No content returned]")
50
+ if debug_mode: print(data)
51
+ else:
52
+ print("[Error] Invalid response format from OpenAI")
53
+ if debug_mode: print(data)
54
+ return 0
55
+ except Exception as e:
56
+ print(f"\n[Connection Error] {e}")
57
+ return 1
@@ -0,0 +1,23 @@
1
+ from .constants import GREEN, CYAN, YELLOW, RESET
2
+
3
+ def print_help():
4
+ """Prints the help menu with available commands."""
5
+ print(f"\n{GREEN}Termai - A CLI AI Assistant{RESET}")
6
+ print(f"A lightweight CLI tool for AI integration in your terminal.\n")
7
+
8
+ print(f"{YELLOW}Usage:{RESET}")
9
+ print(f" ai [OPTIONS] \"YOUR QUERY\"")
10
+ print(f" cat file.txt | ai [OPTIONS] \"OPTIONAL PROMPT\"")
11
+
12
+ print(f"\n{YELLOW}Options:{RESET}")
13
+ print(f" {CYAN}--config{RESET} Open configuration file")
14
+ print(f" {CYAN}--debug{RESET} Enable debug mode")
15
+ print(f" {CYAN}--debug-config{RESET} Print the loaded configuration (redacts keys)")
16
+ print(f" {CYAN}--help, -h{RESET} Show this help message")
17
+ print(f" {CYAN}--reinstall{RESET} Re-run the first-time setup")
18
+
19
+ print(f"\n{YELLOW}Examples:{RESET}")
20
+ print(f" ai \"How do I unzip a tar file?\"")
21
+ print(f" ai --config")
22
+ print(f" cat error.log | ai \"Explain this error briefly\"")
23
+ return 0 # Return 0 for success
@@ -0,0 +1,207 @@
1
+ Metadata-Version: 2.4
2
+ Name: termux-ai
3
+ Version: 0.2.0
4
+ Summary: A lightweight CLI tool for AI integration in your terminal.
5
+ Author-email: estiaksoyeb <estiakahamed122@gmail.com>, attajak <janrak@gmail.com>
6
+ License: MIT License
7
+
8
+ Copyright (c) 2025 Istiak Ahmmed Soyeb
9
+ Copyright (c) 2026 attajak (https://github.com/attajak)
10
+
11
+ Permission is hereby granted, free of charge, to any person obtaining a copy
12
+ of this software and associated documentation files (the "Software"), to deal
13
+ in the Software without restriction, including without limitation the rights
14
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15
+ copies of the Software, and to permit persons to whom the Software is
16
+ furnished to do so, subject to the following conditions:
17
+
18
+ The above copyright notice and this permission notice shall be included in all
19
+ copies or substantial portions of the Software.
20
+
21
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27
+ SOFTWARE.
28
+
29
+ Project-URL: Homepage, https://github.com/attajak/termai
30
+ Project-URL: Bug Reports, https://github.com/attajak/termai/issues
31
+ Project-URL: Funding, https://paypal.me/attajak
32
+ Project-URL: Source, https://github.com/attajak/termai
33
+ Keywords: termai,termux-ai,cli,ai,termux
34
+ Requires-Python: >=3.8
35
+ Description-Content-Type: text/markdown
36
+ License-File: LICENSE
37
+ Requires-Dist: requests
38
+ Dynamic: license-file
39
+
40
+ ## Termai
41
+ Termai is a lightweight, zero-dependency CLI wrapper for Google's Gemini AI, built for Termux on Android and general Linux environments.
42
+ It brings the power of Large Language Models (LLMs) directly to your command line, following the Unix philosophy of piping and standard streams.
43
+
44
+ ## โšก Features
45
+ * **๐Ÿš€ Lightweight:** Uses standard Python requests. No heavy SDKs or complex dependencies.
46
+ * **๐ŸŸข Unix Compatible:** Supports piping (stdin). Feed logs, code, or text files directly into the AI.
47
+ * **๐Ÿ›  Configurable:** Built-in JSON configuration system (ai --config) to edit System Prompts, Temperature, and Models.
48
+ * **โšก Fast:** Defaults to gemini-2.5-flash for instant responses.
49
+ * **๐ŸŽจ Clean UI:** Minimalist output with syntax-highlighted green text.
50
+ * **๐Ÿงน Auto-Cleanup:** The installer sets everything up and deletes the repository to save space.
51
+
52
+ ## ๐Ÿ“ฅ Installation
53
+ ### Method 1: Global Install (Recommended)
54
+ You can install Termai directly using `pip` or `pipx`:
55
+ ```bash
56
+ # Using pip
57
+ pip install .
58
+
59
+ # Using pipx (cleanest)
60
+ pipx install .
61
+ ```
62
+ This will make the `ai` command available globally.
63
+
64
+ ### Method 2: Manual Setup (for Development)
65
+ If you want to contribute or run Termai in a development environment:
66
+ ## ๐Ÿ”‘ Setup
67
+ On the very first run, Termai will ask for your Google Gemini API Key.
68
+ * Get a free API key here: Google AI Studio
69
+ * Run the command:
70
+ ```bash
71
+ ai "hello"
72
+ ```
73
+
74
+ * Paste your key when prompted. It will be saved locally.
75
+ ## ๐Ÿ’ป Usage
76
+ 1. Basic Questions
77
+ Ask anything directly from the terminal.
78
+ ai "How do I untar a file in Linux?"
79
+
80
+ 2. Piping (The Power Move)
81
+ Feed output from other commands into Termai.
82
+ Debug an error log:
83
+ ```bash
84
+ cat error.log | ai "Explain what caused this crash"
85
+ ```
86
+
87
+ Explain a script:
88
+ ```bash
89
+ cat install.sh | ai "What does this script do?"
90
+ ```
91
+
92
+ Generate code and save it:
93
+ ```bash
94
+ ai "Write a Python hello world script" > hello.py
95
+ ```
96
+
97
+ ## โš™๏ธ Configuration
98
+ Termai comes with a built-in configuration editor. You can change the AI provider, model, and personality.
99
+ Run:
100
+ ```bash
101
+ ai --config
102
+ ```
103
+
104
+ This opens `config.json` in your preferred editor. The editor is chosen based on the following priority:
105
+ 1. The `$EDITOR` environment variable.
106
+ 2. `vim` (if installed).
107
+ 3. `nano` (as a fallback).
108
+
109
+ The configuration file looks like this:
110
+ ```json
111
+ {
112
+ "provider": "gemini",
113
+ "proxy": "http://user:pass@127.0.0.1:1080",
114
+ "gemini_config": {
115
+ "api_key": "YOUR_GEMINI_KEY",
116
+ "model_name": "gemini-2.5-flash",
117
+ "system_instruction": "You are a CLI assistant for Termux...",
118
+ "generation_config": {
119
+ "temperature": 0.7,
120
+ "maxOutputTokens": 1024
121
+ }
122
+ },
123
+ "openai_config": {
124
+ "api_key": "YOUR_OPENAI_KEY",
125
+ "model_name": "gpt-4o",
126
+ "system_instruction": "You are a helpful assistant.",
127
+ "temperature": 0.7,
128
+ "max_tokens": 1024
129
+ }
130
+ }
131
+ ```
132
+
133
+ * **`provider`**: Set to `"gemini"` or `"openai"` to choose your AI provider.
134
+ * **`proxy`**: (Optional) Set an HTTP or HTTPS proxy for all requests.
135
+ * **`gemini_config`**: Settings for when `provider` is `"gemini"`.
136
+ * `model_name`: Change to `gemini-2.5-pro` or other available models.
137
+ * `system_instruction`: Give the AI a persona.
138
+ * `temperature`: Set to `1.0` for creative answers, `0.1` for precise logic.
139
+ * **`openai_config`**: Settings for when `provider` is `"openai"`.
140
+ * `model_name`: Change to `gpt-3.5-turbo`, etc.
141
+ * `system_instruction`: A different persona for ChatGPT.
142
+ * `temperature`: Controls randomness.
143
+ * `max_tokens`: The maximum number of tokens to generate.
144
+
145
+ ## ๐Ÿ›  Development
146
+ If you want to contribute or run Termai in a development environment:
147
+
148
+ 1. **Clone and set up a virtual environment:**
149
+ ```bash
150
+ git clone https://github.com/estiaksoyeb/termai
151
+ cd termai
152
+ python -m venv .venv
153
+ source .venv/bin/activate
154
+ ```
155
+
156
+ 2. **Install dependencies:**
157
+ ```bash
158
+ pip install -r requirements.txt
159
+ ```
160
+
161
+ 3. **Run in development mode:**
162
+ ```bash
163
+ pip install -e .
164
+ # Now the 'ai' command will use your local development version.
165
+ ```
166
+
167
+ ## โ“ Help & Troubleshooting
168
+ **Command List:**
169
+ ```bash
170
+ ai --help
171
+ ```
172
+
173
+ **Re-configure API Keys:**
174
+
175
+ To reset and re-enter your API keys, use the `--reinstall` flag.
176
+ ```bash
177
+ ai --reinstall
178
+ ```
179
+
180
+ **Debug Mode:**
181
+
182
+ If the AI isn't responding or you are getting errors, run:
183
+ ```bash
184
+ ai --debug "your question"
185
+ ```
186
+ This will print the raw server response and error codes.
187
+
188
+ **Debug Configuration:**
189
+ If you are having issues with your configuration, you can use the `--debug-config` flag to print the loaded configuration. API keys will be redacted for security.
190
+ ```bash
191
+ ai --debug-config
192
+ ```
193
+
194
+ ## ๐Ÿ—‘ Uninstallation
195
+ ### If installed via pip/pipx:
196
+ ```bash
197
+ pip uninstall termai
198
+ # or
199
+ pipx uninstall termai
200
+ ```
201
+
202
+ ## ๐Ÿ“„ License
203
+ This project is licensed under the MIT License.
204
+ You are free to use, modify, and distribute this software. See the LICENSE file for more details.
205
+ <p align="center">
206
+ Made with โค๏ธ for CLI enthusiasts
207
+ </p>
@@ -0,0 +1,20 @@
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ termai/__init__.py
5
+ termai/__main__.py
6
+ termai/api.py
7
+ termai/cli.py
8
+ termai/config.py
9
+ termai/constants.py
10
+ termai/ui.py
11
+ termai/providers/__init__.py
12
+ termai/providers/base.py
13
+ termai/providers/gemini.py
14
+ termai/providers/openai.py
15
+ termux_ai.egg-info/PKG-INFO
16
+ termux_ai.egg-info/SOURCES.txt
17
+ termux_ai.egg-info/dependency_links.txt
18
+ termux_ai.egg-info/entry_points.txt
19
+ termux_ai.egg-info/requires.txt
20
+ termux_ai.egg-info/top_level.txt
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ ai = termai.cli:main
@@ -0,0 +1 @@
1
+ requests
@@ -0,0 +1 @@
1
+ termai