VSCodeのDevContainer Remote上(など)でClineを動かすとシェル統合が動かない問題の解決
DevContainer でエージェントコーディングをさせる利点
AIエージェントにコーディングをさせるとき、危険なコマンドを実行してホストマシンの大切なデータを紛失する事例が報告されています。
これを避けるために有効な方法として、もちろんルールを個別に定めるのも有効ですが、根本的な解決策として環境をDockerなどで隔離することが考えられます。
これにうってつけなのがDevContainerなのですが、今のところDevContainer上でClineを使うと、
という警告が表示されて、エージェントが実行したコマンドの結果を読み取れないためにタスクを正しく遂行できないということが起こりました。
一応、タスクを一旦中断して結果を貼り付けてから Resume すればなんとか動いてはくれますが、いちいちコピペするのも手間なので直したいというのが人情です。(我々は人間なので)
原因調査
まず、これが起こる原因を調べます。
手がかりとして、警告内に示されている Still having trouble? にヒントがありました。
重要なのはここです。
Unusual Terminal Output
If you're seeing unusual output with rectangles, lines, escape sequences, or control characters, it may be related to terminal customization tools. Common culprits include:
- Powerlevel10k: A zsh theme that adds visual elements to the prompt
- Oh My Zsh: A framework for managing zsh configurations
- Fish shell themes
To troubleshoot:
Temporarily disable these tools in your shell configuration file (e.g., ~/.zshrc for Zsh)
If the issue resolves, gradually re-enable features to identify the conflicting component
要するに、ターミナルに余計な制御文字とかが含まれてると動かないよと言っています。
なるほど、言われてみれば DevContainer の bash もこんな感じで最初から装飾がされていたような気がします。
というわけで、 bash の装飾をしている PS1 環境変数を見ると、確かに何やら設定されています。
$ echo $PS1
`export XIT=$? \ && [ ! -z "${GITHUB_USER:-}" ] && echo -n "\[\033[0;32m\]@${GITHUB_USER:-} " || echo -n "\[\033[0;32m\]\u " \ && [ "$XIT" -ne "0" ] && echo -n "\[\033[1;31m\]➜" || echo -n "\[\033[0m\]➜"` \[\033[1;34m\]\w `\ if [ "$(git config --get devcontainers-theme.hide-status 2>/dev/null)" != 1 ] && [ "$(git config --get codespaces-theme.hide-status 2>/dev/null)" != 1 ]; then \ export BRANCH="$(git --no-optional-locks symbolic-ref --short HEAD 2>/dev/null || git --no-optional-locks rev-parse --short HEAD 2>/dev/null)"; \ if [ "${BRANCH:-}" != "" ]; then \ echo -n "\[\033[0;36m\](\[\033[1;31m\]${BRANCH:-}" \ && if [ "$(git config --get devcontainers-theme.show-dirty 2>/dev/null)" = 1 ] && \ git --no-optional-locks ls-files --error-unmatch -m --directory --no-empty-directory -o --exclude-standard ":/*" > /dev/null 2>&1; then \ echo -n " \[\033[1;33m\]✗"; \ fi \ && echo -n "\[\033[0;36m\]) "; \ fi; \ fi`\[\033[0m\]$
色々探し回ったところ、どうやら ~/.bashrc
で設定されているっぽいです。
if [ "$color_prompt" = yes ]; then
PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
else
PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '
fi
というわけで、 $PS1
をこの .bashrc
内でもっとシンプルな表示の設定に上書きしてしまえば済みそうです。
解決方法
$ echo 'export PS1="\[\e[32m\]\u@\h:\[\e[36m\]\w\[\e[m\]\$ "' >> ~/.bashrc
これを適用して bash を再起動するとこんな感じの見た目になります。
味気ないな~って思う人はもうちょっといい感じにしてもいいかもしれませんが、あんまり凝りすぎると動かなくなるので試行錯誤しながらやりましょう。
これで無事に Cline がコマンドの出力を見られるようになりました。
(なぜか警告が出続けていることがありますが、問題なく動くと思います。)
最後に、この設定は DevContainer をリビルドすると消えてしまうので、 .devcontainer/devcontainer.json
で以下のように postCreateCommand
を設定しておきましょう。
コマンドを json 内でエスケープするのが面倒なので、シェルスクリプトを指定するのを推奨します。
"postCreateCommand": ".devcontainer/postCreateCommand.sh"
#!/bin/bash
# 実は↓のコメントは自分で書いて Copilot に中身書かせました。
# ユーザー名:カレントディレクトリ $ を表示する。ユーザー名とカレントディレクトリは違う色にする
echo 'export PS1="\[\e[32m\]\u@\h:\[\e[36m\]\w\[\e[m\]\$ "' >> ~/.bashrc
おまけ: ただの WSL2 なのに動かない?
そんなことを調べてるうちに、「そういえばWSL2でも動かないのも同じ理由か?」ということに思い至りました。
事実、僕のWSL2環境では、普段使いしている bash に starship
を用いて現在のgitブランチ名をアイコンと共に出すなどの装飾をしていました。
そこで、 .bashrc
で以下のように starship の初期化条件を作ることで対応しました。
if [[ $TERM_PROGRAM != 'vscode' ]]; then
source <(/usr/local/bin/starship init bash --print-full-init)
fi
環境変数 $TERM_PROGRAM
には bash を起動したプロセスの名前が入っているので、これを判定に使います。
VSCode の統合ターミナルを使うとき全部に無効になってしまいますが、それが嫌な場合はこんな感じで個人設定でプロファイルを追加して、以下のように環境変数で制御するのもよいでしょう。
"bash-without-starship": {
"path": "bash",
"icon": "terminal-bash",
"overrideName": true,
"env": {
"STARSHIP_DISABLED": "true"
}
}
if [[ -z $STARSHIP_DISABLED ]]; then
source <(/usr/local/bin/starship init bash --print-full-init)
fi
これで WSL2 と VSCode の環境でも Cline がコマンドの出力を読み取れるようになりました 🎉
Discussion