Skip to content

SSH workspace (Skills)

The agent.zio platform provides an isolated independent virtual development environment (SSH Docker Container) for the person responsible in each industry domain. By connecting through the provided SSH port, you can directly create source code in the /agent_skills folder and manage versions via Git. All work inside that folder is linked in real time with the actual execution engine.

Open a terminal on your local PC (Mac/Linux) or Git Bash (Windows) and run the following command to create an SSH key. (Skip if you already have one.)

Terminal window
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"

When prompted for the key storage location and passphrase, press Enter to accept the defaults.

Copy the text contents of the generated public key file (*.pub) and send it to the platform operator for registration.

  • Mac / Linux: ~/.ssh/id_rsa.pub
  • Windows: C:\Users\<account>\.ssh\id_rsa.pub

Install and Connect with VS Code Remote - SSH

Section titled “Install and Connect with VS Code Remote - SSH”

Install Microsoft’s official “Remote - SSH” extension from the VS Code Marketplace on your local PC. After installation, press F1, select SSH: Connect to Host…, then enter a connection string in the following format.

Terminal window
ssh root@서버IP -p [배정받은포트]

Example: If this instance () has port 2221 assigned, use: ssh root@<instance address> -p 2221

💡 To avoid typing the port each time, you can give it an alias in your local PC’s ~/.ssh/config. Create the file if it doesn’t exist.

Terminal window
Host zio_skills
Port 2221 # 배정받은 포트
HostName <인스턴스 주소>
User root

With this setup, you can connect via terminal with ssh zio_skills, and the same name will appear in VS Code’s SSH: Connect to Host… list.

Once connected successfully, click the [Open Folder] button on the left. Initially, the default explorer path is an empty folder /root/. Specify the correct path following these steps:

  1. Click the [Go to Parent Directory] button (the up arrow .. or ⬆️) next to the input field to navigate to the root directory /.
  2. Select the first folder in alphabetical order, agent_skills, and click [OK].

💡 Tip: Opening the /agent_skills folder once will let VS Code remember it for subsequent remote connections, automatically opening it immediately.

Other Option

Instead of editing directly on the remote host, you can edit local files and have them uploaded automatically whenever you save. This is convenient if you prefer to keep a local copy. Install the “SFTP” extension (by liximomo or Natizyskunk) from the VS Code Marketplace, then create .vscode/sftp.json at the root of your local project.

{
"name": "zio-skills",
"host": "<인스턴스 주소>",
"protocol": "sftp",
"port": 2221,
"username": "root",
"remotePath": "/agent_skills",
"uploadOnSave": true,
"ignore": ["**/.git/**", "**/.vscode/**", "**/__pycache__/**"]
}

Be cautious when collaborating with others. Each save uploads to the server, so a remote change can silently overwrite your local copy. If you’re working in a team, the Remote - SSH approach is safer.

This is when several people share a single domain. For example, if nine developers at one company create skills for the same domain, all nine connect using the same address · same port · same account (root). What differs per person are only their public keys and working folders.

Item Number of People Description
Connection address · port One per domain An SSH development container starts for each domain, so there is one port. It does not increase with the number of people.
Login account One per domain All nine share a single root account.
Public key One per person Each person adds a line to authorized_keys. Identity is determined by this key, not the account.
Working folder One per project Everyone works under /agent_skills/<project_name>/.
Claude identity (login·session) One per person For each public key, CLAUDE_CONFIG_DIR is automatically set, so authentication·session·settings are separated by person. Even with the same root and folder, Claude identities do not mix.

Nine people connect with exactly the same single line.

Terminal window
ssh root@[도메인 주소] -p [배정받은포트]

The port is one per company (domain). It does not give each person a different port.

Claude identity is separated by person — first login only once

Section titled “Claude identity is separated by person — first login only once”

Even when sharing the same root account and folder, Claude login·session·settings are completely separate for each person. This is because each public key automatically sets CLAUDE_CONFIG_DIR (in my session it is /root/.claude-users/<my_name>). You only need to log in once with your identity:

Terminal window
echo $CLAUDE_CONFIG_DIR # 내 전용 경로가 보이는지 먼저 확인
claude # 실행 후 /login 으로 최초 1회 로그인

⚠️ If $CLAUDE_CONFIG_DIR is empty, an old remote session remains. Clean it up in VS Code with F1 → “Remote-SSH: Kill VS Code Server on Host…” and reconnect; a new value will be set. The file explorer and opened folders stay the same (the collaboration view is unchanged), so you can safely reconnect.

Do not edit directly on the server — work via branches

Section titled “Do not edit directly on the server — work via branches”

All nine people see the same folder. If someone edits it directly on the server, there is no record of who changed what, and two people editing the same file will cause conflicts.

  1. Create a local branch (feature/<name>) on your PC, work, and push.
  2. Merge into main via PR in the shared repository.
  3. Pull the changes onto the server.
Terminal window
cd /agent_skills
git pull origin main

The server always stays on main. Do not create or move branches on the server—only pull (git pull). Therefore there is no need to delete branches on the server. Finished feature branches are cleaned up locally and in the shared repository.

What the operator does — collect and register public keys

Section titled “What the operator does — collect and register public keys”

Collect the public key (the contents of the .pub file) from each of the nine people at step 1, and append it line by line to the domain’s authorized_keys. It is recommended to note who owns each line at the end.

Terminal window
ssh-ed25519 AAAAC3NzaC1...abcd kim@company # 김OO, 생산관리
ssh-ed25519 AAAAC3NzaC1...efgh lee@company # 이OO, 품질
ssh-rsa AAAAB3NzaC1...ijkl park@company # 박OO, 설비
  • One line per person. When a new person joins, add one more line; when someone leaves, remove only that line.
  • Only accept .pub files containing public keys. Private keys are never exchanged in any case.
  • After editing the file, you must restart the SSH development container for changes to take effect. The container reads this file once at startup.

You can open and edit each other’s project folders directly. This is the real collaboration experience.

  1. No permission conflicts. All nine share the same root identity, so anyone can open, edit, or delete any file created by someone else. If each person had a separate account, A’s files would often be inaccessible to B.
  2. Web and SSH use the same identity. Files edited in the web [Artifacts] editor are owned by root, so they can be continued to edit via SSH. The permission issue in Q4 does not arise within the team.
  3. Single Git repository. The entire /agent_skills is one repo, so commits record who changed what and allow rollbacks.
  4. Multiple people inherit a skill. When you restart a skill, all .py files inside that folder are re‑registered, so functions added by yesterday’s colleague survive your today’s restart.
  5. Less operator effort. Even as the number of people grows, containers, ports, and firewalls stay the same; only one more line is added to authorized_keys.

⚠️ Two things the team must observe

  • Ask before touching someone else’s folder. The ability to edit each other’s files also means you could delete them. Since system permissions do not prevent this, folder naming conventions and Git are the sole safeguards.
  • Do not place files directly under root. Always create /agent_skills/<project_name>/ and work inside it. Standalone .py files will not be loaded as a skill.

If you have relationships where you must not see each other’s work (e.g., external contractors), do not split accounts; instead, open separate domains. That way ports, folders, and data are completely isolated.

When using Windows, if you are repeatedly prompted for a password, see Permission denied (publickey), or Antigravity·VS Code fails to connect, this is the order to find the cause yourself. The following commands work in Command Prompt (cmd) or PowerShell anywhere. Replace the 계정명 in the path with your own Windows login name.

If you keep being asked for a password, that does not mean “the password is wrong.” The server has completely disabled password login for the root account. If public‑key authentication fails, the screen will prompt for a password, but no password will work. Only the correct public key will allow access—so start by checking whether your public key matches what is registered on the server.

First try to connect from the terminal (PowerShell) instead of an IDE

Section titled “First try to connect from the terminal (PowerShell) instead of an IDE”

Antigravity·VS Code has its own settings that can obscure the cause. First, try a pure ssh connection; this immediately tells you whether it’s an “SSH/key issue” or an “IDE setting issue.”

Terminal window
ssh -p [포트] root@[주소]

Example: if the port is 2223, use ssh -p 2223 root@[domain address]. When connecting for the first time, a trust prompt will appear—type yes.

  • If you see the root@…:~# prompt → SSH, key, and server are all fine. The problem is only in the IDE settings, so just look at 진단 5.
  • If you’re prompted for a password or see Permission denied (publickey) → public‑key issue → start with 진단 1.
  • Connection refused or timeout → wrong port/address or the container is restarting briefly. Try again later.

If it works in the terminal but not in the IDE, the key and server are fine—just verify 진단 5.

Does my public‑key “fingerprint” match what’s registered?

Section titled “Does my public‑key “fingerprint” match what’s registered?”

Your public key has a unique value called a fingerprint. It must match what is registered on the server. Use the following command to check your fingerprint.

Terminal window
ssh-keygen -lf C:\Users\계정명\.ssh\id_rsa.pub

You’ll see one line like this (example):

Terminal window
4096 SHA256:9Zt4Kq7bXwR2mNpL8vC1sD3fG6hJ0kA5eB7yU2iO4wQ user@company (RSA)

The part after SHA256: (the example’s 9Zt4Kq7b…4wQ) is your key’s fingerprint. Compare it exactly—including every character—to the fingerprint shown on your card in the 관리 콘솔 [SSH 등록자] screen or to what the operator told you.

id_rsa.pub is the name of the public‑key file. If you followed step 1 of this manual, just run it as is. If you’re unsure of the file name, run dir C:\Users\계정명\.ssh and use the .pub file that appears in the command.

  • Fingerprints match → the key is correct. Proceed to 진단 3 (permissions) and 진단 5 (Antigravity).
  • Fingerprints differ → the private key you’re using does not correspond to the public key registered on the server. Ask the operator to register the contents of this .pub file again.

Do not send this example key as is. It’s common to copy and send the placeholder (your_email@example.com) from step 1 of this manual. If your comment contains your_email@example.com, that means it isn’t your key. Always send the actual contents of the .pub file created on your own PC.

Look at detailed logs to see where it’s being blocked

Section titled “Look at detailed logs to see where it’s being blocked”

Try connecting with a detailed log (-vv) to see which key you’re offering and how the server responds.

Terminal window
ssh -vv -p [포트] root@[주소]
  • Offering public key ... SHA256:... — Are you offering your key? Does its fingerprint match the registered value?
  • Immediately after offering the key, it jumps to password: → the server has no record of that key (not registered or a different key).
  • No such file or directory ... id_rsa → wrong key file name/location.
  • bad permissions / UNPROTECTED PRIVATE KEY → go to 진단 3 (permissions).

Lock the key and config file permissions (Windows perennial issue)

Section titled “Lock the key and config file permissions (Windows perennial issue)”

Windows will ignore or reject a private key or config file if it’s “too open.” Lock them for your account only. First, find your SID (unique identifier).

Terminal window
whoami /user

You’ll see something like S-1-5-21-…-1001. Put that value in <SID> and run the following commands (for both the private key and config).

Terminal window
# 개인키 (config 파일도 아래 세 줄을 똑같이 실행)
icacls "C:\\Users\\계정명\\.ssh\\id_rsa" /reset
icacls "C:\\Users\\계정명\\.ssh\\id_rsa" /setowner "*<SID>"
icacls "C:\\Users\\계정명\\.ssh\\id_rsa" /inheritance:r /grant:r "*<SID>:F"

We use *<SID> instead of your account name (whoami) because on some PCs the account name may be incorrectly resolved as a domain, causing OpenSSH to keep rejecting even if you grant permissions by name. Using the SID guarantees it.

When Bad owner or permissions on config / lookup_sid: Invalid account type: 3 keeps appearing

Section titled “When Bad owner or permissions on config / lookup_sid: Invalid account type: 3 keeps appearing”

This is a bug in Windows’ default OpenSSH (9.5p2) that misidentifies accounts. Even if you fix permissions as in 진단 3, this message may persist; use one of the following workarounds.

(a) Directly specify config to skip the check — in the terminal:

Terminal window
ssh -F "C:\Users\계정명\.ssh\config" [별칭]

(b) Install a newer OpenSSH version — unzip OpenSSH-Win64.zip from github.com/PowerShell/Win32-OpenSSH/releases, and use the ssh.exe inside. If the version is higher than 9.5p2, this bug is absent.

Antigravity / VS Code can’t read the config or key

Section titled “Antigravity / VS Code can’t read the config or key”

If you can connect from the terminal but not from Antigravity·VS Code, change which SSH client the IDE uses.

  • Set it to use the latest ssh.exe from 진단 4(b). In settings (JSON) add:
"remote.SSH.path": "C:\\Users\\계정명\\OpenSSH-Win64\\ssh.exe"

After changing the setting, do not just close the window; fully exit and restart the IDE for the change to take effect. If it still doesn’t work, send the operator the line Launching SSH server with command: from the Output panel → Remote‑SSH log.

Q1. When connecting, the warning “WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!” appears and connection fails.

Section titled “Q1. When connecting, the warning “WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!” appears and connection fails.”

Cause: If the unique identifier (Host Key) of the remote SSH server differs from what is stored on the local PC, the connection is blocked for security reasons.

This rarely happens now. In the past, every time a container was rebuilt, the key changed and everyone received this warning. Now we keep the key in the server folder and reuse it—rebuilding or rebuilding the image keeps the same key. If you still see this warning, inform the operator. It may be that a new key was created or you are actually connecting to a different server.

Solution: Open a terminal on your local PC (or Git Bash/PowerShell) and run the following key reset command, then try reconnecting.

Terminal window
ssh-keygen -R "[서버IP]:[배정받은포트]"

Example: after running ssh-keygen -R "[<instance address>]:2221", reconnect and type yes at the trust prompt.

Two common issues

  • For a few seconds after recreating the container you may see “Connection refused”. The key hasn’t changed; it’s just not ready yet, so try again later. This warning is not resolved by resetting the key.
  • VS Code hangs on a single failure. Even if the server comes up, it will not reconnect automatically and will repeatedly show Error while creating SOCKS connection. Use F1Remote‑SSH: Kill VS Code Server on Host… to clean that host once, then reconnect.

Q2. Running “git status” in a terminal gives the error “fatal: detected dubious ownership in repository”.

Section titled “Q2. Running “git status” in a terminal gives the error “fatal: detected dubious ownership in repository”.”

Cause: This is Git’s own security check triggered by mismatched file permissions between the physical folder on the host server and the root account inside the container.

Solution: In the remote server terminal, run the following command to register the current directory as a safe area. (On newer systems this is automatic.)

Terminal window
git config --global --add safe.directory /agent_skills

Q3. When connecting you get “Permission denied (publickey)”.

Section titled “Q3. When connecting you get “Permission denied (publickey)”.”

Cause and Checks:

  1. Verify that the SSH private key used on your local PC (id_rsa, etc.) matches the public key registered on the server.
  2. Confirm that the correct port number (-p [port]) is specified in the connection command.
  3. If the problem persists, contact the platform operator to verify the location of the authorized_keys file and its folder permissions (700 / 600).

Q4. Files/folders created via the web interface are not updated on the host server (Permission denied).

Section titled “Q4. Files/folders created via the web interface are not updated on the host server (Permission denied).”

Symptom: When you create a skill folder or file using the web [Artifacts] explorer, attempts to save it with an editor directly attached to the host server (local IDE, CLI editor, etc.) result in permission denial. Inside the SSH development container, working as root avoids this issue.

Cause: File creation on the web interface is performed by the api container, which runs as uid 0 (root). The skill/agent folders are bind‑mounted to share the same physical entity with the host, so files created become owned by root:root on the host. With a default umask 022, only the owner has write permission; others have read-only.

Solution: Set a default ACL on the host side once. Default ACLs take precedence over umask, so future files created by root will automatically inherit these permissions. Run this in the top-level repository folder.

Terminal window
# 앞으로 만들어질 것 (기본 ACL)
sudo setfacl -R -d -m g:$(id -gn):rwx instances/*/.skills instances/*/.agents
# 이미 만들어져 막혀 있는 것 (접근 ACL)
sudo setfacl -R -m g:$(id -gn):rwX instances/*/.skills instances/*/.agents
  • Only the second line uses rwX (uppercase). This gives execute permission only to directories; regular files like .py are skipped. Using lowercase would mark all source files as executable, which Git interprets as a permission change.
  • No container restart is needed. ACLs are attributes of the host filesystem and take effect immediately across mounts.
  • The target is limited to .skills and .agents because under instances/ there are folders like Neo4j data that should remain owned by the container.

Verification: If you see two lines in the output below, everything is normal.

Terminal window
getfacl -p instances/<도메인>/.skills/<프로젝트>
group:계정명:rwx
default:group:계정명:rwx

⚠️ Do not do this: Adding user: "1000:1000" to the api service in docker-compose.yml to run the container as a regular user is not recommended. This container creates a virtual environment inside the image and runs pip install when deploying skills; if that path is owned by root, the container cannot write to itself.

Q5. When connecting it keeps asking for a password (no password works)

Section titled “Q5. When connecting it keeps asking for a password (no password works)”

Cause: If public key authentication fails, the screen prompts for a password, but the root account has password login disabled, so any value will be rejected. It’s not a “password issue” but that the public key does not match the server.

Fix: Follow the steps in 🪟 Windows User Self‑Diagnosis starting with Diagnostic 1 (fingerprint comparison). Usually, either you are using a different key than the one registered on the server, or Antigravity is not carrying your private key.