Skip to content

feat(ssh): add --instance option to target a running instance by ID - #1123

Merged
hsablonniere merged 1 commit into
CleverCloud:masterfrom
mehdi653:feat/ssh-instance-option
Sep 23, 2026
Merged

hsablonniere merged 1 commit into
CleverCloud:masterfrom
mehdi653:feat/ssh-instance-option

Conversation

@mehdi653

@mehdi653 mehdi653 commented Aug 12, 2026 •

Copy link
Copy Markdown
Contributor

Summary

When several instances are running, clever ssh currently requires an interactive prompt and fails in non-interactive mode. This adds --instance instance-id so users and scripts can target a specific running instance without a prompt.

Instance IDs are used rather than instance numbers, which are not stable across deployments (per hsablonniere feedback on #1067). Support for number / any / all selection is left for a follow-up (judu).

Refs #1067

Change

  • Add --instance instance-id option to clever ssh
  • When set, select that running instance and skip the interactive prompt
  • When the ID does not match a running instance of the app, fail with a clear error
  • Update ssh docs and generated skill reference

Spec notes

  • Selection key is the Clever Cloud instance ID (not the ephemeral instance number)
  • Existing behavior is unchanged when --instance is omitted (single instance auto-select, multi-instance TTY prompt, non-TTY failure)
  • Works with -c / --command for non-interactive one-shot commands

Test plan

  • run validate on this branch
  • valid instance id connects without prompt
  • bogus instance id fails with a clear error
  • multi-instance non-TTY with option succeeds
  • multi-instance non-TTY without option still fails as before

E2E results (2026-08-13)

Tested against a real Clever Cloud Node app with the local CLI from this PR checkout (HOME/.local/bin clever, which exposes --instance).

App: ssh-instance-e2e-1123 (app_99596987-df36-4925-8bab-26f50b2e1ba5), scaled to 2 instances, dedicated ed25519 key registered on the account.

  1. Valid instance id, agent disabled, remote echo:
    -> OK, exit 0, no prompt
  2. Bogus instance id:
    -> clear error: Instance bogus is not a running instance of this application, exit 1
  3. Non-TTY multi-instance WITH --instance (stdin closed) on the second instance id:
    -> OK, exit 0
  4. Non-TTY multi-instance WITHOUT --instance:
    -> clear error: Multiple instances are running. Cannot select in non-interactive mode., exit 1

Also: validate passed on 5898785 (lint, prettier, typecheck, docs:check). Working tree clean; no docs rewrite and no force-push needed.

Test app and temporary SSH key were deleted after the run.

@mehdi653
mehdi653 requested a review from a team as a code owner August 12, 2026 22:39
@davlgd
davlgd force-pushed the feat/ssh-instance-option branch from 5898785 to ff49a42 Compare September 10, 2026 17:41

@davlgd davlgd left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this! Just a nitpick here

Comment thread src/commands/ssh/ssh.command.js Outdated
}),
instance: defineOption({
name: 'instance',
schema: z.string().optional(),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

z.string() accepts the empty string, so a missing value reaches the handler and reports Instance is not a running instance of this application, with a gap where the ID should be. It happens with --instance alone, and with --instance --command "hostname", where the flag takes no value and the command still runs.

Suggested change
schema: z.string().optional(),
schema: z.string().min(1).optional(),

Both are then rejected at parse time instead. if (instance != null) stays as it is: cliparse passes null when the option is absent, and the loose check already covers that.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, thanks! Pushed z.string().min(1).optional() so an empty --instance fails at parse time.

With several instances running, `clever ssh` could only pick one through an
interactive prompt and failed in non-interactive mode, so scripts had no way
to reach a given instance. Selection uses the instance ID because instance
numbers change across deployments.

Selecting by number, `any` or `all`, as suggested in CleverCloud#1067, is left for
a follow-up.
@hsablonniere
hsablonniere force-pushed the feat/ssh-instance-option branch from ff74ffe to 764b5b0 Compare September 23, 2026 16:21
@hsablonniere

Copy link
Copy Markdown
Member

Thanks a lot @mehdi653 for this contribution!

To keep the history clean before merging, we squashed your commits into a single one and reworked the commit message wording (you're still the author). We also replaced Fixes #1067 with Refs #1067 in the description, so the issue stays open: we'll handle the rest (selection by number, any / all) in another PR.

@hsablonniere hsablonniere left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👍

@hsablonniere
hsablonniere merged commit adb7cec into CleverCloud:master Sep 23, 2026
5 of 6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants