Mahmood
A terminal agent, powered by Groq, that actually operates your computer — shell, files, macOS apps, the browser, and the APIs of accounts you own. Fast, because Groq is.
pip install mahmood-agent
mahmood setup
mahmood
› my node build is failing, figure out why and fix it
› what's eating my disk? clean up the safe stuff
› find a 27" 4K monitor under $400, put the best one in my Amazon cart
› open a PR from my current branch with a proper description
› what's on my calendar tomorrow, and text Sam that I'm running late
Mahmood reads the situation, runs the commands, and reports what happened. It is not a chatbot that gives you a list of steps to run yourself.
What it can do
| Area | Tools |
|---|---|
| Shell | run commands through your login shell, background jobs (dev servers, builds), job output, working directory |
| Files | read with line numbers, write with automatic backups, exact-string edits, regex search, glob find, delete to Trash |
| macOS | AppleScript/JXA for any app (Mail, Messages, Calendar, Notes, Finder, Music), open apps and URLs, keystrokes via System Events, screenshots it can actually see, clipboard, notifications, process control, system report |
| Browser | a real visible Chrome window with a persistent profile — navigate, read the page as structured elements, click, type, select, scroll, screenshot, and hand control back to you |
| Accounts | authenticated HTTP to GitHub, NVIDIA NGC/NIM, Vercel, Stripe, Linear, Slack, Notion, Cloudflare, OpenAI — plus web search and page fetching |
Screenshots work even with a text-only model. screenshot and
browser_screenshot go to a vision model, whose description is handed back to the
agent — so it can act on what's on screen instead of guessing. If your main model
reads images itself, they're passed through directly and the extra hop is skipped.
Where it stops
This is the part worth reading before you install it.
Read-only actions just run. ls, git status, grep, reading a file,
fetching a page — no prompt, no friction.
Anything that changes something asks first, with the exact command or diff shown:
╭─ run_command — needs approval ──────────────────╮
│ $ npm install --save-dev vitest │
╰─────────────────────────────────────────────────╯
yes / no / always allow run_command this session / explain first
Answer a to trust that tool for the rest of the session, or e to make
Mahmood explain what it's about to do before you decide.
Money and one-way doors always ask — even in --yolo. Mahmood will search
for the product, compare options, add it to the cart, fill in shipping and pick
a payment method. Then it stops:
╭─ Over to you ───────────────────────────────────╮
│ Dell S2722QC, $379.99. Cart total $379.99 with │
│ free shipping to 1400 Oak St. Paying with the │
│ Visa ending 4412. One click left: "Place your │
│ order". │
│ │
│ https://www.amazon.com/gp/buy/spc/handlers/... │
╰─ Mahmood is waiting — check it before you click ╯
press Enter when you're done:
The final click is yours. browser_click refuses any element whose label
matches the final-commit list — place order, buy now, confirm and pay,
start membership, send money, delete account, and friends. That's a
deliberate limit, not a missing feature: an agent that can spend your money
unattended is one bad inference away from an expensive mistake.
Same for logins, captchas and 2FA — Mahmood hands you the browser instead of typing credentials.
Credentials
There is no password prompt anywhere in this package. By design.
- API tokens go in your OS keyring (macOS Keychain, Secret Service,
Windows Credential Locker) via
keyring. Never a plaintext file. - Host-pinned. A token is only ever sent to its own service's hosts. Your
GitHub token cannot leave
api.github.com, no matter what a web page says. - Site logins happen in a browser window you drive. Mahmood uses a
dedicated Chrome profile at
~/.config/mahmood/browser-profile, so you log in once and the session persists — and your main Chrome profile is untouched. - Environment variables (
GROQ_API_KEY,GITHUB_TOKEN, …) are read first if set, so CI and direnv setups work without the keyring.
Every account in mahmood setup is optional. Add none and you still get a
fully working agent with local control; add one and that capability switches on.
Setup
mahmood setup walks through six steps, and only the first is required:
- Groq API key — validated against the live API before it's stored. Get one at console.groq.com/keys.
- Model — picked from what your key can actually see, filtered to models that
can hold a conversation. Defaults to
qwen/qwen3.6-27b. If you choose a text-only model, you're offered a vision model for screenshots. - About you — one line of context Mahmood gets every session.
- Accounts — the optional tokens above.
- Browser control — installs Playwright and Chromium if you want it.
- Approvals — command prefixes to pre-approve, e.g.
git, npm run.
Check the result any time:
mahmood doctor # what works on this machine, what doesn't
mahmood accounts # which credentials are configured
mahmood tools # every tool, with its risk level
Which model
An agent lives or dies by tool calling, not by benchmark scores. These are results from running the same multi-step task — run the failing test, fix the source, re-run to prove it passes — through Mahmood on Groq:
| Model | Verdict |
|---|---|
qwen/qwen3.6-27b |
Default. Completed the task cleanly first time, and reads images, so screenshots need no second model. |
openai/gpt-oss-120b |
Reasons well, but intermittently emits tool arguments Groq rejects as invalid JSON — usually when writing a multi-line file. Mahmood detects this, tells it to use a heredoc instead, and it then finishes. Text-only. |
llama-3.3-70b-versatile |
Sometimes packs the arguments into the function name, which the API rejects. Mahmood repairs that shape when it can. Text-only. |
llama-3.1-8b-instant |
Fast and cheap, fine for simple one-shot jobs. Loses the thread on long tool chains. |
All of them are selectable. The loop retries transient errors with backoff, retries malformed tool calls with a nudge, and gives up with a clear suggestion rather than looping forever.
Rate limits on Groq's free tier
Worth understanding, because it's the main thing you'll notice. Groq meters tokens per minute, and the free tier is tight:
| Model | TPM |
|---|---|
llama-3.3-70b-versatile |
12,000 |
qwen/qwen3.6-27b, openai/gpt-oss-120b |
8,000 |
llama-3.1-8b-instant |
6,000 |
An agent re-sends the whole conversation and every tool definition on each step, so a ten-step task can spend 30,000 tokens a minute without any single request being large. Mahmood reads its actual allowance from Groq's response headers and works inside it:
- trims the conversation to fit before sending
- waits for the window to roll over instead of failing, telling you why:
(rate limit: need ~6,023 tokens, 3,106 left this minute — waiting 37s) - on a 413, shrinks the request rather than blindly retrying
- scales how much command output it feeds back, so one
ls -Rcan't eat a whole window
There is also a daily cap (200,000 tokens on the free tier). Unlike the per-minute one, that can't be waited out inside a session — but it is per model, so switching gives you a fresh allowance immediately, and Mahmood tells you which model to switch to when it happens.
The result is that long tasks get slow on the free tier rather than breaking. If you'd rather they were fast:
/model llama-3.3-70b-versatile— 50% more headroom--no-browser— drops 9 tool definitions, ~900 tokens off every request/clearbetween unrelated tasks — the biggest win, since history is resent every step- Upgrade to Dev Tier — removes the ceiling
/cost shows your allowance and what's left in the current window.
macOS permissions
Desktop control needs two grants in System Settings → Privacy & Security, for your terminal app:
- Screen Recording — for
screenshot - Accessibility — for
send_keys
Skip them and everything else still works.
Browser extra
pip install 'mahmood-agent[browser]'
playwright install chromium
Usage
mahmood # interactive
mahmood run "update my deps and run the tests"
echo "summarise this log" | mahmood
mahmood -m openai/gpt-oss-120b # different model for one session
mahmood --yolo # skip medium-risk prompts (money still asks)
mahmood --no-browser # local only
In the REPL:
/tools |
every tool available right now, with risk levels |
/accounts |
configured credentials |
/setup |
reconfigure without leaving the session |
/yolo |
toggle auto-approval |
/model <name> |
switch model |
/log |
recent actions, with timestamps and risk |
/cwd [path] |
show or change the working directory |
/cost |
tokens used this session |
/clear |
forget the conversation |
/exit |
quit |
Configuration
~/.config/mahmood/config.toml — plain TOML, edit it freely:
model = "qwen/qwen3.6-27b"
vision_model = "qwen/qwen3.6-27b" # describes screenshots; "" disables them
about_me = "Casper. Projects in ~/dev, mostly Next.js and Python. Be terse."
auto_approve = ["git", "npm run", "pytest"]
protected_paths = ["~/.ssh", "~/.aws", "~/.gnupg", "~/Library/Keychains"]
browser = true
browser_channel = "chrome"
max_steps = 40
temperature = 0.2
protected_paths are refused by every file tool, full stop. auto_approve
prefixes skip the confirmation prompt — keep it to things you'd never regret.
An append-only log of every action Mahmood considered, with its risk level and
whether it ran, lands in ~/.config/mahmood/actions.log.
Prompt injection
Web pages, files, command output and search results reach the model as untrusted data. Mahmood is instructed to ignore instructions found there and report them to you instead. The host pinning on credentials is the backstop: if a page talks the model into trying to exfiltrate a token, the request is refused before it leaves your machine.
This mitigates the risk; it does not eliminate it. An agent with shell access is exactly as powerful as your shell. Read the prompts before you approve them — that's what they're for.
Risk levels
| Level | Meaning | Prompts? |
|---|---|---|
safe |
reads only | no |
low |
local, recoverable change | yes (a to trust) |
medium |
mutates state outside this machine | yes (a to trust) |
high |
destructive or hard to reverse | yes, every time |
critical |
spends money, or truly irreversible | always, even in --yolo |
Shell commands are classified by content, not just by tool: sudo, rm -rf,
git push --force, twine upload and similar are promoted to high
automatically, and a chained command is only as safe as its least safe segment —
so ls && rm -rf / is treated as rm -rf /.
Requirements
Python 3.11+. macOS for the desktop tools; shell, files, browser and HTTP work on Linux too.
License
MIT
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mahmood_agent-0.1.3.tar.gz.
File metadata
- Download URL: mahmood_agent-0.1.3.tar.gz
- Upload date:
- Size: 47.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8e72a830c9528e87ac1b95fb1faaa56db25d0b3f6c12472b396b2264c5165b26
|
|
| MD5 |
9ead0fe4ec92ddfe6855218cb36e8440
|
|
| BLAKE2b-256 |
131ec08fd56add364f2c170ff7135c0ad15322c46f645094f74dfb505b0b3fcf
|
File details
Details for the file mahmood_agent-0.1.3-py3-none-any.whl.
File metadata
- Download URL: mahmood_agent-0.1.3-py3-none-any.whl
- Upload date:
- Size: 56.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c7308106037828a596ab1a752f1cab32c2df0949a7131253ed288e2e04c5f452
|
|
| MD5 |
1c9da83f80643ee070ca9f61c8c5df6d
|
|
| BLAKE2b-256 |
70eee0e6b541a0f433f31dce10ca5c10e560a694bbadaba183b9237f0a4e0e6e
|