·tips

Devin CLIで複数アカウント・orgを切り替える

XDG_DATA_HOMEだけを切り替えて認証を分離し、config.jsonは--configで指定、XDG_CONFIG_HOMEは共有。atuin/ghなど共有したいデータはsymlinkで吸収する

4 min read
Writing style

まとめ

  • Devin CLIはXDG_DATA_HOME配下のdevin/credentials.tomlに認証を書くので、XDG_DATA_HOMEだけ切り替えれば認証を分離できる
  • devin.org_idは~/.config/devin/config.jsonに入るので、config.jsonだけ--configでプロファイル別に指定する
  • XDG_CONFIG_HOMEは~/.configのままにして、~/.config/devin/配下のskills・AGENTS.md・sessions.dbなどを共有する
  • atuinやgh extensionsなど、XDG_DATA_HOMEを変えると副作用が出るものはsymlinkで元の場所に戻す

ファイル配置

種別パスprofile間で
認証$XDG_DATA_HOME/devin/credentials.toml分離する
MCP OAuth$XDG_DATA_HOME/devin/mcp/oauth/分離される
sessions/transcripts/logs$XDG_DATA_HOME/devin/分離する
設定(org_id含む)~/.config/devin-<profile>/config.json--configで切り替え
グローバルskills等~/.config/devin/ 配下共有
atuin履歴~/.local/share/atuinsymlinkで共有
gh extensions~/.local/share/ghsymlinkで共有

profile切り替えwrapper

~/binが/opt/homebrew/binよりPATH前方にある前提で、~/bin/devinを置く。

#!/bin/sh
# DEVIN_PROFILE=<name> devin [...]
# devin の auth/state を profile 分離する wrapper。
#   default 以外: XDG_DATA_HOME=~/.local/share/devin-<name>
#                 config.json は ~/.config/devin-<name>/config.json
#                 XDG_CONFIG_HOME は ~/.config のまま
#   atuin, gh など共有したい XDG data は symlink
set -eu

self="$(cd "$(dirname "$0")" && pwd -P)/$(basename "$0")"
real="$(type -aP devin | grep -Fvx "$self" | head -n 1)"

case "${DEVIN_PROFILE:-default}" in
  default)
    exec "$real" "$@" ;;
  *)
    export XDG_DATA_HOME="$HOME/.local/share/devin-$DEVIN_PROFILE"
    mkdir -p "$XDG_DATA_HOME"

    for dir in atuin gh; do
      if [ ! -e "$XDG_DATA_HOME/$dir" ]; then
        mkdir -p "$HOME/.local/share/$dir"
        ln -s "$HOME/.local/share/$dir" "$XDG_DATA_HOME/$dir"
      fi
    done

    mkdir -p "$HOME/.config/devin-$DEVIN_PROFILE"
    exec "$real" --config "$HOME/.config/devin-$DEVIN_PROFILE/config.json" "$@" ;;
esac
devin                              # 今まで通り
DEVIN_PROFILE=work devin auth login  # 別アカウントでログイン
DEVIN_PROFILE=work devin auth status

初回セットアップ・移行

既存のprofileディレクトリ(例:devin-personal)を新しい構成に合わせる。

# config.jsonをプロファイル直下に移動
mv ~/.config/devin-personal/devin/config.json ~/.config/devin-personal/config.json

# atuinを共有
rm -rf ~/.local/share/devin-personal/atuin
ln -s ~/.local/share/atuin ~/.local/share/devin-personal/atuin

# gh extensionsを共有
ln -s ~/.local/share/gh ~/.local/share/devin-personal/gh

~/.config/devin-personal/devin/に残るAGENTS.md・skills・ponytail-hook.jsのsymlinkは不要になる。devinは~/.config/devin/を直接読む。

設定とsessions

  • config.jsonだけ~/.config/devin-<profile>/config.jsonに置く。devin.org_idはここに書き戻される
  • ~/.config/devin/配下のAGENTS.md・skills・sessions.dbは全profileで共有
  • sessions.dbは複数profileから同時アクセスするとdatabase is lockedになり得る。WALなのでretryすれば通る

注意点

  • XDG_CONFIG_HOMEはwrapperで上書きしない。--configだけでconfig.jsonの場所を変える
  • atuinやghはXDG_DATA_HOMEに従うので、symlinkを忘れると履歴・extensionsがプロファイル別になってしまう
  • miseやuvもXDG_DATA_HOMEに従う。プロファイル別にしたくないなら同様にsymlinkするか、MISE_DATA_DIR・UV_TOOL_DIRなど個別の環境変数で固定する
  • XDG_DATA_HOMEを切り替えてもdevinのsessions/transcriptsはプロファイル別になる。履歴を共有したい場合は~/.local/share/devin/cliやsummariesをsymlinkする
  • read_config_fromはprofile側に引き継がれない。main側でproviderを絞っている場合はprofile側configにも書く

ref