Technical runbook (for the AI)
This page is the execution detail behind the task book. A human does not need to read it.
1. Inside the container
# 1) Node 22 + dsh (Codespaces keeps nvm under /usr/local/share/nvm)
export NVM_DIR=/usr/local/share/nvm; . $NVM_DIR/nvm.sh
nvm install 22 && nvm alias default 22
npm install -g @deepseek-ai/dsh
node -v && dsh --version
# 2) the workspace is a clone of the private repo
cd ~ && git clone git@github.com:<you>/<repo>.git dsh-workspace
# 3) scripts live on the persistent volume
mkdir -p /workspaces/<repo>/.dsh-cloud
# start.sh / update.sh / sync.sh / sync.conf — see install/cloud-setup.sh
Deploy key (write access to that one repo only)
ssh-keygen -t ed25519 -N "" -f ~/.ssh/dsh_deploy -C dsh-deploy
cat ~/.ssh/dsh_deploy.pub
# add it under repo Settings -> Deploy keys with "Allow write access"
# or: gh api -X POST /repos/<you>/<repo>/keys -f title="dsh-cloud-autosync" \
# -f key="<public key>" -F read_only=false
cd ~/dsh-workspace
git config core.sshCommand "ssh -i $HOME/.ssh/dsh_deploy -o IdentitiesOnly=yes -o StrictHostKeyChecking=accept-new"
git config user.name "dsh cloud"
git config user.email "dsh-cloud@users.noreply.github.com"
dsh permission presets (append to ~/.dsh/profiles/web/cordis.patch.yml)
- id: sandbox-policy
name: "@deepseek-ai/dsh-sandbox-policy"
config:
mode: workspace-write
workspaceRoot: !!js process.cwd()
- id: approval
name: "@deepseek-ai/dsh-user-approval"
config:
policy: ask
- id: permission
name: "@deepseek-ai/dsh-permission-presets"
config:
defaultPreset: workspace-write
presets:
read-only: { sandbox: read-only, approval: ask }
workspace-write: { sandbox: workspace-write, approval: ask }
danger-full-access: { sandbox: danger-full-access, approval: ask }
2. On the host (Windows)
:: portable gh (no admin needed)
set "DIR=%LOCALAPPDATA%\dsh-cloud"
curl.exe -sL -o "%DIR%\gh.zip" https://github.com/cli/cli/releases/download/vX.Y.Z/gh_X.Y.Z_windows_amd64.zip
powershell -NoProfile -Command "Expand-Archive -LiteralPath '%DIR%\gh.zip' -DestinationPath '%DIR%\gh' -Force"
:: one-time authorization (needs the codespace scope)
"%DIR%\gh\bin\gh.exe" auth login --hostname github.com --git-protocol https --web --scopes codespace,repo,read:org,workflow
:: SSH key (must be created by the current user)
ssh-keygen -t ed25519 -N "" -f "%USERPROFILE%\.ssh\dsh_cs_key" -C dsh-codespace
:: start dsh in the cloud (the last line prints the token URL)
"%DIR%\gh\bin\gh.exe" codespace ssh -c <codespace> -- -i "%USERPROFILE%\.ssh\dsh_cs_key" "bash /workspaces/<repo>/.dsh-cloud/start.sh"
:: tunnel (keep this window open)
start "dsh tunnel" /min cmd /c ""%DIR%\gh\bin\gh.exe" codespace ports forward 3080:3080 -c <codespace>"
macOS/Linux equivalents: macos-linux.md.
3. Acceptance criteria
| Check | Expected |
|---|---|
| cloud dsh process | ss -ltn shows :3080 listening |
| request without token | 401 |
| request with token | 303 plus a dsh-auth-* cookie |
| local tunnel | curl http://127.0.0.1:3080/ returns 401 (proves the tunnel works) |
| browser | the token URL opens the dsh UI |
| git backup | local HEAD == git ls-remote origin refs/heads/main |
| empty dirs | a new empty folder shows up (with .gitkeep) after the tree goes quiet |