@thinger-io/cli 0.3.0 → 0.5.0
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/CHANGELOG.md +107 -0
- package/README.md +107 -37
- package/lib/identity.js +7 -5
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,112 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.5.0] - 2026-10-31
|
|
4
|
+
|
|
5
|
+
Every command follows one grammar, noun first:
|
|
6
|
+
`thinger <noun> [<noun>…] <verb> [<parent ids>…] [<id>] [options]`.
|
|
7
|
+
Nouns nest under their parent (`device property`, `product profile api`),
|
|
8
|
+
ids are positional and named after their noun, and the options keep one
|
|
9
|
+
meaning everywhere (`-j` JSON, `-s` a body field, `-f` one field of the
|
|
10
|
+
answer, `-o` a file, `-y` no questions). A few commands of 0.3 change
|
|
11
|
+
form: see the table below. The old forms are gone, not aliased.
|
|
12
|
+
|
|
13
|
+
The MCP server serves eight tools instead of 25: `thinger_resource_*`
|
|
14
|
+
reach everything by `type`, and records are addressed with `ids`. The old
|
|
15
|
+
tool names and the `parent`/`id` arguments are gone, not aliased: see the
|
|
16
|
+
second table below.
|
|
17
|
+
|
|
18
|
+
### Added
|
|
19
|
+
|
|
20
|
+
- Commands for every resource type the MCP server reaches, generated from
|
|
21
|
+
the same catalog: `list|get|create|update|delete|clone|describe` and the
|
|
22
|
+
type's actions (`thinger endpoint call`, `thinger alarm rule test`,
|
|
23
|
+
`thinger admin host restart`…), with bodies from `--from` and
|
|
24
|
+
`-s key=value`, `-n`/`-d` for the name and description, and
|
|
25
|
+
`set <property> <value>` on every kind of property. Endpoints, tokens,
|
|
26
|
+
alarms, storages, projects, assets, syncs, claims, plugins, product
|
|
27
|
+
profiles, properties and the server administration are now reachable from
|
|
28
|
+
the command line and from CI.
|
|
29
|
+
- `thinger api <path>`: any request to the server, as `gh api` does.
|
|
30
|
+
- Commands over the operations that are not CRUD:
|
|
31
|
+
`thinger bucket write|export`,
|
|
32
|
+
`thinger storage file list|upload|download|delete`,
|
|
33
|
+
`thinger device send|overview`, `thinger device resource list|call`,
|
|
34
|
+
`thinger product apply --from`, `thinger product profile api call` and
|
|
35
|
+
`thinger plugin call`. `product export` and `product apply` keep a
|
|
36
|
+
product in a repository and deploy it.
|
|
37
|
+
- `device list`, `product list` and `bucket list` take `--search`,
|
|
38
|
+
`--filter`, `--count` and `--index`; `device create` and `product create`
|
|
39
|
+
take `--from`, `-s` and `--projects`; `get` takes `-f <dot.path>`.
|
|
40
|
+
- `thinger doc list` and `thinger doc get <doc>`: the guides for agents
|
|
41
|
+
from the command line.
|
|
42
|
+
- MCP: `resource_describe` shows each type's ids, actions, the permission
|
|
43
|
+
each operation needs and ready-to-send examples; actions that change a
|
|
44
|
+
lot at once (`replace_all`, a host's settings or restart, removing a
|
|
45
|
+
plugin) answer a plan and run with `confirm: true` (or ask through the
|
|
46
|
+
client when it supports it); `thinger mcp --read-only` (or
|
|
47
|
+
`THINGER_MCP_READ_ONLY=1`) serves only what reads.
|
|
48
|
+
|
|
49
|
+
### Changed (breaking)
|
|
50
|
+
|
|
51
|
+
| 0.3 | 0.4 |
|
|
52
|
+
| ------------------------------------------------ | ----------------------------------------------------------- |
|
|
53
|
+
| `thinger device list <pattern>` | `thinger device list --search <text>` |
|
|
54
|
+
| `thinger device info <device>` | `thinger device get <device>` |
|
|
55
|
+
| `thinger device property <device>` | `thinger device property list <device>` |
|
|
56
|
+
| `thinger device property <device> <prop>` | `thinger device property get <device> <property>` |
|
|
57
|
+
| `thinger device property-set <device> <p> <v>` | `thinger device property set <device> <property> <value>` |
|
|
58
|
+
| `thinger device resource <device>` | `thinger device resource list <device>` |
|
|
59
|
+
| `thinger device resource <device> <r> -i k=v` | `thinger device resource call <device> <resource> -s k=v` |
|
|
60
|
+
| `thinger product info <product>` | `thinger product get <product>` |
|
|
61
|
+
| `thinger product property-list <product>` | `thinger product property list <product>` |
|
|
62
|
+
| `thinger product property-get <product> <p>` | `thinger product property get <product> <property>` |
|
|
63
|
+
| `thinger product property-set <product> <p> <v>` | `thinger product property set <product> <property> <value>` |
|
|
64
|
+
| `thinger product property-delete <product> <p>` | `thinger product property delete <product> <property> -y` |
|
|
65
|
+
|
|
66
|
+
- `device property get` and `product property get` print the property
|
|
67
|
+
record, with its value under `value`: `-f` paths start there
|
|
68
|
+
(`-f value.setpoint` where 0.3 took `-f setpoint`). `device property list`
|
|
69
|
+
and `product property list` print the records (`-j`: the records, not
|
|
70
|
+
`{ product, properties: [names] }`). `product property delete` asks
|
|
71
|
+
unless `-y`. `device resource call` takes its input from `--from` and
|
|
72
|
+
`-s` (`-i` is gone); `-s` values are parsed as JSON, as before.
|
|
73
|
+
- The root help groups the commands as Resources, Administration,
|
|
74
|
+
Configuration and Integration.
|
|
75
|
+
- The MCP tools (the commands keep their forms and `-j` outputs; the help
|
|
76
|
+
names some positionals as the server does: `asset type get <type>`,
|
|
77
|
+
`asset group get <group>`, `alarm rule get <rule>`,
|
|
78
|
+
`alarm instance get <instance>`,
|
|
79
|
+
`product profile <category> get <product> <resource>`):
|
|
80
|
+
|
|
81
|
+
| 0.3 tool | 0.4 call |
|
|
82
|
+
| ------------------------------------------------ | ----------------------------------------------------------------------------------------- |
|
|
83
|
+
| `thinger_resource_* parent "d1" id "p1"` | `thinger_resource_* ids {"device": "d1", "property": "p1"}` |
|
|
84
|
+
| `thinger_bucket_data_read` | `thinger_resource_list type "bucket_data" ids {bucket}` (`filter` for the query) |
|
|
85
|
+
| `thinger_bucket_data_write` | `thinger_resource_create type "bucket_data" ids {bucket} body <samples>` |
|
|
86
|
+
| `thinger_storage_file_list` | `thinger_resource_list type "storage_file" ids {storage} filter {path}` |
|
|
87
|
+
| `thinger_storage_file_read` | `thinger_resource_get type "storage_file" ids {storage, file}` |
|
|
88
|
+
| `thinger_storage_file_write` | `thinger_resource_create type "storage_file" ids {storage, file} body {content or local}` |
|
|
89
|
+
| `thinger_storage_file_delete` | `thinger_resource_delete type "storage_file" ids {storage, file}` |
|
|
90
|
+
| `thinger_device_resource_list` | `thinger_resource_list type "device_resource" ids {device}` |
|
|
91
|
+
| `thinger_device_resource_call` | `thinger_resource_call type "device_resource" action "call" ids {device, resource}` |
|
|
92
|
+
| `thinger_device_data_send` | `thinger_resource_call type "device" action "send" ids {device} body <data>` |
|
|
93
|
+
| `thinger_device_overview` | `thinger_resource_call type "device" action "overview"` |
|
|
94
|
+
| `thinger_product_resource_call` | `thinger_resource_call type "product_profile_api" action "call" ids {product, resource}` |
|
|
95
|
+
| `thinger_plugin_call` | `thinger_resource_call type "plugin" action "call" ids {plugin} body {path, method}` |
|
|
96
|
+
| `thinger_doc_read` | `thinger_resource_get type "doc" ids {doc}` (`thinger_resource_list type "doc"` lists) |
|
|
97
|
+
| `thinger_profile_list` | `thinger_resource_list type "profile"` |
|
|
98
|
+
| `thinger_dashboard_init` / `_dev` / `_publish` | `thinger_resource_call type "dashboard" action "init"` / `"dev"` / `"publish"` |
|
|
99
|
+
|
|
100
|
+
- Requires `@thinger-io/cli-core` 0.5.0. From this release the CLI's minor
|
|
101
|
+
version follows the core's (0.5.x runs on cli-core 0.5.x), so there is no
|
|
102
|
+
0.4.0.
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
### Fixed
|
|
106
|
+
|
|
107
|
+
- Tokens created with an expiry such as "30d" (`thinger_resource_create`)
|
|
108
|
+
were refused by the server: it takes milliseconds.
|
|
109
|
+
|
|
3
110
|
## [0.3.0] - 2026-10-16
|
|
4
111
|
|
|
5
112
|
### Added
|
package/README.md
CHANGED
|
@@ -6,8 +6,8 @@ operate it with the permissions of your token.
|
|
|
6
6
|
|
|
7
7
|
- **CLI** — devices, products, buckets, dashboard apps and profiles from a
|
|
8
8
|
shell, with `--json` output for scripts.
|
|
9
|
-
- **MCP server** — `thinger mcp` serves
|
|
10
|
-
stdio.
|
|
9
|
+
- **MCP server** — `thinger mcp` serves eight `thinger_resource_*` tools
|
|
10
|
+
over stdio.
|
|
11
11
|
|
|
12
12
|
Both share the same profiles and API layer: sign in once, use either.
|
|
13
13
|
|
|
@@ -65,25 +65,86 @@ profile unless `--profile` or `THINGER_PROFILE` names one, and
|
|
|
65
65
|
|
|
66
66
|
## Commands
|
|
67
67
|
|
|
68
|
+
Every command reads the same way: nouns, then a verb, then the ids,
|
|
69
|
+
outermost first.
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
thinger <noun> [<noun>…] <verb> [<parent ids>…] [<id>] [options]
|
|
73
|
+
```
|
|
74
|
+
|
|
68
75
|
```bash
|
|
69
|
-
thinger device list [
|
|
70
|
-
thinger device
|
|
71
|
-
thinger device create <
|
|
72
|
-
thinger device
|
|
73
|
-
thinger device
|
|
74
|
-
thinger device
|
|
75
|
-
thinger device property
|
|
76
|
-
thinger device
|
|
77
|
-
|
|
78
|
-
thinger
|
|
79
|
-
thinger
|
|
80
|
-
thinger
|
|
81
|
-
thinger
|
|
82
|
-
|
|
83
|
-
thinger product
|
|
76
|
+
thinger device list [--search sensor] [--filter product=meteo]
|
|
77
|
+
thinger device get <device> [-f connection.active]
|
|
78
|
+
thinger device create <device> [-t Generic|MQTT|HTTP|Virtual|Subdevice] [-p product] [-n name]
|
|
79
|
+
thinger device update <device> [-n name] [-s key=value …] [--from device.json]
|
|
80
|
+
thinger device delete <device> [-y]
|
|
81
|
+
thinger device set-product <device> <product>
|
|
82
|
+
thinger device property list <device>
|
|
83
|
+
thinger device property get <device> <property> [-f value.setpoint]
|
|
84
|
+
thinger device property set <device> <property> <json>
|
|
85
|
+
thinger device resource list <device>
|
|
86
|
+
thinger device resource call <device> <resource> [-s key=value …] [-f field]
|
|
87
|
+
thinger device send <device> -s temperature=21.5 # as an HTTP device
|
|
88
|
+
thinger device bucket tag list <device> <bucket>
|
|
89
|
+
|
|
90
|
+
thinger product list | get <product> | delete <product>
|
|
91
|
+
thinger product create <product> [--from product.json] # { config, profile }
|
|
92
|
+
thinger product property list|get|set|delete <product> [property] [value]
|
|
93
|
+
thinger product profile api list <product>
|
|
94
|
+
thinger product profile bucket create <product> <bucket> --from bucket.json
|
|
95
|
+
thinger product profile api call <product> <resource> [--from payload.json]
|
|
96
|
+
thinger product export <product> -o product.json
|
|
97
|
+
thinger product apply --from product.json # create or update: profile, properties
|
|
84
98
|
|
|
85
99
|
thinger bucket list
|
|
86
100
|
thinger bucket read <bucket> [-d device] [-n 10] [-m minutes] [--agg 5m --agg-type mean]
|
|
101
|
+
thinger bucket write <bucket> --from samples.ndjson # or -s temperature=21.5
|
|
102
|
+
thinger bucket export <bucket> -o data.csv [--format csv|json|arff]
|
|
103
|
+
thinger bucket export-file list <bucket>
|
|
104
|
+
|
|
105
|
+
thinger storage file list <storage> [folder]
|
|
106
|
+
thinger storage file upload <storage> ./dist [--to web]
|
|
107
|
+
thinger storage file download <storage> <path> [-o file]
|
|
108
|
+
thinger storage file delete <storage> <path> [-y]
|
|
109
|
+
|
|
110
|
+
thinger plugin call <plugin> [path] [-X post] [--from body.json]
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Every resource type the MCP server reaches has its commands, generated from
|
|
114
|
+
the same catalog, with the verbs it supports and its actions. Child types
|
|
115
|
+
nest under their parent (`device property`, `device bucket tag`,
|
|
116
|
+
`product profile api`, `project member`, `sync lock`) and server types go
|
|
117
|
+
under `admin`:
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
thinger <noun…> list [parents…] [--search text] [--filter key=value] [--count n]
|
|
121
|
+
thinger <noun…> get [parents…] <id> [-f dot.path] [-o file]
|
|
122
|
+
thinger <noun…> create [parents…] [id] [-n name] [-d text] [--from file.json] [-s key=value …]
|
|
123
|
+
thinger <noun…> update [parents…] <id> [--from file.json] [-s key=value …] [--merge]
|
|
124
|
+
thinger <noun…> delete [parents…] <id> [-y]
|
|
125
|
+
thinger <noun…> clone [parents…] <id> <new-id>
|
|
126
|
+
thinger <noun…> set [parents…] <property> <json> # properties only
|
|
127
|
+
thinger <noun…> describe # fields and examples, from the server
|
|
128
|
+
thinger <noun…> <action> [parents…] [id] [--from file.json] [-q key=value]
|
|
129
|
+
|
|
130
|
+
thinger endpoint call notify -s message=hello
|
|
131
|
+
thinger token create ci -n CI -s expire='"30d"' -s 'allow={"Device":{"*":"*"}}'
|
|
132
|
+
thinger alarm rule test overheat
|
|
133
|
+
thinger device property update boiler setpoint -s value.target=21 --merge
|
|
134
|
+
thinger asset type property set boiler max_temp 90
|
|
135
|
+
thinger admin host get-settings <host> # server types, for admins
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
`-s` values are parsed as JSON when they are (`21`, `true`, `{"a":1}`;
|
|
139
|
+
quote strings that look like numbers: `-s code='"007"'`) and dots nest
|
|
140
|
+
(`-s data.source=resource`).
|
|
141
|
+
|
|
142
|
+
Anything else the API offers, with `thinger api` (`{user}` is the account):
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
thinger api /v1/users/{user}/products/boiler/firmwares
|
|
146
|
+
thinger api -X PUT /v1/users/{user}/devices/sensor1 -s enabled=false
|
|
147
|
+
thinger api /v2/users/{user}/storages/web/files/logo.png -o logo.png
|
|
87
148
|
```
|
|
88
149
|
|
|
89
150
|
Every command takes `-j, --json` and then prints `{ ok, data }` or
|
|
@@ -190,27 +251,36 @@ claude mcp add thinger -- thinger mcp
|
|
|
190
251
|
Other hosts take the same command (`thinger`, args `["mcp"]`), or
|
|
191
252
|
`npx` with args `["-y", "@thinger-io/cli", "mcp"]`.
|
|
192
253
|
|
|
193
|
-
Tools:
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
`
|
|
207
|
-
`
|
|
208
|
-
`
|
|
209
|
-
`
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
254
|
+
Tools: `thinger_resource_describe`, `_list`, `_get`, `_create`,
|
|
255
|
+
`_update`, `_delete`, `_clone` and `_call` (actions). Each takes a `type`
|
|
256
|
+
and the record's `ids`, one key per level (`{"device": "d1"}`,
|
|
257
|
+
`{"device": "d1", "property": "setpoint"}`,
|
|
258
|
+
`{"product": "p1", "resource": "temp"}`):
|
|
259
|
+
|
|
260
|
+
- The server's resources: devices, products, buckets, dashboards,
|
|
261
|
+
endpoints, storages, asset types and groups, projects and their members,
|
|
262
|
+
tokens, alarms, claims, plugins, properties, their children, and the
|
|
263
|
+
server's administration (users, hosts, domains, brands, OAuth clients,
|
|
264
|
+
identity providers, proxies). `resource_call` runs their actions, such as
|
|
265
|
+
verifying a domain, calling an endpoint or testing an alarm rule.
|
|
266
|
+
- Data and files: `bucket_data` (list reads a bucket, create writes
|
|
267
|
+
samples), `storage_file` (a storage's files; uploads folders of this
|
|
268
|
+
machine), `device_resource` (a connected device's resources: list, and
|
|
269
|
+
the `call` action); actions `device` `send` and `overview`,
|
|
270
|
+
`product_profile_api` `call` and `plugin` `call`.
|
|
271
|
+
- `doc` (the guides for agents), `profile` (the configured servers) and the
|
|
272
|
+
`dashboard` actions `init`, `dev` and `publish`. `dev` gives an agent the
|
|
273
|
+
dev link above: with browser tools it opens the app, reads its console
|
|
274
|
+
and iterates, then publishes it once.
|
|
275
|
+
|
|
276
|
+
`resource_describe` lists the types with their ids and examples; with a
|
|
277
|
+
type it shows its fields, filter, actions, the permission each operation
|
|
278
|
+
needs and ready-to-send calls, read from the server's own API description.
|
|
279
|
+
Actions that change a lot at once (`replace_all`, a host's settings or
|
|
280
|
+
restart, removing a plugin) answer a plan and run with `confirm: true`.
|
|
213
281
|
Every tool takes an optional `profile`, and most an optional `user`.
|
|
282
|
+
`thinger mcp --read-only` (or `THINGER_MCP_READ_ONLY=1`) serves only what
|
|
283
|
+
reads: describe, list, get and the actions that change nothing.
|
|
214
284
|
|
|
215
285
|
## Shared core
|
|
216
286
|
|
package/lib/identity.js
CHANGED
|
@@ -29,9 +29,11 @@ export const thingerIdentity = {
|
|
|
29
29
|
/** Server-level guidance sent to MCP clients on `initialize`. */
|
|
30
30
|
export const mcpInstructions = `Tools to operate a Thinger.io IoT server with the permissions of the token stored in the CLI profile.
|
|
31
31
|
|
|
32
|
-
-
|
|
32
|
+
- Everything is a resource type behind eight tools: thinger_resource_list / _get / _create / _update / _delete / _clone, and thinger_resource_call for actions. Start with thinger_resource_describe without arguments: it lists the types with their ids, operations and actions and explains the platform's concepts (which data source fits each need, recipes). Each type's ids, filter, bodies, actions and ready-to-send examples are in thinger_resource_describe with that type: read it before the first call on a type.
|
|
33
|
+
- A record is located by \`ids\`, one key per level: {"device": "d1"}, {"device": "d1", "property": "setpoint"}, {"product": "p1", "resource": "temp"}. The records the tools answer carry their ids: pass them back as they are.
|
|
33
34
|
- List before acting to discover ids (thinger_resource_list with type "device", "product", "bucket"…); never guess them.
|
|
34
|
-
- Device resources (the API a connected device's firmware exposes) are
|
|
35
|
-
-
|
|
36
|
-
-
|
|
37
|
-
-
|
|
35
|
+
- Data and files are types too: a bucket's time series is "bucket_data" (list reads it, create writes samples), a storage's files "storage_file". Device resources (the API a connected device's firmware exposes) are "device_resource": list them, and run one with thinger_resource_call action "call".
|
|
36
|
+
- Guides: thinger_resource_list type "doc", then thinger_resource_get type "doc" with ids {"doc": <id>} (concepts, product-code, server-admin, dashboard-sdk…). Read the relevant one before building something new.
|
|
37
|
+
- Custom dashboards are web apps on the dashboard SDK, the npm package @thinger-io/dashboard-sdk (reference: thinger_resource_describe type "dashboard", or the guide "dashboard-sdk"). thinger_resource_call on type "dashboard": action "init" starts one (a TypeScript project from a template of the SDK), "dev" develops it on its own dev server (start the dev server first; the link opens the local app against the server with a temporary token: open it with browser tools to see it and read its console), and "publish" uploads the build folder once it works.
|
|
38
|
+
- Every tool takes an optional \`profile\` (another configured server, see thinger_resource_list type "profile") and most take \`user\` (another account, admin only).
|
|
39
|
+
- Deletes and most actions act immediately: confirm with the user before deleting, overwriting, or running an action that changes, removes or notifies. Actions that change a lot at once (replace_all, a host's settings or restart, removing a plugin) answer a plan first: show it to the user and repeat the call with confirm: true only if they agree.`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thinger-io/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "CLI for Thinger.io servers — devices, products, buckets, dashboard apps — with an MCP server for AI clients",
|
|
5
5
|
"main": "bin/thinger.js",
|
|
6
6
|
"bin": {
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"author": "Thinger.io",
|
|
39
39
|
"license": "MIT",
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@thinger-io/cli-core": "^0.
|
|
41
|
+
"@thinger-io/cli-core": "^0.5.0"
|
|
42
42
|
},
|
|
43
43
|
"type": "module",
|
|
44
44
|
"engines": {
|