(app *App)
| 47 | } |
| 48 | |
| 49 | func newSSHCmd(app *App) *cobra.Command { |
| 50 | var opts sshOptions |
| 51 | |
| 52 | sshCmd := &cobra.Command{ |
| 53 | Use: "ssh [<flags>...] [-- <ssh-flags>...] [<command>]", |
| 54 | Short: "SSH into a codespace", |
| 55 | Long: heredoc.Docf(` |
| 56 | The %[1]sssh%[1]s command is used to SSH into a codespace. In its simplest form, you can |
| 57 | run %[1]sgh cs ssh%[1]s, select a codespace interactively, and connect. |
| 58 | |
| 59 | The %[1]sssh%[1]s command will automatically create a public/private ssh key pair in the |
| 60 | %[1]s~/.ssh%[1]s directory if you do not have an existing valid key pair. When selecting the |
| 61 | key pair to use, the preferred order is: |
| 62 | |
| 63 | 1. Key specified by %[1]s-i%[1]s in %[1]s<ssh-flags>%[1]s |
| 64 | 2. Automatic key, if it already exists |
| 65 | 3. First valid key pair in ssh config (according to %[1]sssh -G%[1]s) |
| 66 | 4. Automatic key, newly created |
| 67 | |
| 68 | The %[1]sssh%[1]s command also supports deeper integration with OpenSSH using a %[1]s--config%[1]s |
| 69 | option that generates per-codespace ssh configuration in OpenSSH format. |
| 70 | Including this configuration in your %[1]s~/.ssh/config%[1]s improves the user experience |
| 71 | of tools that integrate with OpenSSH, such as Bash/Zsh completion of ssh hostnames, |
| 72 | remote path completion for %[1]sscp/rsync/sshfs%[1]s, %[1]sgit%[1]s ssh remotes, and so on. |
| 73 | |
| 74 | Once that is set up (see the second example below), you can ssh to codespaces as |
| 75 | if they were ordinary remote hosts (using %[1]sssh%[1]s, not %[1]sgh cs ssh%[1]s). |
| 76 | |
| 77 | Note that the codespace you are connecting to must have an SSH server pre-installed. |
| 78 | If the docker image being used for the codespace does not have an SSH server, |
| 79 | install it in your %[1]sDockerfile%[1]s or, for codespaces that use Debian-based images, |
| 80 | you can add the following to your %[1]sdevcontainer.json%[1]s: |
| 81 | |
| 82 | "features": { |
| 83 | "ghcr.io/devcontainers/features/sshd:1": { |
| 84 | "version": "latest" |
| 85 | } |
| 86 | } |
| 87 | `, "`"), |
| 88 | Example: heredoc.Doc(` |
| 89 | $ gh codespace ssh |
| 90 | |
| 91 | $ gh codespace ssh --config > ~/.ssh/codespaces |
| 92 | $ printf 'Match all\nInclude ~/.ssh/codespaces\n' >> ~/.ssh/config |
| 93 | `), |
| 94 | PreRunE: func(c *cobra.Command, args []string) error { |
| 95 | if opts.stdio { |
| 96 | if opts.selector.codespaceName == "" { |
| 97 | return errors.New("`--stdio` requires explicit `--codespace`") |
| 98 | } |
| 99 | if opts.config { |
| 100 | return errors.New("cannot use `--stdio` with `--config`") |
| 101 | } |
| 102 | if opts.serverPort != 0 { |
| 103 | return errors.New("cannot use `--stdio` with `--server-port`") |
| 104 | } |
| 105 | if opts.profile != "" { |
| 106 | return errors.New("cannot use `--stdio` with `--profile`") |
no test coverage detected