@gent
Email an idea. Your coding agent gets to work.
Send a task from your phone. Codex or Claude Code runs on your own computer and emails you the result. Reply to continue the same session.
No SSH, mobile terminal app, port forwarding, or public endpoint. Repositories and agent sign-ins stay on your computer; task text and results travel through Gmail and your chosen agent provider.
MIT licensed. Requirements: Gmail or Google Workspace with IMAP access, macOS/Linux, Python 3.11+, and uv. macOS is live-tested; Linux has automated coverage. Your computer must stay awake and online. Install and sign in to Codex or Claude Code first; Claude needs the --permission-prompts option (v2.1.259+). Existing subscriptions, limits, and permissions apply.
Send a task
To: you+agents@gmail.com
Subject: Codex: improve the signup form
Find the confusing parts of the signup form, improve them,
and run the relevant checks. Leave the changes ready to review.
Choose Claude Code with Claude: your task. Target a configured project with Codex/website: your task. Pick a model for one task by putting its name in square brackets before the colon:
Claude [opus]: review the auth flow
Codex/website [gpt-6.1-sol]: fix the build
Claude/mailbox [haiku]: summarise the open issues
The model applies to every reply in that thread and to a local resume. Without brackets the agent's default model from the config is used. Model names may contain letters, numbers, ., _ and -; any other subject is ignored. Agent names are case insensitive; project aliases are case sensitive.
You'll receive Queued, Started, and a result in the email thread. Reply with your next instruction to continue the exact session. Reply status for progress or stop to cancel queued turns and stop the running process. File changes already made are retained.
Plain text and HTML-only email are accepted. Write replies above the quoted conversation. HTML is converted to text without executing active content; recognized quoted threads are removed. Attachments are saved under the task's private local state directory and their paths are included in the agent prompt. Attachments are untrusted input and are not automatically executed.
Default limits: 20 MiB per raw message, 5 MiB per attachment, 10 MiB combined attachments, 10 attachments, and 32,000 characters of task text. Oversized or unsupported nested attachments cause the message to be ignored. Byte/count limits can be lowered with max_message_bytes, max_attachment_bytes, max_attachments_bytes, and max_attachments.
Install
With uv installed:
uv tool install atgent
atgent init
The old agent-mailbox command still works and runs the same program.
init asks for your Gmail address, how the runner signs in (app password from the Keychain, a command or an environment variable, or your own OAuth client), your project folders, and which installed agents to use with their default models. It writes ~/.config/agent-mailbox/config.json without any secret and offers to run doctor. For a script, atgent init --email you@gmail.com --project /absolute/path/to/project writes a minimal config without questions.
Change an agent's default model later with atgent model claude opus, or atgent model codex default to return to Codex's own default.
Choose an app password or your own Gmail OAuth desktop client. An app password is simpler when your account permits it. Follow Google's app-password setup. Managed accounts and some security settings block app passwords; OAuth can still require administrator consent. See Gmail OAuth setup for the alternative.
Keep the password in your password manager or OS keychain. In ~/.config/agent-mailbox/config.json, set password_command to an argument array. For example, after storing the password in a macOS Keychain item named atgent:
"password_command": ["security", "find-generic-password", "-s", "atgent", "-w"]
Alternatively set AGENT_MAILBOX_PASSWORD in your environment. The generated config references that variable, never the password. A password command takes priority. Don't put literal passwords in command arguments or commit local configuration.
atgent doctor
atgent run
doctor authenticates IMAP and SMTP without sending mail and checks CLI installation. It doesn't prove remaining agent capacity. On the first successful poll, the runner skips historical Sent mail and arms new-message intake. Send your task after this happens.
To run detached without opening a window:
atgent start
atgent status
atgent shutdown
This is an ordinary process, with no automatic login/reboot persistence. Logs and private state are under state/ beside your config. start reports process creation; inspect the log and use doctor to verify access.
Automatic startup (optional)
atgent shutdown
atgent install-service
atgent service-status
atgent uninstall-service
Installation registers a user LaunchAgent on macOS or a systemd user unit on Linux. It starts at user login and restarts after failure. Linux startup before login requires user lingering configured separately. macOS does not run the job before login. Keep the Python installation, config path, CLI executables, and credential resolver available at the same paths. Service and manual runners share one lock. Shut down an ordinary runner before installing. shutdown stops the current runner; uninstall-service also removes automatic startup. Neither undoes task changes. The computer must remain awake and connected.
Projects and permissions
Only configured project aliases can be selected. Edit your local config:
"projects": {
"main": "/absolute/path/to/project",
"website": {
"path": "/absolute/path/to/another/project",
"sandbox": "read-only",
"agents": {
"codex": {"approval_policy": "on-request", "approvals": "email"}
}
}
},
"default_project": "main"
Set max_workers to run tasks concurrently (default 1, maximum 32). By default each project directory runs one task at a time, including aliases that resolve to the same directory. Set "concurrent": true on a project ("lab": {"path": "/absolute/path", "concurrent": true}) to let separate tasks run side by side in it, for example a folder that holds many repositories. Turns in the same thread or session always run one at a time. The runner does not coordinate other local editors or separately launched agents, and concurrent tasks in one directory can edit the same files.
Codex settings can be global (codex_sandbox, codex_approval_policy), per agent (agents.codex.sandbox / approval_policy), per project, or per project-agent as above. Precedence is project-agent, project, agent, global, then defaults. Sandboxes are read-only, workspace-write, or danger-full-access; approval policies are never, on-request, untrusted, or on-failure, subject to installed CLI support. approvals can likewise be overridden by agent/project. Choose elevated access deliberately.
With approvals off (the default), Codex uses workspace-write and doesn't wait for approval prompts. Set codex_sandbox to read-only for a read-only baseline. Existing Codex/project instructions still apply; sandboxing isn't bypassed. Privileged or network-dependent work may be blocked by CLI policy.
With approvals off, Claude uses dontAsk by default. It permits Read/Edit/Write/Glob/Grep/Bash/WebFetch tools and denies actions that require interactive approval because no one is present to answer a prompt. The runner provides no OS sandbox for Claude. Bash runs with the same access as an ordinary local session, bounded only by the configured project directory and whatever rules exist in Claude's own settings. Project selection sets Claude's working directory, not a filesystem security boundary. If a turn finishes with denied requests, its status is needs_review, and completed work remains.
Set "claude_permission_mode": "bypassPermissions" globally, per agent, per project, or per project-agent. It uses the same precedence and keys as the Codex settings above. This setting stops dontAsk from denying actions during a task. It runs Claude with --dangerously-skip-permissions, which allows every tool call without a prompt or per-call review, including calls that dontAsk would otherwise deny. It is the only setting that removes the denials caused by this mode, and no narrower setting exists. Config validation rejects combining it with "approvals": "email" because full bypass conflicts with human-reviewed actions. Choose it deliberately, and prefer scoping it to one trusted project instead of using the global default.
Existing CLI sign-ins are reused. Inherited provider API-key variables are removed; explicit agent env entries can opt in. No subscription is created and there is no silent fallback to another agent. For an existing Claude account, set CLAUDE_CONFIG_DIR in agents.claude.env. Keep that account stable across replies.
Approve actions by email (optional)
Add this to your local configuration and restart the runner when no task is active:
"approvals": "email",
"approval_timeout_seconds": 900
When the CLI needs permission, the same running turn pauses. An email displays the complete native action, working directory, reason, task and turn identifiers, and a SHA256 digest. Reply directly to that approval email with approve or deny, or in its task thread with exactly approve TOKEN or deny TOKEN. Ordinary replies and quoted messages never count as approval. You can still send status or stop while waiting.
A grant applies to one concrete request, never a session or future command. Wrong-thread, expired, duplicate, cancelled, and restart-invalidated decisions cannot authorize it. No answer means denial after the timeout. The runner keeps reading mail while the agent waits and never restarts the task to implement approval. Previously completed external actions are not replayed. Native policies may still block an approved request.
Codex uses its native stdio app-server with on-request approval policy and the configured sandbox. Commands already permitted by that sandbox may run without an email; use "codex_sandbox": "read-only" for a stricter baseline. File-change requests need a complete native diff; requests for session-wide root grants, terminal input, unsupported permission types, and actions too large to display fully are refused.
Claude uses its native stream-json host permission channel with default mode. Existing allow rules can run without a new email; hard deny rules remain enforced. No broad tool allowlist is added in email mode. This is a bundled protocol adapter: no separately installed agent plugin or phone app is required. Use a current CLI supporting host permission prompts (Claude Code v2.1.259+ and Codex app-server). If the native channel is unavailable, the turn fails closed rather than falling back to bypass permissions.
Set "approvals": "off" to retain the original noninteractive behavior. This option does not enable bypass mode, change global CLI settings, or remove existing hooks. See approval behavior and limits.
Pick up locally
atgent list # pick a session with the arrow keys, Enter opens it here
atgent open TASK_ID # resume one task's session in this terminal
Each row shows the agent, the model, the turn status, how long ago it last ran and the subject; the bottom pane previews the selected task's last reply. Press / to filter, Esc to clear the filter, and q to quit. The session opens in its project directory with the agent's configured environment and model, so Claude sessions that use their own CLAUDE_CONFIG_DIR resume correctly. The resumed agent is told that you are now in the terminal, so it answers there instead of by email. If the task is still running from email, list and open ask whether to stop it first, then wait for the runner to release the session. atgent pickup TASK_ID prints the plain resume command without running it. Pause the runner during an extended local handoff; don't run local and email turns simultaneously against the same session.
Reliability and trust
- Intake reads Gmail's authenticated Sent special-use folder, not Inbox. A spoofed incoming sender can't submit a task. Anyone able to append to your Sent folder has equivalent task-submission authority; protect your Gmail account and app password.
- Task messages must be authored by the mailbox owner and addressed to the task alias. Automatic notifications are excluded to prevent loops.
- Message IDs are deduplicated in SQLite. References map replies to exact sessions. Unmatched replies never become new tasks.
- Configured workers run different project directories concurrently. The scheduler serializes each project directory and session within this runner.
- An exclusive process lock prevents a second runner. Interrupted turns are held rather than replayed. Recorded orphan process groups are stopped only after matching PID and OS start time. A small crash window exists between process creation and identity recording; inspect the machine after an unclean shutdown.
- SMTP sends with uncertain acceptance aren't blindly resent.
statusshows delivery state; check Sent mail as needed. A task can finish even when its notification fails. - A Sent-folder UID reset pauses intake. Shut down, review pending mail, then explicitly skip historical mail with
atgent rebaseline. - Local state contains prompts, attachments, approvals, and results and is created with private permissions. Agent session transcripts follow their CLI's normal retention policy. Neither belongs in the public repository.
There is no hosted inbox, mobile live-terminal UI, or remote browser-authentication handoff in this version. Email approvals authorize one displayed action; approve all is unsupported. Review work before publishing or deploying it.
Development
PYTHONPATH=src python3 -m unittest discover -s tests -v
For a source checkout, install with uv tool install .. See contributing for development checks.
Automated tests use temporary databases and fake subprocesses; they don't send email or invoke model APIs. See architecture, security, and launch package.
Metadata
Release files for atgent 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| atgent-0.3.0.tar.gz | 70.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| atgent-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 116.6 kB
Release files / atgent-0.3.0.tar.gz
| Download URL | atgent-0.3.0.tar.gz |
|---|---|
| Size | 70.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d88349f0ad55786e9ca549441c445533f226b6b051e9959120fccd3a00c0143a
|
|
BLAKE2b-256 checksum How to use checksums |
24d5950f39ffb8ed7cc37362cb53c55ff3c6659e20e46f620fd997ab7462b963
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.26 {"installer":{"name":"uv","version":"0.11.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / atgent-0.3.0-py3-none-any.whl
| Download URL | atgent-0.3.0-py3-none-any.whl |
|---|---|
| Size | 46.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
9a486c79cdeb2902ede6c6734844f1f650fb24f0f8cdd7b95ec97948b9b3e1a1
|
|
BLAKE2b-256 checksum How to use checksums |
e272adcbc64bfc148a583069532dfa4df34bcdafd0b53274bd868d2189ba10cc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.26 {"installer":{"name":"uv","version":"0.11.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|