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.
Files changed (46) hide show
  1. onecmd-0.2.0/LICENSE +22 -0
  2. onecmd-0.2.0/PKG-INFO +251 -0
  3. onecmd-0.2.0/README.md +212 -0
  4. onecmd-0.2.0/onecmd/__init__.py +0 -0
  5. onecmd-0.2.0/onecmd/auth/__init__.py +0 -0
  6. onecmd-0.2.0/onecmd/auth/owner.py +45 -0
  7. onecmd-0.2.0/onecmd/auth/totp.py +176 -0
  8. onecmd-0.2.0/onecmd/bot/__init__.py +0 -0
  9. onecmd-0.2.0/onecmd/bot/api.py +141 -0
  10. onecmd-0.2.0/onecmd/bot/handler.py +427 -0
  11. onecmd-0.2.0/onecmd/bot/poller.py +105 -0
  12. onecmd-0.2.0/onecmd/config.py +153 -0
  13. onecmd-0.2.0/onecmd/emoji.py +128 -0
  14. onecmd-0.2.0/onecmd/main.py +112 -0
  15. onecmd-0.2.0/onecmd/manager/__init__.py +0 -0
  16. onecmd-0.2.0/onecmd/manager/agent.py +525 -0
  17. onecmd-0.2.0/onecmd/manager/default_sop.md +109 -0
  18. onecmd-0.2.0/onecmd/manager/llm.py +494 -0
  19. onecmd-0.2.0/onecmd/manager/memory.py +99 -0
  20. onecmd-0.2.0/onecmd/manager/queue.py +209 -0
  21. onecmd-0.2.0/onecmd/manager/router.py +101 -0
  22. onecmd-0.2.0/onecmd/manager/sop.py +92 -0
  23. onecmd-0.2.0/onecmd/manager/tasks.py +300 -0
  24. onecmd-0.2.0/onecmd/manager/tools.py +495 -0
  25. onecmd-0.2.0/onecmd/store.py +121 -0
  26. onecmd-0.2.0/onecmd/terminal/__init__.py +0 -0
  27. onecmd-0.2.0/onecmd/terminal/backend.py +148 -0
  28. onecmd-0.2.0/onecmd/terminal/display.py +169 -0
  29. onecmd-0.2.0/onecmd/terminal/macos.py +636 -0
  30. onecmd-0.2.0/onecmd/terminal/scope.py +98 -0
  31. onecmd-0.2.0/onecmd/terminal/tmux.py +209 -0
  32. onecmd-0.2.0/onecmd.egg-info/PKG-INFO +251 -0
  33. onecmd-0.2.0/onecmd.egg-info/SOURCES.txt +44 -0
  34. onecmd-0.2.0/onecmd.egg-info/dependency_links.txt +1 -0
  35. onecmd-0.2.0/onecmd.egg-info/entry_points.txt +2 -0
  36. onecmd-0.2.0/onecmd.egg-info/requires.txt +13 -0
  37. onecmd-0.2.0/onecmd.egg-info/top_level.txt +1 -0
  38. onecmd-0.2.0/pyproject.toml +56 -0
  39. onecmd-0.2.0/setup.cfg +4 -0
  40. onecmd-0.2.0/tests/test_backend.py +260 -0
  41. onecmd-0.2.0/tests/test_config.py +277 -0
  42. onecmd-0.2.0/tests/test_emoji.py +362 -0
  43. onecmd-0.2.0/tests/test_scope.py +284 -0
  44. onecmd-0.2.0/tests/test_store.py +214 -0
  45. onecmd-0.2.0/tests/test_tmux.py +444 -0
  46. 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