リポジトリをクローンする、アーカイブを展開する、プルリクエストをチェックアウトする。そして、エディタで 1 つのファイルを開く。まだ何も実行していません。この記事の問いは、あなたが何かを実行すると決める前に、リポジトリがエディタを通じて何を起こせるか、です。

入り口は 6 つあります。ファイル自身のテキストに設定を書く方法(モードライン)。ディレクトリに、エディタが読み込む設定を置く方法(exrc、.helix)。コードをユーザーの権限で実行するプラグインの仕組み。エディタがリポジトリで git を実行し、git の設定がコマンドを指す場合。プロジェクトが起動を求める言語サーバー。それに、検索ツールです。入り口ごとに、Vim、Neovim、Helix のドキュメントとイシュートラッカーが何を述べているか、そして sim が何をするかを書きます。他のエディタについての主張にはすべて出典をつけ、報告を引いているだけの箇所は、そう明記します。

入り口 1: ファイル内の設定(モードライン)

モードラインとは、ファイルの先頭か末尾の数行にある vim: ts=4 のようなコメントで、エディタのオプションを設定するものです。Vim も Neovim も既定でオンで、root ではオフです [1] [2]。両方のマニュアルが、set 以外のコマンドは「セキュリティ上の理由で」サポートしないこと(「誰かがモードラインを仕込んだトロイの木馬のテキストファイルを作るかもしれない」)、一部のオプションは値が使われるときにサンドボックスが効くようフラグが立っていること、そして次の一文を述べています。「So disable modelines before editing untrusted text.」(信頼できないテキストを編集する前に、モードラインを無効にせよ)[1] [2]

この仕組みは、これまでに破られています。CVE-2019-12735 は、Vim 8.1.1365 より前と Neovim 0.3.6 より前のモードラインにあったコード実行のバグで、モードラインから :source! コマンドに到達できました [3]。2026 年には CVE-2026-34982 が、Vim 9.2.0276 より前にあるモードラインのサンドボックス回避を述べました。3 つのオプションに、モードラインからの設定を防ぐフラグがなく、ある関数には検査が欠けていたのです [4]。Vim は、2026 年 4 月のパッチ 9.2.0350 で、新しいオプション ‘modelinestrict’ を既定でオンにして答えました。モードラインから設定できるのは、短いリストのオプションだけになります [5]。これは強い対応です。同時に、この仕組みの代償も表しています。これだけ経緯のある機能には、サンドボックス、オプションごとのフラグ、許可リスト、そして続くパッチが必要なのです。

Helix はモードラインを解釈しません。要望のイシュー #729 は未解決で、基本的なサポートを加えるプルリクエスト #7788 は、マージされずにクローズされました [6]。

sim は、設定もコマンドも、ファイルの中身からは決して読みません。すり抜けられるモードラインがそもそもありません(SAFE-9)。モードラインの主な用途であるインデント幅は、sim がファイルから自分で判断します。先頭 1,000 行を見て、タブ、スペース 2 つ、スペース 4 つのどれかに決めます(UI-6)。

入り口 2: ディレクトリ内の設定

Vim の ‘exrc’ オプションは、カレントディレクトリの .vimrc、.exrc、.gvimrc を読みます。既定ではオフで、マニュアルの注意書きは率直です。「Setting this option is a potential security leak. E.g., consider unpacking a package or fetching files from github, a .vimrc in there might be a trojan horse. BETTER NOT SET THIS OPTION!」(このオプションをオンにするのは、潜在的なセキュリティホールになる。たとえば、パッケージを展開したり GitHub からファイルを取ってきたりすると、その中の .vimrc がトロイの木馬かもしれない。オンにしないほうがよい)[1]

Neovim の ‘exrc’ も既定でオフです。オンにすると、カレントディレクトリとその親にある .nvim.lua、.nvimrc、.exrc を、「if the files are in the trust list」(そのファイルが信頼リストにあれば)実行します。信頼リストは :trust で管理します [2]。つまり、スイッチではなく、信頼のデータベースです。

Helix は、ワークスペースの .helix/config.toml を読み込みます。25.07.1 のドキュメントにそう書かれています [7]。Helix は示唆に富む例で、開発ブランチには作り込まれた答えがあります。2026 年 3 月にマージされたワークスペース信頼の機能は、次の一覧から始まります。「Helix has several features that can execute arbitrary code: Language servers (LSP), Debug adapters (DAP), Local workspace configuration (.helix/config.toml, .helix/languages.toml), Git integration (filters and other commands in a repository’s .git/config)」(Helix には、任意のコードを実行しうる機能がいくつかある。言語サーバー、デバッグアダプタ、ワークスペースのローカル設定、git との連携)。これらを、direnv と同じ流儀で、ワークスペースごとの信頼の背後に置きます。既定では、言語サーバーは、バイナリがワークスペースではなく PATH から来るので、自動で起動します。一方、ローカル設定の読み込みと、リポジトリの git 設定を信頼することには、明示的な許可が要ります。さらに Helix は .helix/ 以下のすべてのファイルのハッシュを記録し、信頼を与えたあとの変更に気づけるようにしています [8] [9]。これはまだリリースに入っていません。Helix の最新リリースは、2025 年 7 月の 25.07.1 です [10]。リリース版から Helix の振る舞いを読む人は、25.07.1 のドキュメントを読んだ私たちと同じく、古い状態を見ることになります。

sim には、設定ファイルも、プロジェクト固有の設定もありません。実行をまたいで記憶する設定は、見た目、アイコン、Markdown の表示方法の選択だけで、どれも 1 語として、sim のステート用ディレクトリに保存されます。リポジトリの中から、そこに何かを足すことはできません。

入り口 3: プラグイン

プラグインの仕組みは、設計からして、ユーザーの権限でコードを実行するものです。Vim と Neovim には充実したものがあり、これが両者が使われる大きな理由です。Helix には、リリース版にはありません。Scheme の方言 Steel によるプラグインの仕組みは、ドラフトのプルリクエスト #8675 として未マージで、最後の更新は 2026-10-09 でした [11]。

sim にはありません。コンセプトの文書でも、プラグインは「作らないもの」のリストに入っています。これはトレードオフです。プラグインのエコシステムに頼っているなら、いまの sim は向いていません。そうでないかのように言うより、そう書いておきたいと考えています。

入り口 4: git

この入り口は意外に思われがちです。自分ではコードを実行しないエディタでも、リポジトリのステータスを git に尋ねることはあり、git はそのリポジトリ自身の設定を読むからです。

git のドキュメントにある例が core.fsmonitor です。値は「the pathname of the “fsmonitor” hook command」(fsmonitor フックのコマンドのパス名)で、git はどのファイルが変わったかを知るためにこれを実行します。インデックスを更新する必要がある git status などのコマンドが、それを呼びます [12]。2022 年に Justin Steven は、展開したディレクトリに仕込まれた .git/config(通常のリポジトリの中に埋め込まれたベアリポジトリも含む)によって、git status を実行するどんなツールにもそのコマンドを実行させられることを文書にしました。影響を受けるものとして Visual Studio Code(CVE-2021-43891)と JetBrains の各 IDE(CVE-2022-24345)、いくつかのシェルプロンプトを挙げています [13]。フィルタドライバも似ています。filter.<driver>.clean と .smudge は、ファイルの中身に対して動くプログラムを指定します。

同じ種類の問題は、いまの Helix にもあります。2026 年 4 月に立てられ、確認した時点でも未解決のイシュー #15594 は、ファイルを開くと、Helix が git のフィルタパイプラインを通して行の横の差分表示を計算し、そのとき .git/config の smudge コマンドが、ワークスペース信頼のプロンプトより前に実行される、と報告しています。報告は、細工された .git ディレクトリが必要で、通常の git clone では作られませんが、展開したアーカイブでは起こりうると述べています [14]。これは、未解決の報告として引いています。私たちは再現していません。

sim も git を実行します。ツリーのステータス文字、行の記号、ファイル一覧、変更ツリーのためです。決まりは、リポジトリ自身の設定が名指ししているからといって、git にコマンドを実行させないことです。

  1. ほかの git コマンドより先に、sim は git config --list --show-scope --show-origin -z でリポジトリの設定を尋ねます。設定を読むことは、コマンドを実行しません。sim は、食い違いうる 2 つ目のパーサーを書かず、パースを git に任せます。
  2. コマンドラインで止められるものは sim が止め、そのうえで git は動きます。sim の git コマンドは、すべて 1 つの関数で組み立てます。シェルは使わず、core.fsmonitor=false、core.hooksPath には空の専用ディレクトリ、--no-optional-locks、外部 diff もテキスト変換もなし、そしてリポジトリの設定が名指しするフィルタごとに、空の clean、smudge、process を指定します。したがって、ファイルシステムの監視、フック、フィルタ、外部 diff を設定したリポジトリは、拒む理由になりません。git が答え、リポジトリの設定のうちいくつを無効にしたかは、ツリーに出ます(2 git settings off)。代償は、フィルタが変換するファイルが変更されたように見えることです。git が作業ツリーとブロブを比べるためです。git-lfs 自身のフィルタは、git lfs install が書いたとおりの形なら、そのままにします。
  3. それでも、コマンドラインでは止められないコマンドを設定が実行させうる場合は、git を実行しません。判定は、いまあるキーの一覧ではなく、キーの種類です。リポジトリ自身のスコープ(ローカルとワークツリー、それらが読み込むファイル)のどれかの項目で、セクションが include、includeIf、protocol のどれか、変数名が driver、helper、askpass、editor、pager、gitproxy、uploadpack、receivepack、vcs のどれか、あるいは名前が command、cmd、program、hook で終わるもの(core.sshCommand はその 1 つ)が対象です。ユーザー自身のシステム設定とグローバル設定は信頼します。git が読めない設定も、スキップの対象です。
  4. git は、設定に何と書かれていても、sim のためには取得(fetch)しません。GIT_NO_LAZY_FETCH=1、GIT_ALLOW_PROTOCOL=sim-none、GIT_TERMINAL_PROMPT=0 を設定して実行するので、部分クローンにフェッチさせて uploadpack のコマンドを実行させることはできません。
  5. sim は、書き込み系の git コマンドを一切実行しないので、フックは動きません。空のフックパスが、読み取りから到達しうる 1 つのフックも止めます。post-index-change は、git がインデックスを書くときに動きます [15]。git status は、分かったことを保存するためにインデックスを書くことがありますが、--no-optional-locks がその書き込みも止めます。これは sim の仕様の主張で、仕様は、すべてのフックにスクリプトを置いたリポジトリで検証していると述べています。

結果は目に見えます。core.sshCommand を設定している(sim が無効にしないキーです)リポジトリでは、ツリーに git の印は出ず git not run と出て、ステータス行がキーとファイルを名指しして知らせます。

core.sshCommand を設定したリポジトリの sim。ツリーの枠にマゼンタのバッジ「git not run」が出て、ステータス行に「git skipped: core.sshcommand in .git/config could run a command」と出ている

代償は本物です。そうしたリポジトリでは、sim にステータス文字も行の記号もなく、ファイルは git ls-files ではなくディレクトリの走査で集めます。展開したばかりのものには、これが正しい既定だと考えています。

入り口 5: 検索ツール

あいまい検索やリアルタイム検索は、ふつう ripgrep を実行します。ripgrep は、環境変数 RIPGREP_CONFIG_PATH で指定された設定ファイルから追加のフラグを読み、--pre フラグで、検索の前に各ファイルに対してコマンドを実行できます [16]。どちらも正当で便利ですが、何を実行するかを、あなた以外の誰かが決められる経路でもあります。

sim は、PATH の絶対パスの項目から自分で rg を探し(空や相対の項目では、リポジトリの中の ./rg が見つかってしまうからです)、フルパスで、環境変数を空にして --no-config つきで実行し、--pre は決して渡しません。検索語は -e の後ろ、ファイルは -- の後ろに置くので、どれもオプションにはなりません。ripgrep がなかったり失敗したりしたら、組み込みの読み取りが検索を行います。検索は何も書き込まず、プロジェクトのルートの外へ出るシンボリックリンクもたどりません。

入り口 6: 言語サーバー

言語サーバーは、プロジェクトがエディタに起動を求めるプログラムで、プロジェクト自身のビルドの仕組みを動かすことも多いものです。おそらく、もっとも大きな入り口です。

Helix の信頼に関する文書は、既定では言語サーバーが自動で起動し(バイナリは PATH から来て、ワークスペースからではありません)、ワークスペースの .helix ファイルの読み込みと git 設定の信頼には、明示的な許可が必要だと述べています [8]。これは、公開された設計上の判断です。

sim には、言語サーバーのクライアントがまだないので、この入り口は存在せず、これについての防御を主張することもしません。サンドボックスつきのクライアントと、プロジェクトのルートが信頼されているかの表示は、ロードマップにあります。予定であり、まだ提供していません。

入り口を表にすると

入り口 Vim Neovim Helix sim
モードライン オン(root はオフ)。9.2.0350 から ‘modelinestrict’ オン(root はオフ) 解釈しない 読まない
ディレクトリの設定 ‘exrc’、既定でオフ ‘exrc’、信頼リスト 25.07.1 は .helix/ を読み込む。信頼は開発ブランチ そもそもない
プラグイン あり あり リリース版にはない。ドラフトの PR 意図的になし
コマンドを実行する git 設定 ここでは扱わない ここでは扱わない 未解決の報告 #15594。信頼は開発ブランチ 監視、フック、フィルタ、外部 diff は無効にする。コマンドを実行しうるほかのキーがあれば実行せず、キーを名指しする
検索ツール ここでは扱わない ここでは扱わない ここでは扱わない 空の環境変数と --no-config で ripgrep を実行し、--pre は渡さない
言語サーバー ここでは扱わない ここでは扱わない 既定で自動起動 未実装。サンドボックスは予定

「ここでは扱わない」は、引用できる一次情報が見つからなかったので、何も言わない、という意味です。

手放すもの

sim の立場は、固定された振る舞いは、柔軟さより価値がある、というものです。その代わりに、モードラインによる設定、プロジェクト固有の設定、プラグインを手放すことになり、言語サーバーも待つことになります。それらのほうが保証より大事なら、Vim、Neovim、Helix は、それぞれに真剣な答えをもつ成熟したエディタです。Helix の信頼モデルは、使わない人にも読む価値があります。