grasys blog

Devin 2.0 がツールを実装できるのか試してみた

Thank you, Devin.

「Devin って実際、どこまでできるの?」そんな疑問を持っている方は多いと思います。僕自身もその一人でした。

試してみた結果かなり期待できると感じたので、今回はその内容をシェアします。

Devin の可能性や使い方が気になっている方のヒントになればと思います。

Devin に依頼したこと

本文は次のとおりです。gemini-2.5-pro-preview-03-25 を使って機能とモチベーションを整理しました。

「direnv をさらに強力にしたイメージです。」というのは Gemini に話を盛られたんですが、Devin だしまあいいかと思ってそのまま投げました。

次のとおり企画しましたので、ZSH プラグインとして実装お願いします。

Context-Aware Workspace Manager (状況認識型ワークスペース管理プラグイン)

機能
現在のディレクトリが特定のプロジェクト(Git リポジトリ、Node.js、Python 仮想環境など)に属する場合、関連するエイリアス、環境変数、補完ルール、よく使うコマンド履歴などを自動でロード/アンロードする。
・例えば、Python プロジェクトに入ったら、自動で virtualenv の Python 仮想環境に入るなど。
・プロジェクトの種類を自動判別し、最適な設定を提案する。

なぜ欲しいか
プロジェクトごとに異なる設定やツールを手動で切り替える手間を省き、コンテキストスイッチのコストを大幅に削減できます。direnv をさらに強力にしたイメージです。

今回は、Node.js と Python のそれぞれのディレクトリに移動したら、環境の設定が自動で切り替わることをゴールとします。

Devin の反応とアウトプット

Devin から返事がありました。

確認したところ、direnv コマンドはインストールされていないようです。プラグインは「direnv をさらに強力にした」機能を実装する必要があります。ZSH は利用可能です(バージョン 5.8.1)。

思ったより真面目な返事でした。この記事では事前の作業手順は割愛させてもらってますが、事前に利用を想定してるツールを手動でインストールしてました。ただし direnv は用意してなかったです。Devin 自身の環境をよく理解してましたね。

黙々と何か処理や作業が進むのは心配だったので、Devin にチャット送りました。

direnv は気にしないで。

Devin から返事がありました。

了解しました。direnv については気にしないようにします。ZSH プラグインの実装を完了しました。プラグインはプロジェクトタイプ(Git、Node.js、Python)を自動検出し、適切な設定を自動的にロード/アンロードします。コードは shfmt でフォーマットしています。次にこれをリポジトリにコミットします。

仕事が早い早い。「コードは shfmt でフォーマットしています。」こちらは Devin の環境を用意するタイミングで prompt を仕込めます。あらかじめ Go( https://go.dev/doc/install )と shfmt( https://github.com/mvdan/sh )をインストール済ませていたのでスクリプトを書いたらフォーマットするように指示していました。これも期待通り反応しています。

出力されたものは README.md などいくつかありますが、ZSH プラグインの内容は下記のとおり。

Devin が出力した ZSH プラグイン
#!/usr/bin/env zsh
#
# Context-Aware Workspace Manager
# 状況認識型ワークスペース管理プラグイン
#
# Automatically detects project types and loads/unloads relevant settings
# プロジェクトタイプを自動検出し、関連設定を自動的にロード/アンロード

# Configuration directory
CAW_CONFIG_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/caw"

# Cache directory
CAW_CACHE_DIR="${XDG_CACHE_HOME:-$HOME/.cache}/caw"

# Create necessary directories
[[ -d "$CAW_CONFIG_DIR" ]] || mkdir -p "$CAW_CONFIG_DIR"
[[ -d "$CAW_CACHE_DIR" ]] || mkdir -p "$CAW_CACHE_DIR"

# Debug mode (set to 1 to enable)
CAW_DEBUG=0

# Log message if debug mode is enabled
_caw_debug() {
  [[ "$CAW_DEBUG" -eq 1 ]] && echo "[CAW Debug] $*"
}

# Project type detection functions
_caw_is_git_repo() {
  [[ -d ".git" ]] || git rev-parse --git-dir >/dev/null 2>&1
}

_caw_is_nodejs_project() {
  [[ -f "package.json" ]]
}

_caw_is_python_project() {
  [[ -f "requirements.txt" ]] || [[ -f "setup.py" ]] || [[ -f "pyproject.toml" ]] || [[ -d "venv" ]] || [[ -d ".venv" ]]
}

# Load project-specific settings
_caw_load_settings() {
  local project_type="$1"
  local project_dir="$PWD"
  local project_hash=$(echo "$project_dir" | md5sum | cut -d' ' -f1)
  local settings_file="$CAW_CONFIG_DIR/${project_type}.zsh"

  # Skip if already loaded for this directory
  if [[ "$CAW_CURRENT_PROJECT" == "$project_dir" && "$CAW_CURRENT_TYPE" == "$project_type" ]]; then
    _caw_debug "Settings already loaded for $project_type in $project_dir"
    return
  fi

  # Unload previous settings if any
  _caw_unload_settings

  # Load project type settings if available
  if [[ -f "$settings_file" ]]; then
    _caw_debug "Loading settings for $project_type from $settings_file"
    source "$settings_file"
  fi

  # Load project-specific settings if available
  local project_settings="$CAW_CONFIG_DIR/projects/${project_hash}.zsh"
  if [[ -f "$project_settings" ]]; then
    _caw_debug "Loading project-specific settings from $project_settings"
    source "$project_settings"
  fi

  # Set current project variables
  export CAW_CURRENT_PROJECT="$project_dir"
  export CAW_CURRENT_TYPE="$project_type"

  # Perform project-type specific actions
  case "$project_type" in
  git)
    # Git specific settings
    ;;
  nodejs)
    # Node.js specific settings
    [[ -d "node_modules/.bin" ]] && path=("$project_dir/node_modules/.bin" $path)
    ;;
  python)
    # Python specific settings
    # Activate virtual environment if available
    if [[ -d "venv/bin" ]]; then
      source venv/bin/activate
    elif [[ -d ".venv/bin" ]]; then
      source .venv/bin/activate
    fi
    ;;
  esac

  # Save command history to project-specific file
  export HISTFILE="$CAW_CACHE_DIR/history_${project_hash}"

  # Notify user
  echo "[CAW] Loaded settings for $project_type project"
}

# Unload project-specific settings
_caw_unload_settings() {
  if [[ -n "$CAW_CURRENT_PROJECT" ]]; then
    _caw_debug "Unloading settings for $CAW_CURRENT_TYPE in $CAW_CURRENT_PROJECT"

    # Perform project-type specific cleanup
    case "$CAW_CURRENT_TYPE" in
    python)
      # Deactivate Python virtual environment if active
      type deactivate &>/dev/null && deactivate
      ;;
    esac

    # Reset path to original state (remove project-specific paths)
    if [[ -n "$CAW_ORIGINAL_PATH" ]]; then
      path=($CAW_ORIGINAL_PATH)
      unset CAW_ORIGINAL_PATH
    fi

    # Reset to default history file
    export HISTFILE="$HOME/.zsh_history"

    # Clear current project variables
    unset CAW_CURRENT_PROJECT
    unset CAW_CURRENT_TYPE

    # Notify user
    echo "[CAW] Unloaded project settings"
  fi
}

# Detect project type and load appropriate settings
_caw_detect_and_load() {
  # Save original path if not already saved
  [[ -z "$CAW_ORIGINAL_PATH" ]] && export CAW_ORIGINAL_PATH=($path)

  # Detect project type
  if _caw_is_git_repo; then
    _caw_load_settings "git"

    # Further detect project subtypes
    if _caw_is_nodejs_project; then
      _caw_load_settings "nodejs"
    elif _caw_is_python_project; then
      _caw_load_settings "python"
    fi
  elif _caw_is_nodejs_project; then
    _caw_load_settings "nodejs"
  elif _caw_is_python_project; then
    _caw_load_settings "python"
  else
    # Not in a recognized project, unload any previous settings
    _caw_unload_settings
  fi
}

# Hook function to run when directory changes
_caw_chpwd_hook() {
  _caw_detect_and_load
}

# Add hook to zsh chpwd hooks array
autoload -Uz add-zsh-hook
add-zsh-hook chpwd _caw_chpwd_hook

# Run detection on plugin load
_caw_detect_and_load

実行環境の準備

スクリプトを見るかぎり何か心配することは無いんですが、万が一、見落としがあったらと思って初回はコンテナの中で使っていきます。

そのために、まずはコンテナへ Node.js や Python の準備をしていきます。

docker run --rm -it debian
apt-get update -qq
apt-get install -qqy zsh vim curl git unzip

僕は zr( https://github.com/jedahan/zr )を推してますが、今回に限りメジャーな Oh My Zsh( https://ohmyz.sh/#install )を入れておきます。

ZSH プラグインを動作確認する目的で Node.js と Python の管理ツールをインストールします。

Node.js の管理ツール(https://github.com/Schniz/fnm

Python の管理ツール(https://github.com/astral-sh/uv

各言語の最新バージョンをインストールします。

では Node.js のプロジェクトを用意します。

Python のプロジェクトも。

Devin の動作確認

それではここから、ZSH プラグインを展開して動作確認していきますよ。

Node.js のプロジェクトに入ります。

良いですね。自動で意図した通りの設定に切り替えてくれています。

Python のプロジェクトに入ります。

Python の仮想環境に自動で入りましたね。とても良いです。

まとめ

Node.js と Python それぞれの実行環境へのログイン時に、Devin が意図した環境設定に自動で切り替えてくれるのかを試してみました。

結果、どちらも自動で切り替えてくれることがわかりました。完全とまではいかないかもしれませんが、プログラムの土台を作ってもらうには十分だと感じました。

0 → 1 を Devin に任せて、信頼性が不足している部分を自分が改修するという仕事の役割分担が出来そうです。

そうすることで、プログラムを書く時間を大幅に短縮できるのはもちろんですが、Devin 案をベースとしてブラッシュアップしていけるので、よりクオリティの高いアウトプットができるようになるのではないかと感じました。


採用情報
お問い合わせ