AI Agent Notes · 2026-07-06

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:
- The private key does not leave your machine.
- The agent does not need root access by default.
- The remote working directory can be restricted to a project path.
- Changes can be reviewed with
git status,git diff, logs, and tests. - 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:
- use a dedicated key for this workflow;
- keep the private key on your local machine;
- put only the public key on the server;
- do not paste the private key into any model;
- do not write root passwords into prompts.
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:
- the
.pubfile goes to the server; - the private key does not;
- the private key should not be pasted into an AI chat.
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:
- SSH private key content;
- production database passwords;
- payment keys;
- cloud provider keys;
- authentication secrets.
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:
- key login works;
- you have a backup console or recovery method;
- your current SSH session remains open;
- firewall rules will not lock you out.
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:
- This is a server you are authorized to manage;
- The agent uses a local SSH alias;
- The private key is not shared with the model;
- Only the public key is on the server;
- A low-privilege user is used;
- The working directory is fixed;
- The first commands are read-only;
- High-risk commands require confirmation;
- Changes must be reviewed with
git diff; - Deployment and restart require human approval;
- A rollback method exists;
- The workflow is stored in an env file plus a skill/rules file.
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
- Codex Remote Connections: https://developers.openai.com/codex/remote-connections
- Codex CLI: https://developers.openai.com/codex/cli
- Claude Code Setup: https://docs.anthropic.com/en/docs/claude-code/setup
- OpenCode Docs: https://opencode.ai/docs/
- OpenCode CLI: https://opencode.ai/docs/cli/