onecmd 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.
- onecmd-0.2.0/LICENSE +22 -0
- onecmd-0.2.0/PKG-INFO +251 -0
- onecmd-0.2.0/README.md +212 -0
- onecmd-0.2.0/onecmd/__init__.py +0 -0
- onecmd-0.2.0/onecmd/auth/__init__.py +0 -0
- onecmd-0.2.0/onecmd/auth/owner.py +45 -0
- onecmd-0.2.0/onecmd/auth/totp.py +176 -0
- onecmd-0.2.0/onecmd/bot/__init__.py +0 -0
- onecmd-0.2.0/onecmd/bot/api.py +141 -0
- onecmd-0.2.0/onecmd/bot/handler.py +427 -0
- onecmd-0.2.0/onecmd/bot/poller.py +105 -0
- onecmd-0.2.0/onecmd/config.py +153 -0
- onecmd-0.2.0/onecmd/emoji.py +128 -0
- onecmd-0.2.0/onecmd/main.py +112 -0
- onecmd-0.2.0/onecmd/manager/__init__.py +0 -0
- onecmd-0.2.0/onecmd/manager/agent.py +525 -0
- onecmd-0.2.0/onecmd/manager/default_sop.md +109 -0
- onecmd-0.2.0/onecmd/manager/llm.py +494 -0
- onecmd-0.2.0/onecmd/manager/memory.py +99 -0
- onecmd-0.2.0/onecmd/manager/queue.py +209 -0
- onecmd-0.2.0/onecmd/manager/router.py +101 -0
- onecmd-0.2.0/onecmd/manager/sop.py +92 -0
- onecmd-0.2.0/onecmd/manager/tasks.py +300 -0
- onecmd-0.2.0/onecmd/manager/tools.py +495 -0
- onecmd-0.2.0/onecmd/store.py +121 -0
- onecmd-0.2.0/onecmd/terminal/__init__.py +0 -0
- onecmd-0.2.0/onecmd/terminal/backend.py +148 -0
- onecmd-0.2.0/onecmd/terminal/display.py +169 -0
- onecmd-0.2.0/onecmd/terminal/macos.py +636 -0
- onecmd-0.2.0/onecmd/terminal/scope.py +98 -0
- onecmd-0.2.0/onecmd/terminal/tmux.py +209 -0
- onecmd-0.2.0/onecmd.egg-info/PKG-INFO +251 -0
- onecmd-0.2.0/onecmd.egg-info/SOURCES.txt +44 -0
- onecmd-0.2.0/onecmd.egg-info/dependency_links.txt +1 -0
- onecmd-0.2.0/onecmd.egg-info/entry_points.txt +2 -0
- onecmd-0.2.0/onecmd.egg-info/requires.txt +13 -0
- onecmd-0.2.0/onecmd.egg-info/top_level.txt +1 -0
- onecmd-0.2.0/pyproject.toml +56 -0
- onecmd-0.2.0/setup.cfg +4 -0
- onecmd-0.2.0/tests/test_backend.py +260 -0
- onecmd-0.2.0/tests/test_config.py +277 -0
- onecmd-0.2.0/tests/test_emoji.py +362 -0
- onecmd-0.2.0/tests/test_scope.py +284 -0
- onecmd-0.2.0/tests/test_store.py +214 -0
- onecmd-0.2.0/tests/test_tmux.py +444 -0
- onecmd-0.2.0/tests/test_totp.py +358 -0
onecmd-0.2.0/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 antirez (original tgterm)
|
|
4
|
+
Copyright (c) 2026 Erik
|
|
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.
|
onecmd-0.2.0/PKG-INFO
ADDED
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: onecmd
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: AI-powered terminal manager — control and automate your machines from Telegram
|
|
5
|
+
Author: Erik
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/warlockee/1cmd-ai
|
|
8
|
+
Project-URL: Repository, https://github.com/warlockee/1cmd-ai
|
|
9
|
+
Project-URL: Issues, https://github.com/warlockee/1cmd-ai/issues
|
|
10
|
+
Keywords: telegram,terminal,ai,automation,remote
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Environment :: Console
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Intended Audience :: System Administrators
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Operating System :: MacOS
|
|
17
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
22
|
+
Classifier: Topic :: System :: Systems Administration
|
|
23
|
+
Classifier: Topic :: Utilities
|
|
24
|
+
Requires-Python: >=3.11
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
License-File: LICENSE
|
|
27
|
+
Requires-Dist: python-telegram-bot>=21.0
|
|
28
|
+
Requires-Dist: google-genai>=1.0.0
|
|
29
|
+
Requires-Dist: anthropic>=0.39.0
|
|
30
|
+
Requires-Dist: pydantic>=2.0
|
|
31
|
+
Requires-Dist: qrcode>=7.0
|
|
32
|
+
Provides-Extra: macos
|
|
33
|
+
Requires-Dist: pyobjc-framework-Quartz; extra == "macos"
|
|
34
|
+
Requires-Dist: pyobjc-framework-ApplicationServices; extra == "macos"
|
|
35
|
+
Provides-Extra: dev
|
|
36
|
+
Requires-Dist: pytest; extra == "dev"
|
|
37
|
+
Requires-Dist: pytest-cov; extra == "dev"
|
|
38
|
+
Dynamic: license-file
|
|
39
|
+
|
|
40
|
+
# OneCmd
|
|
41
|
+
|
|
42
|
+
An AI-powered terminal manager — control and automate your machines from Telegram.
|
|
43
|
+
|
|
44
|
+
Works on **macOS** and **Linux**.
|
|
45
|
+
|
|
46
|
+
> **One bot per machine.** Each machine needs its own Telegram bot token. Create a separate bot for each machine you want to control (e.g. `@my_macbook_bot`, `@my_server_bot`). Only one onecmd instance can use a given bot token at a time.
|
|
47
|
+
|
|
48
|
+
## Quick Start
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
curl -fsSL https://raw.githubusercontent.com/warlockee/1cmd-ai/main/setup.sh | bash
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
The setup script handles everything: clones the repo, installs Python dependencies, configures your Telegram bot and AI provider, and starts onecmd.
|
|
55
|
+
|
|
56
|
+
Or install manually:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
git clone https://github.com/warlockee/1cmd-ai.git
|
|
60
|
+
cd 1cmd-ai
|
|
61
|
+
python3 -m venv .venv
|
|
62
|
+
.venv/bin/pip install ".[macos]" # macOS (or just "." for Linux)
|
|
63
|
+
.venv/bin/onecmd --apikey YOUR_BOT_TOKEN
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## AI Manager
|
|
67
|
+
|
|
68
|
+
The AI manager is what makes OneCmd powerful. It's an LLM-powered agent that monitors, controls, and automates your terminals — so you can manage servers, run deployments, and debug issues all from a Telegram chat.
|
|
69
|
+
|
|
70
|
+
Send `.mgr` to enter manager mode. Your messages go to the AI agent, which can see and interact with all your terminals. Dot commands (`.list`, `.1`, etc.) still work normally. Send `.exit` to leave manager mode.
|
|
71
|
+
|
|
72
|
+
### What it can do
|
|
73
|
+
|
|
74
|
+
- List, read, and send commands to any terminal
|
|
75
|
+
- Name terminals for easy identification (proactively suggests names based on content)
|
|
76
|
+
- Execute commands asynchronously and notify you when they finish
|
|
77
|
+
- Queue commands to the same terminal so they don't overlap
|
|
78
|
+
- Auto-detect pending commands at prompts and submit them
|
|
79
|
+
- Follow up on completed commands (results feed back to the LLM)
|
|
80
|
+
- Run repeating background tasks ("watch this terminal until X happens")
|
|
81
|
+
- Detect and recover stuck terminals (Smart Diff — probe, compare before/after)
|
|
82
|
+
- Summarize long conversations to preserve context within token limits
|
|
83
|
+
- Auto-fallback between Gemini and Claude on rate limits
|
|
84
|
+
- Remember things across restarts (persistent memory)
|
|
85
|
+
|
|
86
|
+
### Providers
|
|
87
|
+
|
|
88
|
+
The manager supports **Gemini** (Google) and **Claude** (Anthropic). The provider is selected automatically based on which API key is set. If both are set, Gemini is preferred. Override the model with `ONECMD_MGR_MODEL`.
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
# Using Gemini (recommended — fast and free tier available)
|
|
92
|
+
GOOGLE_API_KEY=... onecmd --apikey YOUR_BOT_TOKEN
|
|
93
|
+
|
|
94
|
+
# Using Claude
|
|
95
|
+
ANTHROPIC_API_KEY=sk-... onecmd --apikey YOUR_BOT_TOKEN
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Standard Operating Procedure
|
|
99
|
+
|
|
100
|
+
On first run, the manager copies the default SOP to `.onecmd/agent_sop.md`. This file guides the AI on decision-making and stuck terminal recovery.
|
|
101
|
+
|
|
102
|
+
To add your own rules, create `.onecmd/custom_rules.md`:
|
|
103
|
+
|
|
104
|
+
```markdown
|
|
105
|
+
- Always run tests before deploying
|
|
106
|
+
- Never restart the database without asking me first
|
|
107
|
+
- Prefer yarn over npm
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Custom rules are appended to the default SOP automatically — no need to edit the base file.
|
|
111
|
+
|
|
112
|
+
### Manager commands
|
|
113
|
+
|
|
114
|
+
| Command | Action |
|
|
115
|
+
|---------|--------|
|
|
116
|
+
| `.mgr` | Enter AI manager mode |
|
|
117
|
+
| `.exit` | Leave manager mode |
|
|
118
|
+
| `.health` | Manager health report (uptime, memory, stats) |
|
|
119
|
+
|
|
120
|
+
## Manual Mode
|
|
121
|
+
|
|
122
|
+
Manual mode is always available as a stable, reliable fallback. It works without any AI provider — just you and your terminals over Telegram. No API keys, no token limits, no network dependencies beyond Telegram itself. When the AI is down or you need direct control, manual mode is always there.
|
|
123
|
+
|
|
124
|
+
In manual mode, any text you send is typed directly into the connected terminal as keystrokes.
|
|
125
|
+
|
|
126
|
+
| Command | Action |
|
|
127
|
+
|---------|--------|
|
|
128
|
+
| `.list` | List available terminal sessions |
|
|
129
|
+
| `.1` `.2` ... | Connect to a session by number |
|
|
130
|
+
| `.rename <N> <name>` | Name a terminal for easy identification |
|
|
131
|
+
| `.help` | Show all commands |
|
|
132
|
+
| Any other text | Sent as keystrokes to the connected terminal |
|
|
133
|
+
|
|
134
|
+
### Keystroke Modifiers
|
|
135
|
+
|
|
136
|
+
Prefix your message with an emoji to add a modifier key:
|
|
137
|
+
|
|
138
|
+
| Emoji | Modifier | Example |
|
|
139
|
+
|-------|----------|---------|
|
|
140
|
+
| `❤️` | Ctrl | `❤️c` = Ctrl+C |
|
|
141
|
+
| `💙` | Alt | `💙x` = Alt+X |
|
|
142
|
+
| `💚` | Cmd | macOS only |
|
|
143
|
+
| `💛` | ESC | `💛` = send Escape |
|
|
144
|
+
| `🧡` | Enter | `🧡` = send Enter |
|
|
145
|
+
| `💜` | Suppress auto-newline | `ls -la💜` = no Enter appended |
|
|
146
|
+
|
|
147
|
+
### Escape Sequences
|
|
148
|
+
|
|
149
|
+
`\n` for Enter, `\t` for Tab, `\\` for literal backslash.
|
|
150
|
+
|
|
151
|
+
## How It Works
|
|
152
|
+
|
|
153
|
+
On **macOS**, onecmd reads terminal window text via the Accessibility API (`AXUIElement`), injects keystrokes via `CGEvent`, and focuses windows using `AXUIElement`. It works with any terminal app — no Screen Recording permission needed.
|
|
154
|
+
|
|
155
|
+
On **Linux**, onecmd uses tmux: `tmux list-panes` to discover sessions, `tmux capture-pane` to read content, and `tmux send-keys` to inject keystrokes. All sessions you want to control must run inside tmux.
|
|
156
|
+
|
|
157
|
+
In both cases, terminal output is sent as monospace text to Telegram with a refresh button to update on demand.
|
|
158
|
+
|
|
159
|
+
### Linux: tmux requirement
|
|
160
|
+
|
|
161
|
+
On Linux, onecmd controls tmux sessions. Make sure your work is running inside tmux:
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
# Start a named session
|
|
165
|
+
tmux new -s dev
|
|
166
|
+
|
|
167
|
+
# Or start detached sessions
|
|
168
|
+
tmux new -s server1 -d
|
|
169
|
+
tmux new -s server2 -d
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Then run onecmd separately (outside tmux or in its own tmux window) and use `.list` to see your sessions.
|
|
173
|
+
|
|
174
|
+
## Configuration
|
|
175
|
+
|
|
176
|
+
### Options
|
|
177
|
+
|
|
178
|
+
| Flag | Description |
|
|
179
|
+
|------|-------------|
|
|
180
|
+
| `--apikey <token>` | Telegram bot API token |
|
|
181
|
+
| `--enable-otp` | Enable TOTP authentication (off by default) |
|
|
182
|
+
| `--use-weak-security` | Disable TOTP even if previously configured |
|
|
183
|
+
| `--dbfile <path>` | Custom database path (default: `./mybot.sqlite`) |
|
|
184
|
+
| `--dangerously-attach-to-any-window` | Show all windows, not just terminals (macOS only) |
|
|
185
|
+
| `--verbose` | Enable debug logging |
|
|
186
|
+
|
|
187
|
+
### Environment Variables
|
|
188
|
+
|
|
189
|
+
| Variable | Default | Description |
|
|
190
|
+
|----------|---------|-------------|
|
|
191
|
+
| `GOOGLE_API_KEY` | (none) | Google API key for the AI manager (Gemini) |
|
|
192
|
+
| `ANTHROPIC_API_KEY` | (none) | Anthropic API key for the AI manager (Claude) |
|
|
193
|
+
| `ONECMD_MGR_MODEL` | (auto) | LLM model override |
|
|
194
|
+
| `ONECMD_VISIBLE_LINES` | `40` | Number of terminal lines to include in output |
|
|
195
|
+
| `ONECMD_SPLIT_MESSAGES` | off | Set to `1` to split long output across multiple messages |
|
|
196
|
+
|
|
197
|
+
Terminal output is sent as a single message by default. Each new command or refresh **deletes the previous output messages** and sends fresh ones, creating a clean "live terminal" view rather than spamming the chat.
|
|
198
|
+
|
|
199
|
+
If your terminal produces very long output (e.g. build logs) and you want to see all of it, enable splitting:
|
|
200
|
+
|
|
201
|
+
```bash
|
|
202
|
+
ONECMD_SPLIT_MESSAGES=1 onecmd --apikey YOUR_BOT_TOKEN
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### Prerequisites
|
|
206
|
+
|
|
207
|
+
- **Python 3.11+**
|
|
208
|
+
- **macOS:** Accessibility permission (prompted on first use)
|
|
209
|
+
- **Linux:** `tmux`
|
|
210
|
+
|
|
211
|
+
### Manual Run
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
# Create venv and install
|
|
215
|
+
python3 -m venv .venv
|
|
216
|
+
.venv/bin/pip install ".[macos]" # macOS
|
|
217
|
+
.venv/bin/pip install . # Linux
|
|
218
|
+
|
|
219
|
+
# Run with AI manager
|
|
220
|
+
GOOGLE_API_KEY=... .venv/bin/onecmd --apikey YOUR_BOT_TOKEN
|
|
221
|
+
|
|
222
|
+
# Run without AI manager (manual mode only)
|
|
223
|
+
.venv/bin/onecmd --apikey YOUR_BOT_TOKEN
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
## Security
|
|
227
|
+
|
|
228
|
+
- **Owner lock**: The first Telegram user to message the bot becomes the owner. All other users are ignored.
|
|
229
|
+
- **TOTP**: OTP is **off by default** for a frictionless first-time experience. Use `--enable-otp` to set up Google Authenticator — a QR code is shown on first launch. Use `--use-weak-security` to disable OTP even if previously configured.
|
|
230
|
+
- **One bot = one machine**: Don't share a bot token across machines. Each machine should have its own bot.
|
|
231
|
+
- **Reset**: Delete `mybot.sqlite` to reset ownership and TOTP.
|
|
232
|
+
|
|
233
|
+
## Permissions
|
|
234
|
+
|
|
235
|
+
**macOS:** Requires Accessibility permission. macOS will prompt on first use, or grant it in System Settings > Privacy & Security > Accessibility.
|
|
236
|
+
|
|
237
|
+
**Linux:** No special permissions needed. Just ensure the user running onecmd can access the tmux socket.
|
|
238
|
+
|
|
239
|
+
## Supported Terminals
|
|
240
|
+
|
|
241
|
+
**macOS:** Terminal.app, iTerm2, Ghostty, kitty, Alacritty, Hyper, Warp, WezTerm, Tabby.
|
|
242
|
+
|
|
243
|
+
**Linux:** Any terminal running inside tmux.
|
|
244
|
+
|
|
245
|
+
## Architecture
|
|
246
|
+
|
|
247
|
+
See [ARCHITECTURE.md](ARCHITECTURE.md) for detailed technical documentation.
|
|
248
|
+
|
|
249
|
+
## License
|
|
250
|
+
|
|
251
|
+
MIT -- see [LICENSE](LICENSE).
|
onecmd-0.2.0/README.md
ADDED
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
# OneCmd
|
|
2
|
+
|
|
3
|
+
An AI-powered terminal manager — control and automate your machines from Telegram.
|
|
4
|
+
|
|
5
|
+
Works on **macOS** and **Linux**.
|
|
6
|
+
|
|
7
|
+
> **One bot per machine.** Each machine needs its own Telegram bot token. Create a separate bot for each machine you want to control (e.g. `@my_macbook_bot`, `@my_server_bot`). Only one onecmd instance can use a given bot token at a time.
|
|
8
|
+
|
|
9
|
+
## Quick Start
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
curl -fsSL https://raw.githubusercontent.com/warlockee/1cmd-ai/main/setup.sh | bash
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
The setup script handles everything: clones the repo, installs Python dependencies, configures your Telegram bot and AI provider, and starts onecmd.
|
|
16
|
+
|
|
17
|
+
Or install manually:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
git clone https://github.com/warlockee/1cmd-ai.git
|
|
21
|
+
cd 1cmd-ai
|
|
22
|
+
python3 -m venv .venv
|
|
23
|
+
.venv/bin/pip install ".[macos]" # macOS (or just "." for Linux)
|
|
24
|
+
.venv/bin/onecmd --apikey YOUR_BOT_TOKEN
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## AI Manager
|
|
28
|
+
|
|
29
|
+
The AI manager is what makes OneCmd powerful. It's an LLM-powered agent that monitors, controls, and automates your terminals — so you can manage servers, run deployments, and debug issues all from a Telegram chat.
|
|
30
|
+
|
|
31
|
+
Send `.mgr` to enter manager mode. Your messages go to the AI agent, which can see and interact with all your terminals. Dot commands (`.list`, `.1`, etc.) still work normally. Send `.exit` to leave manager mode.
|
|
32
|
+
|
|
33
|
+
### What it can do
|
|
34
|
+
|
|
35
|
+
- List, read, and send commands to any terminal
|
|
36
|
+
- Name terminals for easy identification (proactively suggests names based on content)
|
|
37
|
+
- Execute commands asynchronously and notify you when they finish
|
|
38
|
+
- Queue commands to the same terminal so they don't overlap
|
|
39
|
+
- Auto-detect pending commands at prompts and submit them
|
|
40
|
+
- Follow up on completed commands (results feed back to the LLM)
|
|
41
|
+
- Run repeating background tasks ("watch this terminal until X happens")
|
|
42
|
+
- Detect and recover stuck terminals (Smart Diff — probe, compare before/after)
|
|
43
|
+
- Summarize long conversations to preserve context within token limits
|
|
44
|
+
- Auto-fallback between Gemini and Claude on rate limits
|
|
45
|
+
- Remember things across restarts (persistent memory)
|
|
46
|
+
|
|
47
|
+
### Providers
|
|
48
|
+
|
|
49
|
+
The manager supports **Gemini** (Google) and **Claude** (Anthropic). The provider is selected automatically based on which API key is set. If both are set, Gemini is preferred. Override the model with `ONECMD_MGR_MODEL`.
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
# Using Gemini (recommended — fast and free tier available)
|
|
53
|
+
GOOGLE_API_KEY=... onecmd --apikey YOUR_BOT_TOKEN
|
|
54
|
+
|
|
55
|
+
# Using Claude
|
|
56
|
+
ANTHROPIC_API_KEY=sk-... onecmd --apikey YOUR_BOT_TOKEN
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Standard Operating Procedure
|
|
60
|
+
|
|
61
|
+
On first run, the manager copies the default SOP to `.onecmd/agent_sop.md`. This file guides the AI on decision-making and stuck terminal recovery.
|
|
62
|
+
|
|
63
|
+
To add your own rules, create `.onecmd/custom_rules.md`:
|
|
64
|
+
|
|
65
|
+
```markdown
|
|
66
|
+
- Always run tests before deploying
|
|
67
|
+
- Never restart the database without asking me first
|
|
68
|
+
- Prefer yarn over npm
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Custom rules are appended to the default SOP automatically — no need to edit the base file.
|
|
72
|
+
|
|
73
|
+
### Manager commands
|
|
74
|
+
|
|
75
|
+
| Command | Action |
|
|
76
|
+
|---------|--------|
|
|
77
|
+
| `.mgr` | Enter AI manager mode |
|
|
78
|
+
| `.exit` | Leave manager mode |
|
|
79
|
+
| `.health` | Manager health report (uptime, memory, stats) |
|
|
80
|
+
|
|
81
|
+
## Manual Mode
|
|
82
|
+
|
|
83
|
+
Manual mode is always available as a stable, reliable fallback. It works without any AI provider — just you and your terminals over Telegram. No API keys, no token limits, no network dependencies beyond Telegram itself. When the AI is down or you need direct control, manual mode is always there.
|
|
84
|
+
|
|
85
|
+
In manual mode, any text you send is typed directly into the connected terminal as keystrokes.
|
|
86
|
+
|
|
87
|
+
| Command | Action |
|
|
88
|
+
|---------|--------|
|
|
89
|
+
| `.list` | List available terminal sessions |
|
|
90
|
+
| `.1` `.2` ... | Connect to a session by number |
|
|
91
|
+
| `.rename <N> <name>` | Name a terminal for easy identification |
|
|
92
|
+
| `.help` | Show all commands |
|
|
93
|
+
| Any other text | Sent as keystrokes to the connected terminal |
|
|
94
|
+
|
|
95
|
+
### Keystroke Modifiers
|
|
96
|
+
|
|
97
|
+
Prefix your message with an emoji to add a modifier key:
|
|
98
|
+
|
|
99
|
+
| Emoji | Modifier | Example |
|
|
100
|
+
|-------|----------|---------|
|
|
101
|
+
| `❤️` | Ctrl | `❤️c` = Ctrl+C |
|
|
102
|
+
| `💙` | Alt | `💙x` = Alt+X |
|
|
103
|
+
| `💚` | Cmd | macOS only |
|
|
104
|
+
| `💛` | ESC | `💛` = send Escape |
|
|
105
|
+
| `🧡` | Enter | `🧡` = send Enter |
|
|
106
|
+
| `💜` | Suppress auto-newline | `ls -la💜` = no Enter appended |
|
|
107
|
+
|
|
108
|
+
### Escape Sequences
|
|
109
|
+
|
|
110
|
+
`\n` for Enter, `\t` for Tab, `\\` for literal backslash.
|
|
111
|
+
|
|
112
|
+
## How It Works
|
|
113
|
+
|
|
114
|
+
On **macOS**, onecmd reads terminal window text via the Accessibility API (`AXUIElement`), injects keystrokes via `CGEvent`, and focuses windows using `AXUIElement`. It works with any terminal app — no Screen Recording permission needed.
|
|
115
|
+
|
|
116
|
+
On **Linux**, onecmd uses tmux: `tmux list-panes` to discover sessions, `tmux capture-pane` to read content, and `tmux send-keys` to inject keystrokes. All sessions you want to control must run inside tmux.
|
|
117
|
+
|
|
118
|
+
In both cases, terminal output is sent as monospace text to Telegram with a refresh button to update on demand.
|
|
119
|
+
|
|
120
|
+
### Linux: tmux requirement
|
|
121
|
+
|
|
122
|
+
On Linux, onecmd controls tmux sessions. Make sure your work is running inside tmux:
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
# Start a named session
|
|
126
|
+
tmux new -s dev
|
|
127
|
+
|
|
128
|
+
# Or start detached sessions
|
|
129
|
+
tmux new -s server1 -d
|
|
130
|
+
tmux new -s server2 -d
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Then run onecmd separately (outside tmux or in its own tmux window) and use `.list` to see your sessions.
|
|
134
|
+
|
|
135
|
+
## Configuration
|
|
136
|
+
|
|
137
|
+
### Options
|
|
138
|
+
|
|
139
|
+
| Flag | Description |
|
|
140
|
+
|------|-------------|
|
|
141
|
+
| `--apikey <token>` | Telegram bot API token |
|
|
142
|
+
| `--enable-otp` | Enable TOTP authentication (off by default) |
|
|
143
|
+
| `--use-weak-security` | Disable TOTP even if previously configured |
|
|
144
|
+
| `--dbfile <path>` | Custom database path (default: `./mybot.sqlite`) |
|
|
145
|
+
| `--dangerously-attach-to-any-window` | Show all windows, not just terminals (macOS only) |
|
|
146
|
+
| `--verbose` | Enable debug logging |
|
|
147
|
+
|
|
148
|
+
### Environment Variables
|
|
149
|
+
|
|
150
|
+
| Variable | Default | Description |
|
|
151
|
+
|----------|---------|-------------|
|
|
152
|
+
| `GOOGLE_API_KEY` | (none) | Google API key for the AI manager (Gemini) |
|
|
153
|
+
| `ANTHROPIC_API_KEY` | (none) | Anthropic API key for the AI manager (Claude) |
|
|
154
|
+
| `ONECMD_MGR_MODEL` | (auto) | LLM model override |
|
|
155
|
+
| `ONECMD_VISIBLE_LINES` | `40` | Number of terminal lines to include in output |
|
|
156
|
+
| `ONECMD_SPLIT_MESSAGES` | off | Set to `1` to split long output across multiple messages |
|
|
157
|
+
|
|
158
|
+
Terminal output is sent as a single message by default. Each new command or refresh **deletes the previous output messages** and sends fresh ones, creating a clean "live terminal" view rather than spamming the chat.
|
|
159
|
+
|
|
160
|
+
If your terminal produces very long output (e.g. build logs) and you want to see all of it, enable splitting:
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
ONECMD_SPLIT_MESSAGES=1 onecmd --apikey YOUR_BOT_TOKEN
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Prerequisites
|
|
167
|
+
|
|
168
|
+
- **Python 3.11+**
|
|
169
|
+
- **macOS:** Accessibility permission (prompted on first use)
|
|
170
|
+
- **Linux:** `tmux`
|
|
171
|
+
|
|
172
|
+
### Manual Run
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
# Create venv and install
|
|
176
|
+
python3 -m venv .venv
|
|
177
|
+
.venv/bin/pip install ".[macos]" # macOS
|
|
178
|
+
.venv/bin/pip install . # Linux
|
|
179
|
+
|
|
180
|
+
# Run with AI manager
|
|
181
|
+
GOOGLE_API_KEY=... .venv/bin/onecmd --apikey YOUR_BOT_TOKEN
|
|
182
|
+
|
|
183
|
+
# Run without AI manager (manual mode only)
|
|
184
|
+
.venv/bin/onecmd --apikey YOUR_BOT_TOKEN
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
## Security
|
|
188
|
+
|
|
189
|
+
- **Owner lock**: The first Telegram user to message the bot becomes the owner. All other users are ignored.
|
|
190
|
+
- **TOTP**: OTP is **off by default** for a frictionless first-time experience. Use `--enable-otp` to set up Google Authenticator — a QR code is shown on first launch. Use `--use-weak-security` to disable OTP even if previously configured.
|
|
191
|
+
- **One bot = one machine**: Don't share a bot token across machines. Each machine should have its own bot.
|
|
192
|
+
- **Reset**: Delete `mybot.sqlite` to reset ownership and TOTP.
|
|
193
|
+
|
|
194
|
+
## Permissions
|
|
195
|
+
|
|
196
|
+
**macOS:** Requires Accessibility permission. macOS will prompt on first use, or grant it in System Settings > Privacy & Security > Accessibility.
|
|
197
|
+
|
|
198
|
+
**Linux:** No special permissions needed. Just ensure the user running onecmd can access the tmux socket.
|
|
199
|
+
|
|
200
|
+
## Supported Terminals
|
|
201
|
+
|
|
202
|
+
**macOS:** Terminal.app, iTerm2, Ghostty, kitty, Alacritty, Hyper, Warp, WezTerm, Tabby.
|
|
203
|
+
|
|
204
|
+
**Linux:** Any terminal running inside tmux.
|
|
205
|
+
|
|
206
|
+
## Architecture
|
|
207
|
+
|
|
208
|
+
See [ARCHITECTURE.md](ARCHITECTURE.md) for detailed technical documentation.
|
|
209
|
+
|
|
210
|
+
## License
|
|
211
|
+
|
|
212
|
+
MIT -- see [LICENSE](LICENSE).
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"""Owner registration and verification.
|
|
2
|
+
|
|
3
|
+
Calling spec:
|
|
4
|
+
Inputs: Store instance, user_id (int)
|
|
5
|
+
Outputs: tuple[bool, bool] — (is_owner, just_registered)
|
|
6
|
+
Side effects: writes "owner_id" to store on first-ever call
|
|
7
|
+
|
|
8
|
+
Logic:
|
|
9
|
+
1. Read "owner_id" from store (O(1) SQLite lookup).
|
|
10
|
+
2. If no owner registered, register this user as owner.
|
|
11
|
+
Return (True, True).
|
|
12
|
+
3. If owner exists and matches user_id, return (True, False).
|
|
13
|
+
4. If owner exists and does NOT match, return (False, False).
|
|
14
|
+
|
|
15
|
+
Guarding:
|
|
16
|
+
- First user to message becomes owner (stored via store.set)
|
|
17
|
+
- No mechanism to change owner at runtime
|
|
18
|
+
- Owner check is O(1) lookup, not bypassable
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
from __future__ import annotations
|
|
22
|
+
|
|
23
|
+
from onecmd.store import Store
|
|
24
|
+
|
|
25
|
+
OWNER_KEY = "owner_id"
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def check_owner(store: Store, user_id: int) -> tuple[bool, bool]:
|
|
29
|
+
"""Check whether *user_id* is the bot owner.
|
|
30
|
+
|
|
31
|
+
Returns ``(is_owner, just_registered)``.
|
|
32
|
+
|
|
33
|
+
On the very first call (no owner in the store), the caller is
|
|
34
|
+
registered as owner and ``(True, True)`` is returned. All
|
|
35
|
+
subsequent calls compare against the stored owner ID.
|
|
36
|
+
"""
|
|
37
|
+
stored = store.get(OWNER_KEY)
|
|
38
|
+
|
|
39
|
+
# First user becomes owner.
|
|
40
|
+
if stored is None:
|
|
41
|
+
store.set(OWNER_KEY, str(user_id))
|
|
42
|
+
return True, True
|
|
43
|
+
|
|
44
|
+
is_owner = stored == str(user_id)
|
|
45
|
+
return is_owner, False
|