cloudeide 0.1.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.
Files changed (4) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +246 -0
  3. package/dist/cli.mjs +17117 -0
  4. package/package.json +57 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 CloudeIDE
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 ADDED
@@ -0,0 +1,246 @@
1
+ # cloudeide
2
+
3
+ Deploy from your terminal, and give an AI coding agent the same abilities over MCP.
4
+
5
+ ```
6
+ pnpm add -g cloudeide
7
+ cloudeide login # paste a token from Settings → API tokens
8
+ cloudeide deploy # build and publish the current directory
9
+ ```
10
+
11
+ Published to the public npm registry, so `npm i -g cloudeide`, `yarn global add
12
+ cloudeide` and `bun add -g cloudeide` all work too — pnpm is just what this
13
+ project uses.
14
+
15
+ ## Getting a token
16
+
17
+ In the CloudeIDE dashboard: **Settings → API tokens**. Choose a name and what
18
+ the token may do, and copy it — it is shown once and stored only as a hash, so
19
+ nobody, including us, can read it back.
20
+
21
+ Three scopes:
22
+
23
+ | Scope | What it allows |
24
+ |---|---|
25
+ | `deploy:read` | Projects, deployments, logs, usage, domains, variable names |
26
+ | `deploy:write` | Start deploys, roll back, create projects, set variables |
27
+ | `deploy:admin` | Delete projects and domains |
28
+
29
+ `deploy:write` implies `deploy:read`, and `deploy:admin` implies both — a token
30
+ that can deploy but not read its own logs would be useless.
31
+
32
+ A token **cannot create another token**. That is deliberate: a leaked
33
+ credential that can mint credentials cannot be contained by revoking it.
34
+
35
+ ## Commands
36
+
37
+ ```
38
+ cloudeide login Store a token for this machine
39
+ cloudeide logout Forget it
40
+ cloudeide whoami Which account, and what this token may do
41
+ cloudeide config What settings are in use, and where each came from
42
+ cloudeide server-status What the server supports
43
+
44
+ cloudeide deploy [dir] Build and publish a directory
45
+ cloudeide status [id] A deployment, or the most recent one
46
+ cloudeide logs [id] [--follow] A deployment's build log
47
+ cloudeide cancel <id> Stop a running deployment
48
+ cloudeide rollback <id> Republish an earlier deployment
49
+ cloudeide deployments Recent deployments
50
+
51
+ cloudeide projects list|create
52
+ cloudeide env list|set
53
+ cloudeide domains list
54
+ cloudeide usage
55
+
56
+ cloudeide mcp Run the MCP server on stdio
57
+ ```
58
+
59
+ `--help` on any command shows its options. `--json` on any command prints the
60
+ result as JSON.
61
+
62
+ ## Deploying
63
+
64
+ `cloudeide deploy` sends the directory's **source** — the server builds it.
65
+
66
+ Left out automatically: `node_modules`, `.git`, build caches, binaries,
67
+ symlinks, and **`.env`**. That last one matters: the server injects its own
68
+ environment variables, so a `.env` is never needed, and uploading one would put
69
+ credentials into a build log and a public bucket. Anything skipped is named in
70
+ the output rather than silently dropped.
71
+
72
+ ```
73
+ cloudeide deploy ./site --env preview # a private, expiring URL
74
+ cloudeide deploy --no-wait # start it and return the id
75
+ cloudeide deploy --dry-run # list what would be sent
76
+ cloudeide deploy --ignore fixtures,tmp # leave out more
77
+ ```
78
+
79
+ Only one deploy per account runs at a time. A second is refused with exit 8
80
+ rather than queued.
81
+
82
+ ## Scripting
83
+
84
+ **`--json` puts exactly one JSON document on stdout and nothing else** — no
85
+ progress, no warnings, no colour. Everything else goes to stderr, so
86
+ `cloudeide deployments > list.txt` captures the list and not the chatter. A
87
+ failure is JSON on stdout too, because a script parsing stdout needs to parse
88
+ the failure as well.
89
+
90
+ Exit codes are a public interface. They may be added to, never reassigned:
91
+
92
+ | Code | Meaning | What to do |
93
+ |---|---|---|
94
+ | 0 | Success | |
95
+ | 1 | Failed | Read the message |
96
+ | 2 | Wrong usage | Fix the command |
97
+ | 3 | Not authenticated | `cloudeide login` |
98
+ | 4 | Token lacks permission | Create one with more scopes |
99
+ | 5 | Not found | Check the id |
100
+ | 6 | Over a limit | Wait, or upgrade |
101
+ | 7 | Out of credits | Buy credits — waiting will not help |
102
+ | 8 | Conflicting state | A deploy is already running |
103
+ | 9 | Server unreachable | Not your fault; retry |
104
+
105
+ ```bash
106
+ if ! cloudeide deploy --json > result.json; then
107
+ case $? in
108
+ 7) echo "out of credits" ;;
109
+ 8) echo "another deploy is running" ;;
110
+ *) jq -r '.error.message' result.json ;;
111
+ esac
112
+ fi
113
+ ```
114
+
115
+ ## Configuration
116
+
117
+ Checked in this order:
118
+
119
+ 1. Flags — `--api-url`, `--token`, `--project`
120
+ 2. Environment — `CLOUDEIDE_API_URL`, `CLOUDEIDE_TOKEN`, `CLOUDEIDE_PROJECT`
121
+ 3. The config file
122
+ 4. Built-in defaults
123
+
124
+ The file lives at `$XDG_CONFIG_HOME/cloudeide/config.json`, or
125
+ `~/.config/cloudeide/config.json`, or `%APPDATA%\cloudeide` on Windows. It is
126
+ written `0600`, and narrowed if it is ever found otherwise.
127
+
128
+ `cloudeide config` reports **where each value came from**, which is the answer
129
+ to "it says I am logged in but it is using the wrong account" — nearly always
130
+ an environment variable somebody forgot.
131
+
132
+ ## Retries
133
+
134
+ Getting this wrong is worse than not retrying at all: a `POST` that timed out
135
+ may already have been processed, and repeating it can deploy twice.
136
+
137
+ - `GET` retries network failures and 5xx.
138
+ - **Any** method retries `429` and `503`, because those mean the server
139
+ explicitly did not process the request.
140
+ - Nothing else retries.
141
+
142
+ Backoff is exponential with jitter and honours `Retry-After`, capped at 20
143
+ seconds so a server asking for an hour cannot hang a CI job. When a route knows
144
+ better than its status code — "AWS is not configured here" is a correct 503 and
145
+ retrying it is pointless — the server says so and that answer wins.
146
+
147
+ ## Editors and agents
148
+
149
+ Cursor, Claude Code and Codex are all MCP hosts, so all three use the same
150
+ server. One command wires it in:
151
+
152
+ ```
153
+ cloudeide login # once per machine
154
+ cloudeide install cursor # or claude-code, or codex
155
+ cloudeide doctor # says what is wrong, if anything
156
+ ```
157
+
158
+ | Editor | Written to | `--global` writes |
159
+ | --- | --- | --- |
160
+ | Cursor | `.cursor/mcp.json` | `~/.cursor/mcp.json` |
161
+ | Claude Code | `.mcp.json` | `~/.claude.json` |
162
+ | Codex | `.codex/config.toml` | `~/.codex/config.toml` |
163
+
164
+ `--print` shows the file without writing it. `--force` replaces an existing
165
+ entry. `--name` adds a second server under a different name.
166
+
167
+ **No token is written into these files.** Every setup guide for every one of
168
+ these hosts tells you to put your credential in the config's `env` block —
169
+ and for a project-scoped file that is a credential on its way into git.
170
+ Claude Code's own docs describe `.mcp.json` as the scope shared through
171
+ version control. It is not needed: `cloudeide login` writes a 0600 file in
172
+ your config directory, the MCP server reads it at startup like every other
173
+ command, and one login covers every editor on the machine. `--with-token`
174
+ exists for a container with no home directory, and refuses a shared file
175
+ without `--force`.
176
+
177
+ **The command is written as absolute paths.** An editor spawns servers from a
178
+ GUI process whose `PATH` came from the desktop session, not from a login
179
+ shell — so `nvm`, `fnm`, `volta`, `asdf` and a user-local npm prefix are all
180
+ routinely missing from it. A config saying `"command": "cloudeide"` works when
181
+ you test it in a terminal and then fails inside the editor with no error
182
+ anywhere. Both the interpreter and the script are recorded absolutely, because
183
+ relying on the shebang just moves the same problem down one level.
184
+
185
+ That does pin the Node you had when you ran `install`. `cloudeide doctor`
186
+ checks the pin still exists and tells you to re-run with `--force` if a
187
+ version manager moved it.
188
+
189
+ ## MCP
190
+
191
+ `cloudeide mcp` speaks the Model Context Protocol on stdio. `install` writes
192
+ the config for you, but the shape is ordinary:
193
+
194
+ ```json
195
+ {
196
+ "mcpServers": {
197
+ "cloudeide": {
198
+ "command": "/absolute/path/to/node",
199
+ "args": ["/absolute/path/to/cli.mjs", "mcp"]
200
+ }
201
+ }
202
+ }
203
+ ```
204
+
205
+ Thirteen tools: `whoami`, `list_projects`, `create_project`, `deploy`,
206
+ `deployment_status`, `deployment_logs`, `list_deployments`,
207
+ `cancel_deployment`, `rollback`, `list_env_vars`, `set_env_var`,
208
+ `list_domains`, `usage` — each prefixed `cloudeide_`.
209
+
210
+ Three things shape them, all following from the fact that an agent is not a
211
+ person at a terminal:
212
+
213
+ - **It cannot wait.** `deploy` returns a deployment id immediately;
214
+ `deployment_status` is a separate call. A tool that blocked for eleven
215
+ minutes would time out in the host, leaving the agent unsure whether the
216
+ deploy is even running.
217
+ - **It cannot see.** Every result is structured JSON with the API's own field
218
+ names. `deployment_status` returns the last twenty log lines and a count;
219
+ `deployment_logs` returns everything, so status alone rarely floods the
220
+ context.
221
+ - **It retries the wrong things.** Every error says `retryable` explicitly, and
222
+ every tool description says what it costs. `deploy` says it spends credits
223
+ and does not wait; `rollback` says it changes the live site.
224
+
225
+ Tools are **not** filtered by scope. A read-only token still sees `deploy` and
226
+ gets a clear permission error naming the scope it needs — hiding it would make
227
+ an agent conclude the platform cannot deploy and invent a workaround.
228
+
229
+ ## Development
230
+
231
+ ```
232
+ pnpm install
233
+ pnpm run build # bundles to dist/cli.mjs
234
+ pnpm run typecheck
235
+ pnpm test # unit suites: args, client, collect, output, writers
236
+ pnpm pack # inspect exactly what would be published
237
+ pnpm publish # requires npm registry auth
238
+ ```
239
+
240
+ `pnpm publish` runs `prepublishOnly`, which rebuilds and runs the unit suites —
241
+ so a tarball can never be cut from a stale `dist/` or a red test run.
242
+
243
+ The suites that need a server live in `artifacts/api-server/test/live/` and run
244
+ the built binary as a subprocess against a real API and a real Postgres —
245
+ because the exit code, stdout and stderr *are* the interface, and a test that
246
+ imports the command functions would pass while the binary was unusable.