AI Agent Notes · 2026-07-06

Local AI Agents over SSH Keys: A Safer Workflow for Claude Code, Codex, and OpenCode

Local AI Agents over SSH Keys: A Safer Workflow for Claude Code, Codex, and OpenCode

Claude Code, Codex, OpenCode, and similar AI coding agents are becoming common tools for reading projects, modifying code, checking logs, writing tests, and debugging production-like issues.

If the whole project is local, the workflow is simple:

Agent works in the local repo → you review git diff → you run tests → you decide whether to keep the change.

But many real projects are not purely local.

Your service may run on a VPS. Logs may live on a server. Docker Compose may be remote. Nginx, Caddy, systemd, or environment-specific configuration may only exist on a remote machine.

So the natural question is:

Can a local AI agent help me inspect or operate my own server?

Yes, but the safe workflow matters.

The unsafe workflow is:

Paste the root password, SSH private key, or production database password into the model.

Do not do that.

A safer workflow is:

The agent runs locally;
The SSH private key stays on your machine;
The server only receives the public key;
The local machine uses an SSH alias;
The server uses a low-privilege user;
The agent is limited to a fixed project directory;
High-risk commands require explicit confirmation.

This article gives a practical workflow you can adapt.

Use this only on servers you own or are authorized to manage. Do not use it on unauthorized systems, and do not practice directly on a production server without a rollback path.

Two Different Patterns

People often mix up two different patterns.

Pattern A: Run the Agent on the Remote Machine

In this pattern, you SSH into the server first, then start the agent CLI inside the remote project directory.

ssh ai-devbox
cd /srv/agent-work/project
claude

or:

ssh ai-devbox
cd /srv/agent-work/project
opencode

The agent process runs on the server and directly reads or writes the remote file system.

Pattern B: Run the Agent Locally and Let It Use SSH

This article focuses on Pattern B.

Local AI agent
→ local shell
→ ssh ai-devbox
→ remote low-privilege user
→ fixed project directory

The agent does not need to see your private key. It only uses your local SSH configuration.

For example, it can run:

ssh ai-devbox "whoami && hostname && uptime"

or:

ssh ai-devbox "cd /srv/agent-work/project && git status"

The key idea is:

The private key stays local. The agent only invokes ssh through the local shell.

Recommended Architecture

A minimal setup looks like this:

Your laptop
  ├─ Claude Code / Codex / OpenCode
  ├─ ~/.ssh/config
  └─ ~/.ssh/id_xxx_agent      # private key, local only

Remote server
  ├─ agent user               # low privilege
  ├─ ~/.ssh/authorized_keys    # public key only
  └─ /srv/agent-work/project

This gives you several advantages:

  1. The private key does not leave your machine.
  2. The agent does not need root access by default.
  3. The remote working directory can be restricted to a project path.
  4. Changes can be reviewed with git status, git diff, logs, and tests.
  5. Access can be revoked by removing the public key or disabling the user.

Step 1: Create a Low-Privilege Server User

Do not start with root.

Create a dedicated user for agent-assisted work:

sudo useradd -m -s /bin/bash agent
sudo mkdir -p /srv/agent-work
sudo chown -R agent:agent /srv/agent-work

Create or assign a project directory:

sudo mkdir -p /srv/agent-work/project
sudo chown -R agent:agent /srv/agent-work/project

At the beginning, avoid granting sudo.

A better rule is:

The agent may read files, inspect logs, modify project code, and run tests.
Anything involving sudo, services, databases, or production configuration must be confirmed by the human.

Step 2: Generate a Dedicated SSH Key Locally

Generate a key specifically for this agent-server workflow.

Example:

ssh-keygen -t ed25519 \
  -C "agent-devbox" \
  -f ~/.ssh/id_ed25519_agent

Important note:

ed25519 is only an example.
The SSH key type does not have to be fixed.

Depending on server compatibility or team security policy, you may use RSA, ECDSA, or another accepted key type.

The important rules are:

The generated files look like this:

~/.ssh/id_ed25519_agent      # private key, local only
~/.ssh/id_ed25519_agent.pub  # public key, server side

You may also add a passphrase and use ssh-agent for additional protection.

Step 3: Install the Public Key on the Server

If ssh-copy-id is available:

ssh-copy-id -i ~/.ssh/id_ed25519_agent.pub agent@SERVER_IP

Or manually:

sudo mkdir -p /home/agent/.ssh
sudo nano /home/agent/.ssh/authorized_keys
sudo chown -R agent:agent /home/agent/.ssh
sudo chmod 700 /home/agent/.ssh
sudo chmod 600 /home/agent/.ssh/authorized_keys

Remember:

Step 4: Create a Local SSH Alias

Edit your local SSH config:

nano ~/.ssh/config

Add:

Host ai-devbox
  HostName 1.2.3.4
  User agent
  IdentityFile ~/.ssh/id_ed25519_agent
  IdentitiesOnly yes
  ServerAliveInterval 30

Test it manually:

ssh ai-devbox

Then check:

whoami
hostname
pwd

Ideally, whoami should show:

agent

If it shows root, you have not created a safe default boundary yet.

Step 5: Start with Read-Only Checks

The first agent task should not be deployment.

Start with read-only commands:

ssh ai-devbox "whoami && hostname && uptime"

Then inspect the project:

ssh ai-devbox "cd /srv/agent-work/project && pwd && git status"

Then check recent commits:

ssh ai-devbox "cd /srv/agent-work/project && git log --oneline -5"

Only after this works should you let the agent read files, inspect logs, run tests, propose patches, or modify non-critical files.

Step 6: Prompt the Local Agent Clearly

Do not simply say:

Check my server.

That instruction is too broad.

A better prompt:

You are a local development agent.

You may access my server through ssh ai-devbox.
You may only work inside /srv/agent-work/project.

Start with read-only checks:
- whoami
- hostname
- pwd
- git status
- recent logs

Do not delete files.
Do not modify production configuration.
Do not operate the database.
Do not run sudo, rm -rf, systemctl restart, or docker compose down without asking first.

If a high-risk command seems necessary, stop and explain:
1. why it is needed;
2. what it may affect;
3. whether there is a safer alternative;
4. how to roll back.

Before modifying anything, provide a plan.
Make only one small change at a time.
After changing files, show git diff.
Do not deploy or restart services without my confirmation.

The goal is not merely to make the agent polite. The goal is to define an operational boundary.

Step 7: Use an Env File Plus a Skill File

If you operate servers with agents frequently, do not repeat all rules every time.

But do not hardcode every server detail into the skill either.

A better pattern is to split configuration and behavior:

.agent-server.env       # server/project-specific values
ssh-server-ops-skill.md # reusable behavior rules

This lets you reuse the same skill across multiple projects. You change the env file, not the rules.

Configuration: .agent-server.env

Create a .agent-server.env file in the project root or in your agent working directory:

# This file stores connection aliases and project paths.
# It must not contain SSH private keys or production secrets.

AGENT_SSH_HOST=ai-devbox
AGENT_REMOTE_USER=agent
AGENT_PROJECT_PATH=/srv/agent-work/project
AGENT_ALLOWED_PATH_PREFIX=/srv/agent-work

# Read-only checks
AGENT_READONLY_CHECK_1=whoami && hostname && uptime
AGENT_READONLY_CHECK_2=cd /srv/agent-work/project && pwd && git status
AGENT_READONLY_CHECK_3=cd /srv/agent-work/project && git log --oneline -5

# Optional project-specific commands
AGENT_LOG_CMD=cd /srv/agent-work/project && tail -n 200 logs/app.log
AGENT_TEST_CMD=cd /srv/agent-work/project && npm test
AGENT_DIFF_CMD=cd /srv/agent-work/project && git diff --stat && git diff

# These commands are not always forbidden, but require confirmation first.
AGENT_CONFIRM_COMMANDS=sudo,rm,chmod -R,chown -R,systemctl restart,docker compose down,database migration

Do not put secrets in this file.

Avoid storing:

If a command may reveal secrets, instruct the agent to check whether the value exists, not to print the value.

Reusable Rules: ssh-server-ops-skill.md

Save the following as ssh-server-ops-skill.md, AGENTS.md, CLAUDE.md, or another rules file supported by your tool.

# SSH Server Ops Skill

## Goal

Safely operate an authorized remote server project through a local SSH alias.

This skill only applies to servers explicitly authorized by the user.
Do not connect to unknown hosts, scan networks, or access unauthorized resources.

## Configuration Source

First read `.agent-server.env`.

Do not hardcode Host, Project path, test command, or log command in this skill.
If the env file is missing or a required field is empty, ask the user instead of guessing.

Use these fields:

- `AGENT_SSH_HOST`: SSH alias, for example `ai-devbox`;
- `AGENT_PROJECT_PATH`: remote project directory;
- `AGENT_ALLOWED_PATH_PREFIX`: allowed remote path prefix;
- `AGENT_READONLY_CHECK_*`: read-only check commands;
- `AGENT_LOG_CMD`: log inspection command;
- `AGENT_TEST_CMD`: test command;
- `AGENT_DIFF_CMD`: diff command;
- `AGENT_CONFIRM_COMMANDS`: commands requiring confirmation.

## Default Flow

1. Read `.agent-server.env` and summarize the host and project path to be used.
2. Run read-only checks first:
   - `ssh $AGENT_SSH_HOST "$AGENT_READONLY_CHECK_1"`
   - `ssh $AGENT_SSH_HOST "$AGENT_READONLY_CHECK_2"`
   - `ssh $AGENT_SSH_HOST "$AGENT_READONLY_CHECK_3"`
3. Confirm the remote user is not root and the working path is under `AGENT_ALLOWED_PATH_PREFIX`.
4. Summarize the current state.
5. Provide a change plan.
6. Make only one small change at a time.
7. Run `AGENT_TEST_CMD` after changes. If it is empty, ask the user for the test command.
8. Run `AGENT_DIFF_CMD` and show a diff summary.
9. If deployment is needed, explain the command, impact, and rollback plan first.
10. Deploy or restart services only after user confirmation.

## Reply Format

Use this structure:

1. Current check result;
2. Env configuration summary;
3. Planned action;
4. Files or services that may be affected;
5. Whether high-risk commands are involved;
6. Execution result;
7. `git diff` summary;
8. Rollback method;
9. Suggested next step.

## Allowed Operations

- Read project files;
- Read non-sensitive logs;
- Run read-only checks defined in env;
- Run `git status`, `git diff`, and `git log`;
- Run the test command defined in env;
- Modify project code;
- Provide a plan before modification and show diff afterward.

## Forbidden Operations

- Do not read, output, or copy SSH private keys;
- Do not print secret values from `.env` files;
- Do not use root by default;
- Do not operate outside `AGENT_ALLOWED_PATH_PREFIX`;
- Do not run `rm -rf /`;
- Do not operate production databases directly;
- Do not modify secrets, payment, authentication, or production environment files without confirmation;
- Do not restart services without confirmation;
- Do not perform destructive actions without backup or rollback.

## High-Risk Commands

Ask the user before running commands listed in `AGENT_CONFIRM_COMMANDS`, including:

- `sudo`
- `rm`
- `chmod -R`
- `chown -R`
- `systemctl restart`
- `docker compose down`
- database migrations
- deleting logs or backups
- modifying Nginx / Caddy / systemd configuration
- modifying `.env`, secret, payment, or auth configuration

## Rollback Requirement

If code or configuration is modified, explain the rollback method, such as:

- Git rollback: `git checkout -- <file>`;
- config rollback: restore a backup file;
- deployment rollback: switch back to the previous image or version;
- data-related operation: back up first, do not execute automatically.

This pattern separates what changes from what should remain stable:

env file = host, path, commands, project-specific values
skill file = safety rules, workflow, confirmation boundaries

Example Tasks

Read Logs Without Changing Anything

Use the SSH Server Ops Skill.
Read .agent-server.env first.
Through AGENT_SSH_HOST, inspect recent application errors.
Only run read-only commands.
Do not modify files or restart services.
Summarize the three most likely causes and the files to inspect next.

Modify a Test Environment

Use the SSH Server Ops Skill.
Read .agent-server.env first.
Enter AGENT_PROJECT_PATH.
Run read-only checks.
Propose a minimal change plan.
Wait for my confirmation before editing.
After editing, run AGENT_TEST_CMD and show AGENT_DIFF_CMD output.

Deployment Pre-Check

Use the SSH Server Ops Skill.
Only perform a deployment pre-check.
Do not deploy.
Do not restart services.

Check:
- git status;
- recent commits;
- required environment variables exist, but do not print secret values;
- config syntax if a safe command exists.

Return:
1. whether deployment appears safe;
2. risks;
3. manual confirmations needed;
4. rollback plan.

Optional Hardening

You can further reduce risk with these measures:

Add a Passphrase to the Key

A passphrase helps if the key file is accidentally copied.

Use ssh-agent

This avoids writing sensitive details into commands or prompts.

Avoid Agent Forwarding by Default

Do not enable ForwardAgent yes unless you understand why you need it.

Restrict authorized_keys

For sensitive servers, consider authorized_keys restrictions such as source IP limits or disabling port forwarding.

Be Careful When Disabling Password Login

Before changing SSH daemon settings, make sure:

Common Mistakes

Mistake 1: Pasting the Private Key into the Model

A local agent can call ssh ai-devbox. It does not need to see the private key content.

Mistake 2: Using Root by Default

Root is convenient but dangerous. A low-privilege user limits the blast radius.

Mistake 3: Asking the Agent to Debug, Modify, and Deploy in One Step

Break the workflow into stages:

Read-only check
→ plan
→ small change
→ test
→ diff
→ human confirmation
→ deploy

Mistake 4: No Rollback Plan

Any change involving production config, service restart, database, payment, or authentication should have a rollback plan first.

Final Checklist

Before letting a local AI agent operate a server, check:

Conclusion

A local AI agent connecting to a server should not mean handing the server to AI.

A better framing is:

The agent is a remote development assistant that can inspect, explain, propose, and make small controlled changes.

The safest principles are:

Private key stays local;
Agent does not use root by default;
Read before modifying;
Show diff before deployment;
Put variable server details in env;
Put stable safety rules in a skill file.

With this pattern, Claude Code, Codex, OpenCode, and similar local agents can become useful server assistants without turning your infrastructure into an uncontrolled experiment.

References