@hiro5409/attio-cli 0.0.0-stage → 0.1.1
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.
- package/LICENSE +21 -0
- package/README.md +174 -2
- package/bin/attio-api +2 -0
- package/dist/cli-cTGHeWUi.mjs +4747 -0
- package/dist/cli-cTGHeWUi.mjs.map +1 -0
- package/dist/main.mjs +7 -0
- package/dist/main.mjs.map +1 -0
- package/dist/package-lsdxDgro.mjs +70 -0
- package/dist/package-lsdxDgro.mjs.map +1 -0
- package/package.json +70 -3
- package/skills/attio-cli/SKILL.md +26 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Hiro5409
|
|
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.
|
package/README.md
CHANGED
|
@@ -1,3 +1,175 @@
|
|
|
1
|
-
#
|
|
1
|
+
# attio-cli
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
An unofficial CLI for the [Attio API](https://docs.attio.com/rest-api/overview). Every command is generated from Attio's OpenAPI schema and carries the name Attio's own documentation gives the operation.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
Requires Node.js 24.11.0 or newer. macOS and Linux are supported; Windows is not tested. mise, pnpm, and Vite+ are development tools and are not required to use the npm package.
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
npm install --global @hiro5409/attio-cli
|
|
11
|
+
attio-api --version
|
|
12
|
+
attio-api --help
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
The command is `attio-api`. The `attio` command belongs to Attio's own CLI for building apps on its platform, and the two can be installed side by side.
|
|
16
|
+
|
|
17
|
+
## Authentication
|
|
18
|
+
|
|
19
|
+
Create an access token in Attio under Workspace settings → Developers, with the scopes the commands you run need, and provide it through the environment:
|
|
20
|
+
|
|
21
|
+
```sh
|
|
22
|
+
export ATTIO_ACCESS_TOKEN=…
|
|
23
|
+
attio-api meta identify
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
`meta identify` reports the token's workspace and scopes. The CLI reads the token from `ATTIO_ACCESS_TOKEN` only and stores nothing. Do not pass access tokens as command arguments or keep them in the repository; a secret manager that injects the variable into the command's environment keeps the token out of shell history.
|
|
27
|
+
|
|
28
|
+
## Usage
|
|
29
|
+
|
|
30
|
+
Commands are grouped the way Attio's API reference groups its operations, and each command is named after its page there. [Upsert a record](https://docs.attio.com/rest-api/endpoint-reference/records/upsert-a-record) is `attio-api records upsert-a-record`.
|
|
31
|
+
|
|
32
|
+
```sh
|
|
33
|
+
attio-api --help
|
|
34
|
+
attio-api records --help
|
|
35
|
+
attio-api records upsert-a-record --help
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Path and query parameters are options. Operations that take a request body accept it as JSON through `--body`:
|
|
39
|
+
|
|
40
|
+
```sh
|
|
41
|
+
attio-api objects list-objects
|
|
42
|
+
|
|
43
|
+
attio-api attributes list-attributes --target objects --identifier companies
|
|
44
|
+
|
|
45
|
+
attio-api records list-records --object companies --body '{"limit": 10}'
|
|
46
|
+
|
|
47
|
+
attio-api records upsert-a-record --object companies --matching-attribute domains \
|
|
48
|
+
--body '{"data": {"values": {"name": "Example", "domains": ["example.com"]}}}'
|
|
49
|
+
|
|
50
|
+
attio-api notes create-a-note --body "$(cat note.json)"
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
The body is the request body Attio documents for the operation, unchanged. Each command performs one operation and prints its response; to read a further page, pass the `offset` or `cursor` the operation documents.
|
|
54
|
+
|
|
55
|
+
Two operations have no command: uploading a file, which takes a multipart body, and downloading a file, which answers with a redirect.
|
|
56
|
+
|
|
57
|
+
## Output and failures
|
|
58
|
+
|
|
59
|
+
A successful command prints Attio's response to stdout as JSON and exits with 0. A failed command prints nothing to stdout and one JSON object to stderr:
|
|
60
|
+
|
|
61
|
+
```json
|
|
62
|
+
{
|
|
63
|
+
"error": {
|
|
64
|
+
"code": "FORBIDDEN",
|
|
65
|
+
"hint": "Attio's message names what is missing: a scope on the token, access to the resource, or a plan that allows the operation.",
|
|
66
|
+
"attio": { "code": "…", "type": "…" },
|
|
67
|
+
"status": 403,
|
|
68
|
+
"message": "…"
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
`code` is stable. `status` and `attio` appear when Attio answered, and `attio` carries the error code and type from Attio's own response.
|
|
74
|
+
|
|
75
|
+
| Exit code | `code` | Meaning |
|
|
76
|
+
| --------- | ------------------------------------------------------------------ | --------------------------------------------------------------------------------------- |
|
|
77
|
+
| 0 | | Successful command or help |
|
|
78
|
+
| 1 | `API_ERROR`, `NOT_FOUND`, `NETWORK_ERROR` | Attio reported a failure or could not be reached |
|
|
79
|
+
| 2 | `INVALID_ARGUMENT`, `BAD_REQUEST`, `AUTH_REQUIRED`, `UNAUTHORIZED` | The command line or the request is invalid, or the token is missing or rejected |
|
|
80
|
+
| 3 | `FORBIDDEN` | Attio denied the operation: a missing scope, no access to the resource, or a plan limit |
|
|
81
|
+
| 4 | `RATE_LIMITED` | Attio is still rate limiting after the retries |
|
|
82
|
+
|
|
83
|
+
`INVALID_ARGUMENT` comes from the command line itself: an unknown or missing option, or a body that is not JSON. No request reached Attio. The body's content is Attio's to validate, because Attio accepts shapes its schema does not describe, such as a single value where the schema shows a list; a rejected request is `BAD_REQUEST`, with Attio's explanation as the message. Responses are printed as Attio returned them.
|
|
84
|
+
|
|
85
|
+
Each attempt has a 10-second timeout; a timeout is reported as `NETWORK_ERROR` without a retry. GET, PUT, and DELETE requests are retried up to twice after a rate limit, a server error, or a failed connection. POST and PATCH requests are retried only after a rate limit, because Attio does not process a rate-limited request. A retry waits as long as Attio's `Retry-After` header asks. After `NETWORK_ERROR` or a server error on a write, the write may have taken effect; check before repeating it.
|
|
86
|
+
|
|
87
|
+
During 0.x, minor releases may change commands; a command's name follows the summary in Attio's schema, so it changes when Attio renames the operation. Pin the version when depending on exact names.
|
|
88
|
+
|
|
89
|
+
## Agent skill
|
|
90
|
+
|
|
91
|
+
The [attio-cli skill](skills/attio-cli/SKILL.md) guides command discovery, authentication, and interpretation of failures. Install it for Codex with GitHub CLI's `gh skill` command:
|
|
92
|
+
|
|
93
|
+
```sh
|
|
94
|
+
gh skill install Hiro5409/attio-cli attio-cli --agent codex --scope user
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Use `--agent claude-code` for Claude Code. The npm package also includes the skill under `skills/attio-cli`.
|
|
98
|
+
|
|
99
|
+
## Development
|
|
100
|
+
|
|
101
|
+
Install and [activate mise](https://mise.jdx.dev/getting-started.html), which provides the pinned tools:
|
|
102
|
+
|
|
103
|
+
```sh
|
|
104
|
+
mise trust
|
|
105
|
+
mise install
|
|
106
|
+
pnpm install --frozen-lockfile
|
|
107
|
+
lefthook install
|
|
108
|
+
vp pack
|
|
109
|
+
node bin/attio-api --help
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
`bin/attio-api` runs the build in `dist`, so run `vp pack` again after changing the source. The pnpm version is declared in both `mise.toml` and `package.json`; change them together.
|
|
113
|
+
|
|
114
|
+
## API schema
|
|
115
|
+
|
|
116
|
+
Everything under `src/types/attio` is generated from the committed OpenAPI snapshot, `openapi/attio-api.json`. A new operation in the schema becomes a command without further work; `openapi-ts.config.ts` lists the operations left out, each with the reason.
|
|
117
|
+
|
|
118
|
+
Check whether Attio's published schema changed, then update the snapshot and regenerate:
|
|
119
|
+
|
|
120
|
+
```sh
|
|
121
|
+
vp run api-schema:check
|
|
122
|
+
vp run api-schema:update
|
|
123
|
+
vp run generate-types
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
`@hey-api/openapi-ts` and `@hey-api/shared` are pinned to the same snapshot release and move together.
|
|
127
|
+
|
|
128
|
+
## Quality checks
|
|
129
|
+
|
|
130
|
+
```sh
|
|
131
|
+
vp run check
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
The tests run commands end to end and replace only Attio's HTTP API. To check a packed artifact the way the CI does, without contacting Attio:
|
|
135
|
+
|
|
136
|
+
```sh
|
|
137
|
+
package_dir=$(mktemp -d)
|
|
138
|
+
pnpm pack --pack-destination "$package_dir"
|
|
139
|
+
node scripts/check-package.ts "$package_dir"/*.tgz
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## Dependency updates
|
|
143
|
+
|
|
144
|
+
Dependabot proposes the updates, and a maintainer reviews and merges them. The generator packages and Vite+ are updated by hand, because each moves together with other pins.
|
|
145
|
+
|
|
146
|
+
Dependency Review needs the repository's [dependency graph](https://docs.github.com/en/code-security/reference/supply-chain-security/dependency-graph-supported-package-ecosystems) to be enabled.
|
|
147
|
+
|
|
148
|
+
## Releases
|
|
149
|
+
|
|
150
|
+
A maintainer releases from `main`: commit the new `version` in `package.json`, push the commit to `main`, then push the annotated tag for that version:
|
|
151
|
+
|
|
152
|
+
```sh
|
|
153
|
+
git tag -a v1.2.3
|
|
154
|
+
git push origin v1.2.3
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
`git tag -a` opens an editor for the tag message; list there, as Markdown bullets, the changes a user will notice. The message becomes the GitHub Release notes.
|
|
158
|
+
|
|
159
|
+
The tag starts the Release workflow, which publishes the tested artifact to npm and then creates the GitHub Release from it.
|
|
160
|
+
|
|
161
|
+
Before publishing, configure three settings outside the repository:
|
|
162
|
+
|
|
163
|
+
- A GitHub environment `npm` whose deployment policy allows only `v*` tags.
|
|
164
|
+
- An npm [trusted publisher](https://docs.npmjs.com/trusted-publishers/) for user `Hiro5409`, repository `attio-cli`, workflow filename `release.yml`, and environment `npm`, with `npm publish` allowed and `npm dist-tag` left unchecked.
|
|
165
|
+
- [Immutable releases](https://docs.github.com/en/code-security/concepts/supply-chain-security/immutable-releases) for the repository, so that the tag and the attached artifact of a published GitHub Release cannot change.
|
|
166
|
+
|
|
167
|
+
To retry a failed run, run the workflow again from its tag. A rerun publishes only what is still missing:
|
|
168
|
+
|
|
169
|
+
```sh
|
|
170
|
+
gh workflow run release.yml --ref v1.2.3
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
## License
|
|
174
|
+
|
|
175
|
+
[MIT](LICENSE). This project is not affiliated with Attio.
|
package/bin/attio-api
ADDED