How to Automatically Change Directory on SSH Login: A Technical Guide


37 views

When working with SSH, you might want to automatically navigate to a specific directory upon login. This is particularly useful when you frequently access certain project directories on remote servers. The naive approach of using LocalCommand in ~/.ssh/config often fails with confusing errors.

The LocalCommand directive executes on your local machine before the SSH connection is established. This explains why you're getting "No such file or directory" errors - it's trying to change directories locally, not on the remote server.

# This won't work as expected
Host example.net
    LocalCommand "cd web"  # Executes locally!

Here are several effective ways to achieve automatic directory changing on SSH login:

1. Using Remote Command

Add this to your ~/.ssh/config:

Host example.net
    RemoteCommand cd /path/to/your/directory && exec \$SHELL
    RequestTTY force

2. Modifying Shell Startup Files

Edit the remote server's ~/.bashrc or ~/.bash_profile:

# For interactive SSH sessions
if [[ -n $SSH_CONNECTION ]]; then
    cd /path/to/your/directory
fi

3. Using SSH ForcedCommand

For more control, create a wrapper script:

#!/bin/bash
cd /path/to/your/directory
exec bash -i

Then in ~/.ssh/config:

Host example.net
    RemoteCommand /path/to/wrapper_script
    RequestTTY force

For different directories based on connection source:

if [[ "$SSH_CLIENT" =~ "192.168.1.100" ]]; then
    cd /projects/client_a
elif [[ "$SSH_CLIENT" =~ "10.0.0.5" ]]; then
    cd /projects/client_b
fi
  • Always use absolute paths for reliability
  • Check file permissions on the remote directory
  • Verify your shell startup files are actually being sourced
  • Test with ssh -v for debugging connection issues

When attempting to automatically change directories upon SSH login, many developers first try using LocalCommand in their SSH config. However, this approach fails because:

Host example.com
    LocalCommand "cd /path/to/directory"

The key reasons this doesn't work:

  • LocalCommand executes on the client machine, not the remote server
  • Even with absolute paths, you'll encounter permission or I/O errors
  • The command executes in a separate shell that terminates immediately

The most reliable method is to configure the remote shell's initialization files:

# For Bash users:
echo "cd /path/to/your/directory" >> ~/.bashrc

# For Zsh users:
echo "cd /path/to/your/directory" >> ~/.zshrc

This approach works because:

  • Shell initialization files are executed after login
  • The directory change persists for the entire session
  • Works consistently across different SSH clients

For more control, combine SSH command with shell config:

# In your ~/.ssh/config
Host myserver
    HostName example.com
    User myuser
    RequestTTY yes
    RemoteCommand bash --init-file <(echo "source ~/.bashrc; cd /path/to/directory")

Benefits of this hybrid approach:

  • Doesn't modify existing shell configuration
  • Allows per-connection directory specification
  • Maintains all shell initialization features

When you need a one-time directory change:

ssh -t user@example.com "cd /path/to/directory && exec \$SHELL -l"

This command:

  • Changes to the specified directory immediately
  • Starts an interactive shell in that location
  • Doesn't require any configuration changes

Create multiple SSH config entries for different directories:

Host project1
    HostName example.com
    User dev
    RemoteCommand bash -c "cd /projects/webapp && exec bash -l"

Host project2
    HostName example.com
    User dev
    RemoteCommand bash -c "cd /projects/api && exec bash -l"

Now you can simply use:

ssh project1  # Automatically goes to /projects/webapp
ssh project2  # Automatically goes to /projects/api

Permission Issues: Ensure the target directory exists and is accessible:

ssh user@host "test -d /path/to/directory || echo 'Directory missing'"

Interactive Shell Problems: If commands exit immediately, force TTY allocation:

ssh -t user@host "cd /path && exec \$SHELL"

Environment Variables: Preserve them during directory change:

ssh -t user@host "cd /path && env -i HOME=$HOME USER=$USER \$SHELL -l"