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.
- termux_ai-0.2.0/LICENSE +22 -0
- termux_ai-0.2.0/PKG-INFO +207 -0
- termux_ai-0.2.0/README.md +168 -0
- termux_ai-0.2.0/pyproject.toml +28 -0
- termux_ai-0.2.0/setup.cfg +4 -0
- termux_ai-0.2.0/termai/__init__.py +1 -0
- termux_ai-0.2.0/termai/__main__.py +4 -0
- termux_ai-0.2.0/termai/api.py +24 -0
- termux_ai-0.2.0/termai/cli.py +65 -0
- termux_ai-0.2.0/termai/config.py +151 -0
- termux_ai-0.2.0/termai/constants.py +15 -0
- termux_ai-0.2.0/termai/providers/__init__.py +0 -0
- termux_ai-0.2.0/termai/providers/base.py +7 -0
- termux_ai-0.2.0/termai/providers/gemini.py +50 -0
- termux_ai-0.2.0/termai/providers/openai.py +57 -0
- termux_ai-0.2.0/termai/ui.py +23 -0
- termux_ai-0.2.0/termux_ai.egg-info/PKG-INFO +207 -0
- termux_ai-0.2.0/termux_ai.egg-info/SOURCES.txt +20 -0
- termux_ai-0.2.0/termux_ai.egg-info/dependency_links.txt +1 -0
- termux_ai-0.2.0/termux_ai.egg-info/entry_points.txt +2 -0
- termux_ai-0.2.0/termux_ai.egg-info/requires.txt +1 -0
- termux_ai-0.2.0/termux_ai.egg-info/top_level.txt +1 -0
termux_ai-0.2.0/LICENSE
ADDED
|
@@ -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.
|
termux_ai-0.2.0/PKG-INFO
ADDED
|
@@ -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 @@
|
|
|
1
|
+
# Termai package initialization
|
|
@@ -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,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 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
requests
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
termai
|