atgent 0.3.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.
- atgent-0.3.0/LICENSE +21 -0
- atgent-0.3.0/MANIFEST.in +2 -0
- atgent-0.3.0/PKG-INFO +185 -0
- atgent-0.3.0/README.md +169 -0
- atgent-0.3.0/SECURITY.md +25 -0
- atgent-0.3.0/docs/approvals.md +35 -0
- atgent-0.3.0/docs/architecture.md +29 -0
- atgent-0.3.0/docs/launch.md +34 -0
- atgent-0.3.0/docs/oauth.md +24 -0
- atgent-0.3.0/docs/verification.md +32 -0
- atgent-0.3.0/pyproject.toml +31 -0
- atgent-0.3.0/setup.cfg +4 -0
- atgent-0.3.0/src/agent_mailbox/__init__.py +3 -0
- atgent-0.3.0/src/agent_mailbox/__main__.py +3 -0
- atgent-0.3.0/src/agent_mailbox/claude_approvals.py +268 -0
- atgent-0.3.0/src/agent_mailbox/cli.py +319 -0
- atgent-0.3.0/src/agent_mailbox/codex_approvals.py +238 -0
- atgent-0.3.0/src/agent_mailbox/core.py +853 -0
- atgent-0.3.0/src/agent_mailbox/oauth.py +256 -0
- atgent-0.3.0/src/agent_mailbox/render.py +187 -0
- atgent-0.3.0/src/agent_mailbox/runtime.py +534 -0
- atgent-0.3.0/src/agent_mailbox/service.py +144 -0
- atgent-0.3.0/src/agent_mailbox/ui.py +320 -0
- atgent-0.3.0/src/atgent.egg-info/PKG-INFO +185 -0
- atgent-0.3.0/src/atgent.egg-info/SOURCES.txt +32 -0
- atgent-0.3.0/src/atgent.egg-info/dependency_links.txt +1 -0
- atgent-0.3.0/src/atgent.egg-info/entry_points.txt +3 -0
- atgent-0.3.0/src/atgent.egg-info/top_level.txt +1 -0
- atgent-0.3.0/tests/test_approvals.py +136 -0
- atgent-0.3.0/tests/test_claude_approvals.py +202 -0
- atgent-0.3.0/tests/test_features.py +479 -0
- atgent-0.3.0/tests/test_mailbox.py +248 -0
- atgent-0.3.0/tests/test_models.py +206 -0
- atgent-0.3.0/tests/test_replies.py +300 -0
atgent-0.3.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Compound Labs
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
atgent-0.3.0/MANIFEST.in
ADDED
atgent-0.3.0/PKG-INFO
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: atgent
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: Email an idea. Your local coding agent gets to work.
|
|
5
|
+
Author: Compound Labs
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/kyisaiah47/atgent
|
|
8
|
+
Project-URL: Repository, https://github.com/kyisaiah47/atgent
|
|
9
|
+
Project-URL: Issues, https://github.com/kyisaiah47/atgent/issues
|
|
10
|
+
Project-URL: Security, https://github.com/kyisaiah47/atgent/security/policy
|
|
11
|
+
Keywords: codex,claude-code,email,automation
|
|
12
|
+
Requires-Python: >=3.11
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
License-File: LICENSE
|
|
15
|
+
Dynamic: license-file
|
|
16
|
+
|
|
17
|
+
# @gent
|
|
18
|
+
|
|
19
|
+
**Email an idea. Your coding agent gets to work.**
|
|
20
|
+
|
|
21
|
+
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.
|
|
22
|
+
|
|
23
|
+
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.
|
|
24
|
+
|
|
25
|
+
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.
|
|
26
|
+
|
|
27
|
+
## Send a task
|
|
28
|
+
|
|
29
|
+
```text
|
|
30
|
+
To: you+agents@gmail.com
|
|
31
|
+
Subject: Codex: improve the signup form
|
|
32
|
+
|
|
33
|
+
Find the confusing parts of the signup form, improve them,
|
|
34
|
+
and run the relevant checks. Leave the changes ready to review.
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
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:
|
|
38
|
+
|
|
39
|
+
```text
|
|
40
|
+
Claude [opus]: review the auth flow
|
|
41
|
+
Codex/website [gpt-6.1-sol]: fix the build
|
|
42
|
+
Claude/mailbox [haiku]: summarise the open issues
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
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.
|
|
46
|
+
|
|
47
|
+
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.
|
|
48
|
+
|
|
49
|
+
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.
|
|
50
|
+
|
|
51
|
+
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`.
|
|
52
|
+
|
|
53
|
+
## Install
|
|
54
|
+
|
|
55
|
+
With [uv](https://docs.astral.sh/uv/getting-started/installation/) installed:
|
|
56
|
+
|
|
57
|
+
```sh
|
|
58
|
+
uv tool install atgent
|
|
59
|
+
atgent init
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
The old `agent-mailbox` command still works and runs the same program.
|
|
63
|
+
|
|
64
|
+
`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.
|
|
65
|
+
|
|
66
|
+
Change an agent's default model later with `atgent model claude opus`, or `atgent model codex default` to return to Codex's own default.
|
|
67
|
+
|
|
68
|
+
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](https://support.google.com/accounts/answer/185833). Managed accounts and some security settings block app passwords; OAuth can still require administrator consent. See [Gmail OAuth setup](docs/oauth.md) for the alternative.
|
|
69
|
+
|
|
70
|
+
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`:
|
|
71
|
+
|
|
72
|
+
```json
|
|
73
|
+
"password_command": ["security", "find-generic-password", "-s", "atgent", "-w"]
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
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.
|
|
77
|
+
|
|
78
|
+
```sh
|
|
79
|
+
atgent doctor
|
|
80
|
+
atgent run
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
`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.
|
|
84
|
+
|
|
85
|
+
To run detached without opening a window:
|
|
86
|
+
|
|
87
|
+
```sh
|
|
88
|
+
atgent start
|
|
89
|
+
atgent status
|
|
90
|
+
atgent shutdown
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
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.
|
|
94
|
+
|
|
95
|
+
## Automatic startup (optional)
|
|
96
|
+
|
|
97
|
+
```sh
|
|
98
|
+
atgent shutdown
|
|
99
|
+
atgent install-service
|
|
100
|
+
atgent service-status
|
|
101
|
+
atgent uninstall-service
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
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.
|
|
105
|
+
|
|
106
|
+
## Projects and permissions
|
|
107
|
+
|
|
108
|
+
Only configured project aliases can be selected. Edit your local config:
|
|
109
|
+
|
|
110
|
+
```json
|
|
111
|
+
"projects": {
|
|
112
|
+
"main": "/absolute/path/to/project",
|
|
113
|
+
"website": {
|
|
114
|
+
"path": "/absolute/path/to/another/project",
|
|
115
|
+
"sandbox": "read-only",
|
|
116
|
+
"agents": {
|
|
117
|
+
"codex": {"approval_policy": "on-request", "approvals": "email"}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
"default_project": "main"
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
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.
|
|
125
|
+
|
|
126
|
+
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.
|
|
127
|
+
|
|
128
|
+
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.
|
|
129
|
+
|
|
130
|
+
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.
|
|
131
|
+
|
|
132
|
+
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.
|
|
133
|
+
|
|
134
|
+
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.
|
|
135
|
+
|
|
136
|
+
## Approve actions by email (optional)
|
|
137
|
+
|
|
138
|
+
Add this to your local configuration and restart the runner when no task is active:
|
|
139
|
+
|
|
140
|
+
```json
|
|
141
|
+
"approvals": "email",
|
|
142
|
+
"approval_timeout_seconds": 900
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
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.
|
|
146
|
+
|
|
147
|
+
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.
|
|
148
|
+
|
|
149
|
+
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.
|
|
150
|
+
|
|
151
|
+
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.
|
|
152
|
+
|
|
153
|
+
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](docs/approvals.md).
|
|
154
|
+
|
|
155
|
+
## Pick up locally
|
|
156
|
+
|
|
157
|
+
```sh
|
|
158
|
+
atgent list # pick a session with the arrow keys, Enter opens it here
|
|
159
|
+
atgent open TASK_ID # resume one task's session in this terminal
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
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.
|
|
163
|
+
|
|
164
|
+
## Reliability and trust
|
|
165
|
+
|
|
166
|
+
- 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.
|
|
167
|
+
- Task messages must be authored by the mailbox owner and addressed to the task alias. Automatic notifications are excluded to prevent loops.
|
|
168
|
+
- Message IDs are deduplicated in SQLite. References map replies to exact sessions. Unmatched replies never become new tasks.
|
|
169
|
+
- Configured workers run different project directories concurrently. The scheduler serializes each project directory and session within this runner.
|
|
170
|
+
- 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.
|
|
171
|
+
- SMTP sends with uncertain acceptance aren't blindly resent. `status` shows delivery state; check Sent mail as needed. A task can finish even when its notification fails.
|
|
172
|
+
- A Sent-folder UID reset pauses intake. Shut down, review pending mail, then explicitly skip historical mail with `atgent rebaseline`.
|
|
173
|
+
- 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.
|
|
174
|
+
|
|
175
|
+
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.
|
|
176
|
+
|
|
177
|
+
## Development
|
|
178
|
+
|
|
179
|
+
```sh
|
|
180
|
+
PYTHONPATH=src python3 -m unittest discover -s tests -v
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
For a source checkout, install with `uv tool install .`. See [contributing](CONTRIBUTING.md) for development checks.
|
|
184
|
+
|
|
185
|
+
Automated tests use temporary databases and fake subprocesses; they don't send email or invoke model APIs. See [architecture](docs/architecture.md), [security](SECURITY.md), and [launch package](docs/launch.md).
|
atgent-0.3.0/README.md
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
# @gent
|
|
2
|
+
|
|
3
|
+
**Email an idea. Your coding agent gets to work.**
|
|
4
|
+
|
|
5
|
+
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.
|
|
6
|
+
|
|
7
|
+
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.
|
|
8
|
+
|
|
9
|
+
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.
|
|
10
|
+
|
|
11
|
+
## Send a task
|
|
12
|
+
|
|
13
|
+
```text
|
|
14
|
+
To: you+agents@gmail.com
|
|
15
|
+
Subject: Codex: improve the signup form
|
|
16
|
+
|
|
17
|
+
Find the confusing parts of the signup form, improve them,
|
|
18
|
+
and run the relevant checks. Leave the changes ready to review.
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
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:
|
|
22
|
+
|
|
23
|
+
```text
|
|
24
|
+
Claude [opus]: review the auth flow
|
|
25
|
+
Codex/website [gpt-6.1-sol]: fix the build
|
|
26
|
+
Claude/mailbox [haiku]: summarise the open issues
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
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.
|
|
30
|
+
|
|
31
|
+
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.
|
|
32
|
+
|
|
33
|
+
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.
|
|
34
|
+
|
|
35
|
+
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`.
|
|
36
|
+
|
|
37
|
+
## Install
|
|
38
|
+
|
|
39
|
+
With [uv](https://docs.astral.sh/uv/getting-started/installation/) installed:
|
|
40
|
+
|
|
41
|
+
```sh
|
|
42
|
+
uv tool install atgent
|
|
43
|
+
atgent init
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
The old `agent-mailbox` command still works and runs the same program.
|
|
47
|
+
|
|
48
|
+
`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.
|
|
49
|
+
|
|
50
|
+
Change an agent's default model later with `atgent model claude opus`, or `atgent model codex default` to return to Codex's own default.
|
|
51
|
+
|
|
52
|
+
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](https://support.google.com/accounts/answer/185833). Managed accounts and some security settings block app passwords; OAuth can still require administrator consent. See [Gmail OAuth setup](docs/oauth.md) for the alternative.
|
|
53
|
+
|
|
54
|
+
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`:
|
|
55
|
+
|
|
56
|
+
```json
|
|
57
|
+
"password_command": ["security", "find-generic-password", "-s", "atgent", "-w"]
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
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.
|
|
61
|
+
|
|
62
|
+
```sh
|
|
63
|
+
atgent doctor
|
|
64
|
+
atgent run
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
`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.
|
|
68
|
+
|
|
69
|
+
To run detached without opening a window:
|
|
70
|
+
|
|
71
|
+
```sh
|
|
72
|
+
atgent start
|
|
73
|
+
atgent status
|
|
74
|
+
atgent shutdown
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
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.
|
|
78
|
+
|
|
79
|
+
## Automatic startup (optional)
|
|
80
|
+
|
|
81
|
+
```sh
|
|
82
|
+
atgent shutdown
|
|
83
|
+
atgent install-service
|
|
84
|
+
atgent service-status
|
|
85
|
+
atgent uninstall-service
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
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.
|
|
89
|
+
|
|
90
|
+
## Projects and permissions
|
|
91
|
+
|
|
92
|
+
Only configured project aliases can be selected. Edit your local config:
|
|
93
|
+
|
|
94
|
+
```json
|
|
95
|
+
"projects": {
|
|
96
|
+
"main": "/absolute/path/to/project",
|
|
97
|
+
"website": {
|
|
98
|
+
"path": "/absolute/path/to/another/project",
|
|
99
|
+
"sandbox": "read-only",
|
|
100
|
+
"agents": {
|
|
101
|
+
"codex": {"approval_policy": "on-request", "approvals": "email"}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
"default_project": "main"
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
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.
|
|
109
|
+
|
|
110
|
+
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.
|
|
111
|
+
|
|
112
|
+
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.
|
|
113
|
+
|
|
114
|
+
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.
|
|
115
|
+
|
|
116
|
+
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.
|
|
117
|
+
|
|
118
|
+
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.
|
|
119
|
+
|
|
120
|
+
## Approve actions by email (optional)
|
|
121
|
+
|
|
122
|
+
Add this to your local configuration and restart the runner when no task is active:
|
|
123
|
+
|
|
124
|
+
```json
|
|
125
|
+
"approvals": "email",
|
|
126
|
+
"approval_timeout_seconds": 900
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
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.
|
|
130
|
+
|
|
131
|
+
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.
|
|
132
|
+
|
|
133
|
+
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.
|
|
134
|
+
|
|
135
|
+
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.
|
|
136
|
+
|
|
137
|
+
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](docs/approvals.md).
|
|
138
|
+
|
|
139
|
+
## Pick up locally
|
|
140
|
+
|
|
141
|
+
```sh
|
|
142
|
+
atgent list # pick a session with the arrow keys, Enter opens it here
|
|
143
|
+
atgent open TASK_ID # resume one task's session in this terminal
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
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.
|
|
147
|
+
|
|
148
|
+
## Reliability and trust
|
|
149
|
+
|
|
150
|
+
- 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.
|
|
151
|
+
- Task messages must be authored by the mailbox owner and addressed to the task alias. Automatic notifications are excluded to prevent loops.
|
|
152
|
+
- Message IDs are deduplicated in SQLite. References map replies to exact sessions. Unmatched replies never become new tasks.
|
|
153
|
+
- Configured workers run different project directories concurrently. The scheduler serializes each project directory and session within this runner.
|
|
154
|
+
- 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.
|
|
155
|
+
- SMTP sends with uncertain acceptance aren't blindly resent. `status` shows delivery state; check Sent mail as needed. A task can finish even when its notification fails.
|
|
156
|
+
- A Sent-folder UID reset pauses intake. Shut down, review pending mail, then explicitly skip historical mail with `atgent rebaseline`.
|
|
157
|
+
- 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.
|
|
158
|
+
|
|
159
|
+
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.
|
|
160
|
+
|
|
161
|
+
## Development
|
|
162
|
+
|
|
163
|
+
```sh
|
|
164
|
+
PYTHONPATH=src python3 -m unittest discover -s tests -v
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
For a source checkout, install with `uv tool install .`. See [contributing](CONTRIBUTING.md) for development checks.
|
|
168
|
+
|
|
169
|
+
Automated tests use temporary databases and fake subprocesses; they don't send email or invoke model APIs. See [architecture](docs/architecture.md), [security](SECURITY.md), and [launch package](docs/launch.md).
|
atgent-0.3.0/SECURITY.md
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Security policy
|
|
2
|
+
|
|
3
|
+
atgent can cause a coding agent to read and modify local files. Treat access to the configured Gmail account, app password or OAuth token, queue, and agent sessions as access to your automation authority.
|
|
4
|
+
|
|
5
|
+
Intake uses authenticated Gmail Sent. Never adapt it to Inbox polling by checking only the visible From header: that would allow sender spoofing. Shared mailboxes, forwarded task submissions, and multiple authorized senders aren't supported.
|
|
6
|
+
|
|
7
|
+
Secrets are resolved at runtime, not stored in the repository or generated config. The runner removes inherited provider API keys and its configured password environment variable before launching agents. An agent with your OS identity may still access credentials available to that identity; this tool isn't a VM or secret-isolation boundary.
|
|
8
|
+
|
|
9
|
+
Task text, attachments, responses, and session IDs are retained locally and travel through Gmail. Don't email secrets. SMTP uncertainty is exposed rather than blindly retried. Cancellation cannot undo file changes or external actions already completed.
|
|
10
|
+
|
|
11
|
+
HTML is converted to text without running scripts or loading remote resources. Quoted-reply removal recognizes common email markup, not every email client. Review your outgoing reply and keep new instructions above quoted content. Attachments are untrusted files: filenames are sanitized and numbered, parents use mode 0700, and files use mode 0600 without overwrites. The runner enforces raw-message, attachment, combined-size, and count limits. It does not scan malware or automatically extract archives. Agents receive file paths; their own tools may interpret file contents. Stored attachments follow local task retention and are not deleted automatically.
|
|
12
|
+
|
|
13
|
+
OAuth requires the full Gmail IMAP/SMTP scope. Protect the OAuth client and refresh token as mailbox credentials. Tokens use macOS Keychain or Linux secret-tool when available; otherwise a warned 0600 local file is used. Keychain failures do not silently fall back to a file. PKCE and callback state checks protect the temporary loopback flow. The configured Gmail identity is authenticated before saving credentials. OAuth does not bypass Workspace administrator restrictions or account security policy.
|
|
14
|
+
|
|
15
|
+
Project directories and sessions are serialized within this runner, including project aliases resolving to the same directory. Concurrent unrelated projects still share the same OS identity and may access shared resources. Codex sandbox and approval policy are configurable; danger-full-access explicitly removes its sandbox. Claude is not given an OS sandbox. A project directory is not a security boundary. Existing external editors and agents require separate coordination.
|
|
16
|
+
|
|
17
|
+
Report vulnerabilities using [GitHub private vulnerability reporting](https://github.com/kyisaiah47/atgent/security/advisories/new). Do not include live credentials or private task contents. Do not disclose vulnerabilities in public issues.
|
|
18
|
+
|
|
19
|
+
Security fixes target the latest commit on `main` during the initial 0.1 development series. There are no older supported release lines yet.
|
|
20
|
+
|
|
21
|
+
## Email approvals
|
|
22
|
+
|
|
23
|
+
Opt-in email approvals use the same authenticated Sent-folder trust boundary as tasks. One random token is bound to a persisted immutable payload digest, task, and active turn. A decision must be a complete unquoted command in the correct thread; it is consumed immediately before one native permission response. Approval is not a persistent allow rule. Expiry, stop, process exit, and runner recovery revoke outstanding grants. Large or incomplete requests are denied rather than partially displayed.
|
|
24
|
+
|
|
25
|
+
Email and local SQLite contain full native action inputs, which can include sensitive command arguments or file content. Use this mode only with a mailbox and computer you trust. An account attacker who can author mail in Sent has task and approval authority. Email approval cannot make arbitrary agent code safe or override explicit native deny policies. A bare approve/deny must reference the actual approval email; other replies require its token. Whole-turn and permanent grants are unsupported.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Optional email approvals
|
|
2
|
+
|
|
3
|
+
Enable `"approvals": "email"` in the local runner config, optionally with `"approval_timeout_seconds": 900` (30 to 86400 seconds). Stop/restart an idle runner to apply a configuration change. Existing configurations default to `off` and are not migrated silently.
|
|
4
|
+
|
|
5
|
+
An approval email shows the complete action and its native request identifiers. Reply to that email with precisely one command:
|
|
6
|
+
|
|
7
|
+
```text
|
|
8
|
+
approve TOKEN_FROM_THE_EMAIL
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
or:
|
|
12
|
+
|
|
13
|
+
```text
|
|
14
|
+
deny TOKEN_FROM_THE_EMAIL
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Alternatively, reply directly to the actual approval email with exactly `approve` or `deny`. The message references must identify that pending approval; a bare decision elsewhere in the task thread is insufficient.
|
|
18
|
+
|
|
19
|
+
Use your connected Gmail account. A new thread, generic “yes,” extra text, quoted approval, or reused token does not authorize a request. `status` reports outstanding approvals and `stop` cancels the task. Multiple requests have separate tokens; responses apply only to their own request. `approve all` is unsupported; no whole-turn or persistent grant is created.
|
|
20
|
+
|
|
21
|
+
## How it runs
|
|
22
|
+
|
|
23
|
+
The mail intake loop and agent worker run independently. The agent subprocess remains paused at its native permission callback while mail arrives. A valid approval is consumed exactly once, then returned directly to that pending callback. No turn is replayed, no model is told to retry already completed actions, and no future permission rule is created. Token expiry uses wall-clock time; keep the computer's clock accurate.
|
|
24
|
+
|
|
25
|
+
Codex uses stdio app-server, initialized on demand for one task turn, and starts or resumes the exact saved thread. Supported callbacks are command execution and file changes with complete displayed diffs. Root grants and terminal-input approvals are refused. The configured sandbox still governs actions that do not need approval. Only a single-request `accept` is returned, never `acceptForSession` or a policy amendment.
|
|
26
|
+
|
|
27
|
+
Claude uses the same native stream-json `can_use_tool` host channel exposed by its Agent SDK. The runner responds with `allow` and the unchanged original input, or `deny`. Native hard deny rules are evaluated before this channel. There is no MCP service or separately installed plugin. Existing hooks and settings remain in place.
|
|
28
|
+
|
|
29
|
+
A missing native channel, incomplete action, payload over 24000 serialized characters, invalid protocol response, or runner failure cannot produce a grant. Stop, shutdown, task timeout, and restart revoke outstanding approvals and terminate the owned task process group. A process crash can occur after a native grant has already been sent: review retained changes and issue a deliberate follow-up instead of replaying the task.
|
|
30
|
+
|
|
31
|
+
## Verification
|
|
32
|
+
|
|
33
|
+
The automated suite covers wrong-thread replies, expiry, replay, tampering, cancellation, stale native requests, same-session continuation, and approval/denial over actual subprocess pipes. These tests use deterministic native-protocol fixtures and do not consume model usage or send email.
|
|
34
|
+
|
|
35
|
+
During implementation, isolated tests also exercised installed Codex and Claude Code with existing subscription sign-ins. Codex was tested end to end through real owner Gmail Sent intake and SMTP; the controlled file was absent before the decision, denial left it absent, and a separate matching approval allowed the waiting native command. Claude's installed native host channel was verified to wait, consume one grant, and preserve hard deny rules. A later Mac live run verified both agents through real owner Sent-folder approval replies, while their separate projects ran concurrently. Both tasks completed and all 10 notifications were accepted by SMTP. Installed versions were Codex 0.162.1 and Claude Code 2.1.280. These integration tests are manual checks, not CI dependencies.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Architecture
|
|
2
|
+
|
|
3
|
+
```text
|
|
4
|
+
Any email client → Gmail Sent → IMAP/TLS → local SQLite queue
|
|
5
|
+
↓
|
|
6
|
+
Codex / Claude Code
|
|
7
|
+
↓
|
|
8
|
+
Email thread ← Gmail ← SMTP/TLS ← result + session ID
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
One executable runs transport and a configurable worker pool. Intake stays responsive while tasks run or wait for native approvals, so stop emails can interrupt the owned child process group. SQLite records message IDs, task threads, queued turns, sessions, process identity, approval requests, and delivery state. No cloud database or public inbound listener is needed. The optional OAuth login starts a temporary loopback-only callback listener.
|
|
12
|
+
|
|
13
|
+
Initial subjects select agent/project. Replies select existing threads through References/In-Reply-To, not a model's guess. Agent/project stay fixed for each task. A new email starts a new task.
|
|
14
|
+
|
|
15
|
+
Manual and service runners share a config-local advisory lock. Explicit service installation creates a user LaunchAgent on macOS or a systemd user unit on Linux, with login startup and restart on failure. Service installation refuses an already active manual runner. Service removal stops and unregisters the user job. Service commands have bounded subprocess timeouts. The job cannot run while the machine is asleep, offline, or logged out on macOS.
|
|
16
|
+
|
|
17
|
+
Transactions deduplicate messages and enqueue work/notifications together. The watermark advances after ingestion commits. A crash between those steps revisits the message and deduplication suppresses duplicate work. First-run baselining skips historical mail.
|
|
18
|
+
|
|
19
|
+
Claiming commits `running` before spawning a CLI. Session IDs are captured from streamed events. Restart recovery checks recorded processes against OS start times, holds interrupted turns, and doesn't retry uncertain SMTP sends. This isn't an exactly-once guarantee for external actions performed by an agent.
|
|
20
|
+
|
|
21
|
+
Claims occur inside one locked SQLite transaction. Active turns block candidates with the same resolved project directory or session. Aliases for one directory therefore cannot create overlap. Worker count defaults to one and is capped at 32. Configuration is loaded at startup; restart an idle runner to apply changes. Separate processes and local agent sessions outside the runner are not coordinated.
|
|
22
|
+
|
|
23
|
+
MIME parsing prefers plain text, with a stdlib HTML-to-text fallback. Recognized quoted threads and active HTML content are excluded. Size is checked over IMAP before fetching the raw message, then checked again in the parser. Attachment bytes and counts are bounded. Sanitized, numbered files are written without overwriting beneath private task/message directories. Their absolute paths become part of the task prompt. Attachments and task state remain local until the owner removes them; no archive extraction or attachment execution is performed.
|
|
24
|
+
|
|
25
|
+
Codex sandbox and approval policy resolve from project-agent, project, agent, global, then defaults. Defaults remain workspace-write and never, or on-request when email approvals are selected. Claude's noninteractive mode retains its existing Read/Edit/Write allowlist; email mode uses native host permission prompts. Approval decisions enter through the same Sent-folder intake. Random request tokens bind one complete action to one active turn; expiry, cancellation, exit, and recovery revoke unused grants. A directly referenced approval email permits a bare approve/deny reply. Other decisions require its explicit token. No turn is replayed to implement a grant.
|
|
26
|
+
|
|
27
|
+
Gmail supports app passwords or XOAUTH2 for both IMAP and SMTP. OAuth uses an owner-supplied desktop client, PKCE, a random state value, and a temporary loopback callback. Authentication against the configured Gmail identity succeeds before credentials are saved. Refresh tokens use the OS keychain; the unsupported-keychain fallback warns and uses a private file. No OAuth client secret is distributed.
|
|
28
|
+
|
|
29
|
+
A future hosted email service could replace transport with signed jobs over outbound connections. It must preserve authorization, delivery IDs, local permission control, and session mappings, without collecting agent credentials or exposing a machine-wide shell endpoint.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Launch package
|
|
2
|
+
|
|
3
|
+
Name: **atgent** (shown as @gent). Name, package-index availability, and trademarks haven't been cleared. The [source repository](https://github.com/kyisaiah47/atgent) is public. This is a local runner, not a hosted service.
|
|
4
|
+
|
|
5
|
+
## Pitch
|
|
6
|
+
|
|
7
|
+
**Email an idea. Your coding agent gets to work.**
|
|
8
|
+
|
|
9
|
+
Start Codex or Claude Code tasks from your phone using email. Your computer runs the work with your existing agent sign-in and project setup. Results arrive in the same thread, and a reply continues the session. No SSH or mobile terminal app required.
|
|
10
|
+
|
|
11
|
+
## Launch post
|
|
12
|
+
|
|
13
|
+
I kept having coding ideas while away from my desk. I wanted to send the idea and have my computer start working.
|
|
14
|
+
|
|
15
|
+
So I built atgent. Email yourself a task, choose Codex or Claude Code in the subject, and get the result back in that thread. Reply to continue, check status, or stop the work. Pick up the same session when you're back at your computer.
|
|
16
|
+
|
|
17
|
+
It's open source, runs locally, and uses your existing agent sign-in. It supports Gmail app passwords or an owner-supplied OAuth desktop client. HTML-only email and attachments are accepted. Different projects can run concurrently. Optional email approvals authorize one displayed action. Automatic startup can be installed as a user service. Your computer needs to stay awake and online. macOS has live verification; Linux has automated coverage.
|
|
18
|
+
|
|
19
|
+
## Demonstration
|
|
20
|
+
|
|
21
|
+
1. Dictate a small task on an iPhone to your +agents alias.
|
|
22
|
+
2. Show the subject selecting agent/project.
|
|
23
|
+
3. Show Queued and Started messages.
|
|
24
|
+
4. Show the verified change in a disposable sample project.
|
|
25
|
+
5. Reply with a follow-up and show the same session continuing.
|
|
26
|
+
6. Show the local resume command and installation steps.
|
|
27
|
+
|
|
28
|
+
Use a test mailbox for public recordings. Hide addresses, unrelated tasks and account details. Capture fresh proof, and don't present simulations as completed work.
|
|
29
|
+
|
|
30
|
+
## Free and hosted
|
|
31
|
+
|
|
32
|
+
Ship the MIT local runner first. A future paid service could offer a dedicated address, easy pairing, managed delivery, and progress notifications. These are roadmap features, not included today. Keep agent credentials on customer machines and use outbound device connections.
|
|
33
|
+
|
|
34
|
+
Before a broader launch: choose the name, test onboarding on a clean second machine, and record a fresh public demonstration. Real Gmail task, attachment, concurrency, and native approval round trips have been verified on macOS; see the verification receipt. Publish destination links only after they exist. OAuth setup requires an owner-supplied Google desktop client and consent configuration. App passwords remain the simpler option where available.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Gmail OAuth setup
|
|
2
|
+
|
|
3
|
+
OAuth is optional. Keep the app-password method if it works for your account. OAuth uses your own installed-app client; no shared client or client secret ships with this package. It does not bypass Workspace administrator policy. The CLI implements the authorization and refresh flow. Google project and consent setup remain manual.
|
|
4
|
+
|
|
5
|
+
1. In your Google Cloud project, configure the OAuth consent screen and audience. For an external app in testing, add the intended Gmail account as a test user.
|
|
6
|
+
2. Configure the Gmail scope `https://mail.google.com/`. IMAP and SMTP require this full-mail scope. Google classifies it as restricted. External production distribution can require verification and additional requirements. Testing-mode authorizations may expire after seven days. See Google's [XOAUTH2 scope documentation](https://developers.google.com/workspace/gmail/imap/xoauth2-protocol) and [refresh-token expiry rules](https://developers.google.com/identity/protocols/oauth2).
|
|
7
|
+
3. Create an OAuth client with application type **Desktop app**. Use its client ID in the local config:
|
|
8
|
+
|
|
9
|
+
```json
|
|
10
|
+
"oauth": {"client_id": "YOUR_DESKTOP_CLIENT_ID.apps.googleusercontent.com"}
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
If the desktop client's token exchange requires its client secret, keep that value in a password manager or keychain. Set `oauth.client_secret_env` to its environment variable name or `oauth.client_secret_command` to a secret-resolver argument array. Never commit it or put the literal secret in the resolver command arguments.
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
atgent oauth-login
|
|
17
|
+
atgent doctor
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Open the printed Google authorization URL and choose the configured Gmail identity. The CLI waits up to five minutes for its temporary `127.0.0.1` callback. It uses PKCE and verifies callback state. It authenticates IMAP as the configured email before saving the token. `doctor` then verifies IMAP and SMTP without sending mail. When `oauth` is configured it takes priority over the password method; remove that section to return to app-password authentication.
|
|
21
|
+
|
|
22
|
+
Refresh tokens are stored in macOS Keychain under `agent-mailbox.gmail`, keyed by email, or through Linux `secret-tool`. A keychain error is reported. When no supported keychain exists, the runner warns and stores a mode-0600 token file under its private state directory. Do not share that state or include it in backups you do not trust. Revoke access through your Google account to invalidate a refresh token.
|
|
23
|
+
|
|
24
|
+
OAuth is covered by fake token exchange, callback, refresh, storage, and IMAP/SMTP protocol tests. See [the live verification receipt](verification.md) for the current Mac setup outcome. This is not proof that every managed domain permits the scope.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Verification receipt — 2026-10-13
|
|
2
|
+
|
|
3
|
+
Verified on macOS with Python 3.13:
|
|
4
|
+
|
|
5
|
+
- All 42 automated tests passed. The original 12 tests remain, with fake-based coverage for HTML-only mail, quoted-reply removal, attachments and size limits, malformed charsets, private parent directories, symlink refusal, concurrent workers, project aliases, shared sessions, per-project permission precedence, native approvals, OAuth loopback/PKCE/token refresh/keychain fallback/atomic file writes/XOAUTH2, and service units/install/status/removal/runner-lock refusal.
|
|
6
|
+
- Ruff checks passed. Source distribution and wheel built successfully.
|
|
7
|
+
- Installed the wheel into a clean temporary environment; all tests and CLI startup passed there.
|
|
8
|
+
- Authenticated Gmail IMAP and SMTP using an existing credential resolver, without putting the secret in source/config.
|
|
9
|
+
- Submitted real email tasks for both Codex and Claude Code. Each created and read back a proof file in an isolated temporary project.
|
|
10
|
+
- Submitted follow-up emails referencing the result messages. Both resumed their original session IDs and verified the requested follow-up file edits.
|
|
11
|
+
- All 12 task notifications were accepted by SMTP. The final completed result for each agent was independently found in the personal Inbox.
|
|
12
|
+
- The first Claude turn reported a denied tool request despite completing its file edit. Its follow-up, limited to Read/Write tools, completed without denials. The runner now distinguishes `needs_review` for completed turns with denied requests.
|
|
13
|
+
- Removed the temporary proof project and its files. Kept only private lightweight receipts and normal agent-owned session state outside this repository.
|
|
14
|
+
|
|
15
|
+
## Additional feature checks on this Mac
|
|
16
|
+
|
|
17
|
+
The local lightweight feature receipt records Codex CLI 0.162.1 and Claude Code 2.1.280 with their existing subscription sign-ins. No provider API keys were used for model calls.
|
|
18
|
+
|
|
19
|
+
- Submitted HTML-only mail with an attachment through real owner Gmail Sent intake. Codex read the attachment's contents and completed the proof task.
|
|
20
|
+
- Ran real Codex and Claude tasks in two separate disposable project directories. Their execution overlapped; both completed.
|
|
21
|
+
- Both running agents requested native approval. Owner replies sent through Gmail Sent granted their exact pending action, with no task replay. Both grants were consumed and all 10 task/approval notifications were accepted by SMTP.
|
|
22
|
+
- Installed the user service, verified its running state with `launchctl print`, verified the shared lock rejected another runner, requested shutdown, and uninstalled it. A later check confirmed the service was removed. The check did not reboot this Mac.
|
|
23
|
+
- Codex sandbox selection was exercised live with native approval requests. The full config precedence and accepted policy values are verified by unit tests; every sandbox/policy combination has not been live-tested.
|
|
24
|
+
- Upgraded the installed uv tool to 0.2.0. Verified the prior installed runner's PID, held lock, and idle queue before stopping it. Restarted the ordinary detached runner with unchanged personal config and confirmed its lock and queue state. No turn was replayed.
|
|
25
|
+
|
|
26
|
+
Service definitions allow 45 seconds for child cleanup; removal commands allow 60 seconds. These shutdown grace settings are unit-tested, not a separate live reboot/termination check.
|
|
27
|
+
|
|
28
|
+
Gmail OAuth has fake-based coverage only. Live client setup was started, but the desktop client and consent authorization were not complete when this receipt was written. No successful live OAuth authorization or token refresh is claimed.
|
|
29
|
+
|
|
30
|
+
Not yet verified: a physical iPhone submission, Linux runtime or systemd startup on a physical Linux host, an actual reboot, or onboarding on a separate physical machine. The first hosted CI matrix passed on macOS/Linux with Python 3.11/3.13: [run 38485858618](https://github.com/kyisaiah47/atgent/actions/runs/38485858618). The source repository is public. No package-index release or hosted runner service is claimed. The website has a separate deployment receipt.
|
|
31
|
+
|
|
32
|
+
GitHub publication checks: all tracked history passed Gitleaks with no detected secrets; source uses generic email examples and no personal config/task state. The repository has MIT licensing, Issues, contribution guidance, and enabled private vulnerability reporting.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=77"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "atgent"
|
|
7
|
+
version = "0.3.0"
|
|
8
|
+
description = "Email an idea. Your local coding agent gets to work."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.11"
|
|
11
|
+
license = "MIT"
|
|
12
|
+
license-files = ["LICENSE"]
|
|
13
|
+
authors = [{name = "Compound Labs"}]
|
|
14
|
+
keywords = ["codex", "claude-code", "email", "automation"]
|
|
15
|
+
dependencies = []
|
|
16
|
+
|
|
17
|
+
[project.urls]
|
|
18
|
+
Homepage = "https://github.com/kyisaiah47/atgent"
|
|
19
|
+
Repository = "https://github.com/kyisaiah47/atgent"
|
|
20
|
+
Issues = "https://github.com/kyisaiah47/atgent/issues"
|
|
21
|
+
Security = "https://github.com/kyisaiah47/atgent/security/policy"
|
|
22
|
+
|
|
23
|
+
[project.scripts]
|
|
24
|
+
atgent = "agent_mailbox.cli:main"
|
|
25
|
+
agent-mailbox = "agent_mailbox.cli:main"
|
|
26
|
+
|
|
27
|
+
[tool.setuptools.packages.find]
|
|
28
|
+
where = ["src"]
|
|
29
|
+
|
|
30
|
+
[tool.ruff.lint]
|
|
31
|
+
select = ["E4", "E7", "E9", "F", "I"]
|