| title | CLI |
|---|---|
| description | Validate and migrate smartcloud configs from the command line. |
The smartcloud command runs the same code as the action on your own machine. Use it to check a config before you push it, convert a v1 config, see what a run would do without doing it, and find out why a repository is not set up right. Nothing it does writes to GitHub.
| Command | Use it to | Needs a token |
|---|---|---|
validate |
Check a config and every preset it extends. | Only for extends |
migrate |
Convert a v1 .github/config.json to v2 YAML. |
No |
check-commit |
Check a commit message for DCO sign-off and AI attribution, as a git hook. | No |
dry-run |
Run every feature against a real pull request, issue or event, writing nothing. | Yes |
plan settings |
List the repository settings the config would apply. | Yes |
sync |
Render the files the sync feature would write into a local folder. | Yes |
doctor |
Check the token, config, presets, private actions, secrets and variables. | Yes |
You need Node 24 or later.
From the first v2 release, the CLI and the [MCP server](/mcp-server) are published together as `@resnovas/smartcloud`:```sh
npx @resnovas/smartcloud --help
# or install it once
npm install --global @resnovas/smartcloud
smartcloud --help
```
```sh
git clone https://github.com/Resnovas/smartcloud.git
cd smartcloud
pnpm install
pnpm nx run @resnovas/smartcloud:build
node apps/cli/dist/main.js --help
```
Inside the checkout, `pnpm run cli <command>` does the same.
The examples below write smartcloud for whichever you use. smartcloud --version prints the version, and smartcloud <command> --help lists a command's options.
A command that fails prints one line starting smartcloud: on stderr and exits with code 1. Any other result exits with code 0.
smartcloud validate [path]Checks a config and every preset it extends, merges them under the locked preset rules, and prints where the config was built from and any migration warnings.
Without a path, it uses the first of .github/smartcloud.yml, .github/smartcloud.yaml and .github/config.json in the current directory.
$ smartcloud validate
.github/smartcloud.yml is a valid smartcloud config.
Built from: Resnovas/.github/smartcloud/house.yml@main, .github/smartcloud.yml
Validation is strict: an unknown key or invalid value in the config or any preset is an error, where a run only drops it with a warning. A config that fails prints one line starting smartcloud: and exits with code 1.
smartcloud migrate [input] [--out <file>]Converts a v1 JSON config (default .github/config.json) to v2 YAML, and prints a warning for every v1 key it does not carry over. The output starts with a schema hint for editors, and is proven to decode before it is written.
| Option | Meaning |
|---|---|
--out, -o |
Write the YAML to this file instead of printing it. |
A v2 file given to migrate is rewritten unchanged. See Migrating from v1 for worked examples.
smartcloud check-commit <file> [--author-name <name> --author-email <email>] [--config <file>]Checks a commit message against the DCO sign-off and AI attribution rules before the commit exists, and exits with code 1 when any rule is broken. The author defaults to git's own, and the config to the repository's in the working directory, or smartcloud's defaults when there is none. Comment lines are ignored, as git ignores them.
Use it as a git commit-msg hook, so a commit that would fail the pull request check is stopped locally:
#!/bin/sh
exec npx --yes @resnovas/smartcloud check-commit "$1"smartcloud dry-run --repo <owner/name> (--pr <n> | --issue <n> | --event <event>) [--config <file>] [--features <a,b>]Runs every feature against a real pull request, issue or repository event, through the dry-run layer. It reads GitHub as the action would, then prints the job summary and every write the run would make. It never writes.
| Option | Meaning |
|---|---|
--repo |
The repository, as owner/name. |
--pr, --issue |
Simulate this pull request or issue, built from its current state on GitHub. |
--event |
Simulate schedule, push or workflow_dispatch. |
--config |
Use this local config file instead of the repository's own config on its default branch. |
--features |
Only these features, comma separated. An empty list, such as --features ,, runs every feature. |
Give exactly one of --pr, --issue or --event.
# What would smartcloud do on pull request 42, with the config I am editing?
smartcloud dry-run --repo my-org/my-repo --pr 42 --config .github/smartcloud.yml
# What would the daily sweep do, stale and lock only?
smartcloud dry-run --repo my-org/my-repo --event schedule --features stale,locksmartcloud plan settings --repo <owner/name> [--config <file>]Prints every repository settings step the config would apply, with its request, without applying any of them. Use it before merging a change to the settings section, since those steps change the repository for everyone.
smartcloud plan settings --repo my-org/my-repo --config .github/smartcloud.ymlIt reads only the repository itself, so any token that can read the repository works. A config without a settings section prints no steps. When a run would ignore part of the settings section, such as a merge queue method that conflicts with the rest of the ruleset, the plan lists it after the steps under "Ignored, so not applied", with the reason.
smartcloud sync --repo <owner/name> --out <dir> [--config <file>]smartcloud sync --repo my-org/my-repo --out /tmp/sync-previewRenders the files the sync feature would write to the repository into a local directory, with each file's status (added, updated, made executable or unchanged), and lists any conflicts. Nothing is sent to GitHub. A config without a sync section fails with the config has no sync section. Every file is checked before any is written: one that would land outside the directory, or be written through a symlink inside it, stops the command with nothing written.
smartcloud doctor --repo <owner/name> [--config <file>]Checks what smartcloud needs to run on a repository, with the token the CLI finds, and prints one line per check. It exits with code 1 when any check fails. Nothing is written.
| Check | Fails or warns when |
|---|---|
token, token scopes |
A classic or OAuth token lacks the repo scope (fails) or the workflow scope (warns). |
check runs |
The token is a personal or OAuth token, which GitHub never lets create check runs, or a workflow passes a secret to smartcloud as its token (warns: if that secret is a personal access token, the smartcloud check fails). Use a GitHub App token or the workflow token. |
repository |
The token cannot read the repository (fails, and the remaining checks are skipped), or is not an admin, so the settings feature cannot run (warns). |
config, presets |
The config, or any preset it extends, cannot be read or is invalid (fails). A private preset in another repository is noted, because runs with the workflow token skip it. |
actions access |
A workflow uses an action or reusable workflow from a private repository whose Actions access (Settings > Actions > General > Access) does not allow it (fails). Reading the access level needs admin access to that repository; without it, the check warns. |
workflows |
The workflow files under .github/workflows cannot be read (warns), so the checks that read them are skipped. |
secrets, variables |
A workflow reads a secret or variable that the repository, its organisation and its environments do not have (fails). Listing them needs admin access; when a list cannot be read, the check warns instead. |
Run it with your own token to check the repository, or with the token a workflow passes to smartcloud to check that token:
$ smartcloud doctor --repo Resnovas/example
smartcloud doctor for Resnovas/example:
ok token: an OAuth token, such as the GitHub CLI's with scopes: repo, workflow, read:org
warning check runs: this token cannot create check runs, so the smartcloud check fails in a workflow that passes it; ...
ok repository: the token is an admin of Resnovas/example, so every feature can run
ok config: the config and its 1 preset(s) resolve: Resnovas/private-presets/smartcloud/house.yml@main, .github/smartcloud.yml
ok presets: Resnovas/private-presets is private: runs with the workflow token, such as pull requests from forks and Dependabot, skip its presets
ok workflows: read 4 workflow file(s)
ok actions access: public, so usable from any workflow: actions/checkout, actions/setup-node
FAIL actions access: Resnovas/private-presets is private and its Actions access is none, so .github/workflows/house-graphify.yml cannot use its actions or reusable workflows; ...
FAIL secrets: missing POSTHOG_CLI_TOKEN (read by .github/workflows/house-release.yml); ...
ok variables: every variable the workflows read exists: RESNOVAS_BOT_APP_ID
2 failure(s), 1 warning(s).
Workflows are read line by line rather than parsed: every uses: of another repository and every secrets.NAME or vars.NAME outside a comment line counts, including one guarded by a condition.
dry-run, plan settings, sync and doctor always read GitHub. validate needs a token only to read presets named in extends, so validating a config without presets works offline. When it does need one, it uses GITHUB_TOKEN if set, and otherwise the token of the signed-in GitHub CLI (gh auth token). The token is never printed.