
Security News
Re-Enabled GitHub Actions Expose Thousands of Repositories to Mini Shai-Hulud
Two compromised GitHub Actions were re-enabled with malicious tags intact, exposing thousands of downstream repositories to Mini Shai-Hulud.
Deploy from your terminal, and give an AI coding agent the same abilities over MCP.
Deploy from your terminal, and give an AI coding agent the same abilities over MCP.
pnpm add -g cloudeide
cloudeide login # paste a token from Settings → API tokens
cloudeide deploy # build and publish the current directory
Published to the public npm registry, so npm i -g cloudeide, yarn global add cloudeide and bun add -g cloudeide all work too — pnpm is just what this
project uses.
In the CloudeIDE dashboard: Settings → API tokens. Choose a name and what the token may do, and copy it — it is shown once and stored only as a hash, so nobody, including us, can read it back.
Three scopes:
| Scope | What it allows |
|---|---|
deploy:read | Projects, deployments, logs, usage, domains, variable names |
deploy:write | Start deploys, roll back, create projects, set variables |
deploy:admin | Delete projects and domains |
deploy:write implies deploy:read, and deploy:admin implies both — a token
that can deploy but not read its own logs would be useless.
A token cannot create another token. That is deliberate: a leaked credential that can mint credentials cannot be contained by revoking it.
cloudeide login Store a token for this machine
cloudeide logout Forget it
cloudeide whoami Which account, and what this token may do
cloudeide config What settings are in use, and where each came from
cloudeide server-status What the server supports
cloudeide deploy [dir] Build and publish a directory
cloudeide status [id] A deployment, or the most recent one
cloudeide logs [id] [--follow] A deployment's build log
cloudeide cancel <id> Stop a running deployment
cloudeide rollback <id> Republish an earlier deployment
cloudeide deployments Recent deployments
cloudeide projects list|create
cloudeide env list|set
cloudeide domains list
cloudeide usage
cloudeide mcp Run the MCP server on stdio
--help on any command shows its options. --json on any command prints the
result as JSON.
cloudeide deploy sends the directory's source — the server builds it.
Left out automatically: node_modules, .git, build caches, binaries,
symlinks, and .env. That last one matters: the server injects its own
environment variables, so a .env is never needed, and uploading one would put
credentials into a build log and a public bucket. Anything skipped is named in
the output rather than silently dropped.
cloudeide deploy ./site --env preview # a private, expiring URL
cloudeide deploy --no-wait # start it and return the id
cloudeide deploy --dry-run # list what would be sent
cloudeide deploy --ignore fixtures,tmp # leave out more
Only one deploy per account runs at a time. A second is refused with exit 8 rather than queued.
--json puts exactly one JSON document on stdout and nothing else — no
progress, no warnings, no colour. Everything else goes to stderr, so
cloudeide deployments > list.txt captures the list and not the chatter. A
failure is JSON on stdout too, because a script parsing stdout needs to parse
the failure as well.
Exit codes are a public interface. They may be added to, never reassigned:
| Code | Meaning | What to do |
|---|---|---|
| 0 | Success | |
| 1 | Failed | Read the message |
| 2 | Wrong usage | Fix the command |
| 3 | Not authenticated | cloudeide login |
| 4 | Token lacks permission | Create one with more scopes |
| 5 | Not found | Check the id |
| 6 | Over a limit | Wait, or upgrade |
| 7 | Out of credits | Buy credits — waiting will not help |
| 8 | Conflicting state | A deploy is already running |
| 9 | Server unreachable | Not your fault; retry |
if ! cloudeide deploy --json > result.json; then
case $? in
7) echo "out of credits" ;;
8) echo "another deploy is running" ;;
*) jq -r '.error.message' result.json ;;
esac
fi
Checked in this order:
--api-url, --token, --projectCLOUDEIDE_API_URL, CLOUDEIDE_TOKEN, CLOUDEIDE_PROJECTThe file lives at $XDG_CONFIG_HOME/cloudeide/config.json, or
~/.config/cloudeide/config.json, or %APPDATA%\cloudeide on Windows. It is
written 0600, and narrowed if it is ever found otherwise.
cloudeide config reports where each value came from, which is the answer
to "it says I am logged in but it is using the wrong account" — nearly always
an environment variable somebody forgot.
Getting this wrong is worse than not retrying at all: a POST that timed out
may already have been processed, and repeating it can deploy twice.
GET retries network failures and 5xx.429 and 503, because those mean the server
explicitly did not process the request.Backoff is exponential with jitter and honours Retry-After, capped at 20
seconds so a server asking for an hour cannot hang a CI job. When a route knows
better than its status code — "AWS is not configured here" is a correct 503 and
retrying it is pointless — the server says so and that answer wins.
Cursor, Claude Code and Codex are all MCP hosts, so all three use the same server. One command wires it in:
cloudeide login # once per machine
cloudeide install cursor # or claude-code, or codex
cloudeide doctor # says what is wrong, if anything
| Editor | Written to | --global writes |
|---|---|---|
| Cursor | .cursor/mcp.json | ~/.cursor/mcp.json |
| Claude Code | .mcp.json | ~/.claude.json |
| Codex | .codex/config.toml | ~/.codex/config.toml |
--print shows the file without writing it. --force replaces an existing
entry. --name adds a second server under a different name.
No token is written into these files. Every setup guide for every one of
these hosts tells you to put your credential in the config's env block —
and for a project-scoped file that is a credential on its way into git.
Claude Code's own docs describe .mcp.json as the scope shared through
version control. It is not needed: cloudeide login writes a 0600 file in
your config directory, the MCP server reads it at startup like every other
command, and one login covers every editor on the machine. --with-token
exists for a container with no home directory, and refuses a shared file
without --force.
The command is written as absolute paths. An editor spawns servers from a
GUI process whose PATH came from the desktop session, not from a login
shell — so nvm, fnm, volta, asdf and a user-local npm prefix are all
routinely missing from it. A config saying "command": "cloudeide" works when
you test it in a terminal and then fails inside the editor with no error
anywhere. Both the interpreter and the script are recorded absolutely, because
relying on the shebang just moves the same problem down one level.
That does pin the Node you had when you ran install. cloudeide doctor
checks the pin still exists and tells you to re-run with --force if a
version manager moved it.
cloudeide mcp speaks the Model Context Protocol on stdio. install writes
the config for you, but the shape is ordinary:
{
"mcpServers": {
"cloudeide": {
"command": "/absolute/path/to/node",
"args": ["/absolute/path/to/cli.mjs", "mcp"]
}
}
}
Thirteen tools: whoami, list_projects, create_project, deploy,
deployment_status, deployment_logs, list_deployments,
cancel_deployment, rollback, list_env_vars, set_env_var,
list_domains, usage — each prefixed cloudeide_.
Three things shape them, all following from the fact that an agent is not a person at a terminal:
deploy returns a deployment id immediately;
deployment_status is a separate call. A tool that blocked for eleven
minutes would time out in the host, leaving the agent unsure whether the
deploy is even running.deployment_status returns the last twenty log lines and a count;
deployment_logs returns everything, so status alone rarely floods the
context.retryable explicitly, and
every tool description says what it costs. deploy says it spends credits
and does not wait; rollback says it changes the live site.Tools are not filtered by scope. A read-only token still sees deploy and
gets a clear permission error naming the scope it needs — hiding it would make
an agent conclude the platform cannot deploy and invent a workaround.
pnpm install
pnpm run build # bundles to dist/cli.mjs
pnpm run typecheck
pnpm test # unit suites: args, client, collect, output, writers
pnpm pack # inspect exactly what would be published
pnpm publish # requires npm registry auth
pnpm publish runs prepublishOnly, which rebuilds and runs the unit suites —
so a tarball can never be cut from a stale dist/ or a red test run.
The suites that need a server live in artifacts/api-server/test/live/ and run
the built binary as a subprocess against a real API and a real Postgres —
because the exit code, stdout and stderr are the interface, and a test that
imports the command functions would pass while the binary was unusable.
FAQs
Deploy from your terminal, and give an AI coding agent the same abilities over MCP.
The npm package cloudeide receives a total of 0 weekly downloads. As such, cloudeide popularity was classified as not popular.
We found that cloudeide demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.

Security News
Two compromised GitHub Actions were re-enabled with malicious tags intact, exposing thousands of downstream repositories to Mini Shai-Hulud.

Research
/Security News
A malicious Firefox extension fetches its payload after installation to evade detection, steal Google session cookies, and automate account takeover.

Research
/Security News
The compromise affects MemTensor's MemOS, an open source memory framework for large language models (LLMs) and AI agents. Both npm package @memtensor/memos-cloud-openclaw-plugin and the PyPI package MemoryOS are compromised. They drop cross-platform Go binaries that exfiltrate developer secrets.