Expose per-contact autofiling in the CLI
- Dominant language
- Go
- Stars
- 368
- Forks
- 44
- Avg merge
- 15h 15m
- Merged PRs (30d)
- 189
Description
## Problem
HEY's web UI lets you open a contact and set **Autofiling in ``**. Every new conversation from
that contact then gets the label on arrival ([help 884](https://help.hey.com/article/884-labels)).
The CLI does not expose that setting. `hey contact update` takes `--alias`, `--email` and `--name`,
and no other command reaches it:
```console
$ hey contact update --help | sed -n '/FLAGS/,/INHERITED/p'
FLAGS
--alias strings Replacement alternate email address (repeatable)
--email string New primary email address
-h, --help help for update
--name string New contact name
```
So the setting is configurable by hand and by nobody else. It cannot be scripted, version-controlled,
or checked by an agent.
**It cannot be read back either.** `hey contact show` returns no autofiling field. `folders` appears
in the payload only under `postings[]`, which is the labels already attached to threads, not the rule
that attaches them:
```console
$ hey contact show --json --jq '.data | keys'
["account_id","avatar_background_color","avatar_url","clearance","contactable_type","domain",
"edit_app_url","email_address","entries_title","id","initials","name","note","postings","updated_at"]
```
The read gap is the one that bites. Because there is no read-back, the only way to confirm a setting
took is to open the contact page and look. I set autofiling on 26 contact records across two linked
accounts and caught four silent UI failures, using `updated_at` flipping to the current date as a
proxy. A proxy is not a check.
The per-account scoping makes it worse. Autofiling is per contact **per account**, so a contact in
two linked accounts needs it set twice. Setting it once looks complete while covering half the mail.
8 of my 19 client contacts were dual-account. That is exactly the class of mistake a scripted,
readable setting prevents and a manual one invites.
## Implementation context
The routes exist. `basecamp/hey-sdk` lists all three in `spec/route-snapshot.json`:
```
GET /autofileables/{autofileable_id}/autofilings
POST /autofileables/{autofileable_id}/autofilings
DELETE /autofileables/{autofileable_id}/autofilings/{id}
```
They are excluded from the SDK on purpose, in `spec/excluded-routes.json`, with the reason
`phase-2: autofiling rules`.
So this is a scheduling question, not a discovery one. For what it is worth as an argument for
pulling it forward: the snapshot holds 1651 routes and 723 exclusions across roughly 100 phase-2
areas, and autofiling is a three-route area. Most of the others are much larger.
The path says `autofileable`, not `contact`, so the resource is polymorphic and a contact-first
command would cover a subset. That may argue for a different command shape than the one below.
## Proposed behavior
A contact-first command, mirroring where the setting lives in the UI:
```console
hey contact autofile # GET, show the current rule
hey contact autofile --to "City Stems" # POST, set it
hey contact autofile --clear # DELETE
```
`--to` resolving a label by name or ID would match `hey label add --to`, which takes an ID, and
`hey search --label`, which takes a name. Either is fine as long as it is stated, because that pair
already surprises people.
`--clear` needs the autofiling record ID from the GET, so it is two calls internally and one command
to the caller.
Two smaller asks, either of which is worth having on its own:
- **Surface the current rule on `hey contact show`.** The GET route already exists. This alone closes
the verification gap, even with no write command.
- **Make the account explicit.** The setting is per account, so the command should honour `--account`
and say which mailbox it wrote to. `--account all` setting both would remove the dual-account trap
entirely.
## Expected outcome
An agent or a script can set a contact's autofiling label, read it back, and prove it. Client mail
routing becomes reproducible from a file instead of remembered from a screen.
## Related
- #336 is the same contact-first shape for a different setting, the default delivery box
(Imbox, The Feed, Paper Trail, Screened Out). This issue is about the autofiling **label**, which
is a separate control on the same contact page. Whatever command name #336 settles on, these two
should probably agree.
Checked against `hey` 1.3.0 with the v1.3.1 changelog reviewed, `basecamp/hey-cli@main`, and
`basecamp/hey-sdk@main` on 2026-09-01. `autofile` returns zero hits across the hey-cli tree.
Contributor guide
Research direction
Start with the excluded autofiling routes in spec/excluded-routes.json and their entries in spec/route-snapshot.json, then compare the existing hey contact show/update, hey label add --to, and hey search --label commands. Account scoping and the command shape still need deciding, with #336 as a related reference. Done means the rule can be set, read back, and cleared, including the correct account.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- api, cli
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100