fedit について
feditは、正確なファイル編集を必要とするシステム管理者、DevOpsエンジニア、スクリプト向けのGo製コマンドラインツール兼MCPサーバーです。行番号やアンカーによる編集、検証、大容量ファイル向けのストリーミング処理に対応します。
主な機能
- 01アンカー指定の挿入、削除、置換、移動、コピー
- 02検証機能付きの行単位編集
- 03複数ファイル操作とファイル間転送
- 04大容量ファイルのストリーミング検索と置換
- 05言語マッパーと区切りフィールドの抽出
活用シーン
- 01デプロイスクリプトでの設定ファイル更新
- 02複数ファイルにある該当セクションの編集
- 03大容量ログの検索や内容置換
MCP 対応
MCPサーバーは、ファイル表示、検索、マッピング、編集のツールを公開し、対応する複数ファイル操作やファイル間操作も提供します。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
このサーバーのパッケージやリモートエンドポイントはまだ取得できていません。プロジェクトの README の手順に従ってください。
ツール
ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。
詳細
fedit — ターミナル向け高速ファイルエディター
コマンドラインからファイルをピンポイントで編集できる、依存関係ゼロの CLI ツールです。 対話型エディターは不要です。sed/awk の複雑な操作も必要ありません。組み込みの検証機能を備えた、シンプルで予測しやすい操作だけを提供します。
システム管理者、DevOps エンジニア、設定変更をスクリプト化するすべての人のために作られています。

go install github.com/amalexico/fedit@latest
fedit を選ぶ理由
- 単一バイナリ、依存関係ゼロ — 純粋な Go 製で、どこでも実行できます
- 21 種類の言語マッパー — 編集前にあらゆるファイルの構造を確認できます
- -v フラグ — 次に進む前に、変更のたびに検証できます
- 行を認識 — 正規表現による予期しない動作や、「どの一致箇所に適用されたのか」という疑問はありません
- ストリームエンジン — 複数 GB のファイルを行単位で、整合性を保ちながら処理できます
- フィールド抽出 — awk を使わずに CSV/TSV の N 列目を取り出せます
- 複数ファイルを一度に処理 — -file にカンマ区切りのリストまたは glob を指定できます。さらに -dest によるファイル間のコピー、移動、置換にも対応しています(v1.9.0 以降)
- 安全 — 指定しない限りインプレース編集は行わず、指定していないファイルには決して触れません
インストール
Go install(推奨):
go install github.com/amalexico/fedit@latest
または、GitHub Releases からバイナリをダウンロードし、PATH に配置します。
検証:
fedit -file /etc/hostname -op show
クイックスタート
# See what is in a file
fedit -file config.yaml -op show
# See just lines 10-25
fedit -file config.yaml -op show -line 10 -end 25
# Find every line containing "timeout"
fedit -file config.yaml -op find -match "timeout"
# See the structure of a Go file
fedit -file main.go -op map -lang go
# Replace line 42 with new content
fedit -file config.yaml -op replace -line 42 -end 42 -text "timeout: 60s" -v
# Insert a line after every occurrence of "server {"
fedit -file nginx.conf -op insertafter -match "server {" -text " include security.conf;" -v
# Move a function block before another (content-matched, atomic)
fedit -file main.go -op move -match "func OldHelper(" -end 45 -beforematch "func NewHelper(" -v
# Copy a config block and paste it 3 times at a new location
fedit -file values.yaml -op copy -line 50 -end 65 -after 200 -times 3 -v
# Extract column 2 from a TSV file (v1.4+)
fedit -file data.tsv -op fields -col 2
# Write content with literal backslashes — no \n escape expansion (v1.6.0)
fedit -file config.txt -op writeraw -text "path=C:\\Users\\admin"
# Hex-encode tricky text to sidestep shell quoting (v1.6.0)
# fwencode produces the hex; fedit decodes it before writing
fedit -file config.txt -op write -texthex 706174683d2f746d70
# Overwrite a file cleanly then insert new content (v1.6.0)
fedit -file config.txt -op insert -line 0 -cleanfirst -text "# regenerated"
# Get bare line numbers for scripting (v1.6.0)
fedit -file main.go -op find -match "TODO" -x 2>$null
# Regex replace on a multi-GB log without loading it into memory (v1.4+)
fedit -file huge.log -op replaceall -match 'ERROR' -text 'WARN' -stream
すべての操作
show — ファイルの内容を表示
# Entire file
fedit -file app.conf -op show
# Lines 50-75 only
fedit -file app.conf -op show -line 50 -end 75
# Last 10 lines
fedit -file app.conf -op show -line -10:
# Lines 50 to 5th from end
fedit -file app.conf -op show -line 50 -end -5
# Lines 100-103 (relative range)
fedit -file app.conf -op show -line 100:+3
# Show from one anchor to another (no line numbers needed)
fedit -file config.go -op show -match "func Start" -endmatch "func End"
find — 部分文字列に一致する行を検索
# Find all lines containing "ERROR"
fedit -file /var/log/app.log -op find -match "ERROR"
# Output includes context lines and occurrence numbers
# Use -nth to target a specific match in other operations
ヒント: まず find を実行して行番号を確認し、その後、正確な行を指定して replace または delete を使います。
insert — 行番号の後に内容を挿入
# Insert a comment after line 1
fedit -file script.sh -op insert -line 1 -text "# Added by deploy script" -v
# Insert multiple lines from a file
fedit -file config.yaml -op insert -line 10 -textfile extra-config.yaml -v
insertafter — 一致する行の後に挿入(推奨)
# Add a firewall rule after the matching comment
fedit -file iptables.rules -op insertafter -match "# Custom rules" -text "-A INPUT -p tcp --dport 8080 -j ACCEPT" -v
# Target the 2nd occurrence
fedit -file nginx.conf -op insertafter -match "server {" -nth 2 -text " listen 8443 ssl;" -v
# Target the last occurrence
fedit -file docker-compose.yml -op insertafter -match "volumes:" -nth -1 -text " - /data:/data" -v
insertbefore — 一致する行の前に挿入(推奨)
# Add a header before the first route definition
fedit -file routes.rb -op insertbefore -match "get '/'" -text " # === Public Routes ===" -v
# Insert a dependency before the closing bracket
fedit -file package.json -op insertbefore -match "}" -nth -1 -textfile new-deps.txt -v
replace — 行範囲を新しい内容に置換
# Replace a single line
fedit -file config.ini -op replace -line 15 -end 15 -text "max_connections = 200" -v
# Replace lines 30-35 with content from a patch file
fedit -file server.conf -op replace -line 30 -end 35 -textfile patched-block.txt -v
# Replace a section by content anchors (no line numbers needed)
fedit -file CHANGELOG.md -op replace -match "## v1.6" -endmatch "## v1.5" -textfile new-section.txt -v
replaceall — グローバルな検索・置換
# Change all occurrences of old domain to new
fedit -file nginx.conf -op replaceall -match "old.example.com" -text "new.example.com" -v
# Update a version string everywhere
fedit -file Makefile -op replaceall -match "1.1.0" -text "1.2.0" -v
fields -- 区切り文字付きファイルから列を抽出(v1.4.0)
# Extract column 2 from a tab-separated file (default delimiter: tab)
fedit -file data.tsv -op fields -col 2
# Extract the third field from a CSV
fedit -file report.csv -op fields -col 3 -delim ","
# Extract usernames from /etc/passwd (colon-delimited)
fedit -file /etc/passwd -op fields -col 1 -delim ":"
出力はパイプで渡せるよう stdout に書き込まれます。-col より短い行は黙ってスキップされます。
常にストリーミング処理されるため、ファイルサイズに関係なくメモリ制限はありません。
-stream -- 大容量ファイルのストリーミングモード(v1.4.0)
replaceall または find に -stream を追加すると、ファイル全体をメモリに読み込まずに行単位で処理できます。1 行あたり 10 MB のバッファーにより、JSON の塊やミニファイされたファイルにも対応します。
整合性を保つため、一時ファイルに書き込んでから名前を変更します。処理が中断されても元のファイルは変更されません。
# Replace a pattern in a multi-GB log file
fedit -file server.log -op replaceall -match "10.0.0.1" -text "10.0.0.2" -stream
# Regex replace in a huge file with capture groups
fedit -file big.csv -op replaceall -match-regex 'id_(\d+)' -text 'ID_$1' -stream
# Streaming find -- grep-style output to stdout
fedit -file huge.log -op find -match "FATAL" -stream
-stream で対応:replaceall(リテラルおよび正規表現)、find。
非対応:move、copy、map(これらの操作ではファイル構造全体をメモリに読み込む必要があります)。
writeraw — エスケープシーケンスを展開せずに書き込み
# Write a Windows path without double-escaping backslashes
fedit -file config.ini -op writeraw -text "basedir=C:\\Program Files\\App"
# Write content from a file as-is
fedit -file output.txt -op writeraw -textfile template.txt
write とは異なり、writeraw では \n は改行ではなく、2 文字(バックスラッシュ + n)として扱われます。
writelines — stdin から対話形式で行を書き込み
fedit -file notes.txt -op writelines
# Type lines at the > prompt, Ctrl+Z (Windows) or Ctrl+D (Unix) to finish
-texthex — 16 進数でエンコードした入力(v1.6.0)
まずテキストを 16 進数にエンコードし(例:fwencode を使用)、その 16 進文字列を -text に渡します。
特殊文字によるシェルのクォート問題をすべて解消します。
# Decode hex string and write — no quoting gymnastics needed
fedit -file deploy.sh -op write -texthex 23212f62696e2f62617368
-matchhex / -endmatchhex — 16 進数でエンコードした検索アンカー(v1.8.1)
-texthex と同じ方法を、検索アンカーに適用します。PowerShell は fedit に渡される前に -match 内の二重引用符を改変するため、case "replace": が気付かないうちに case replace: となり、何も一致しません。代わりにアンカーを 16 進数で渡してください。fedit が一度だけ -match(または -endmatch)にデコードするため、アンカーを受け取るすべての操作を変更せずに使えます。
# Find a line containing double quotes (hex of: case "replace":)
fedit -file main.go -op find -matchhex 6361736520227265706c616365223a
無効な 16 進数が指定された場合は、matchhex: invalid hex string: ...(または endmatchhex: ...)を表示して終了コード 1 で終了します。
複数ファイル -- カンマ区切りのリストまたは glob(v1.8.1 以降は show/find/map、v1.9.0 以降は変更操作と MCP、v1.11.0 以降はリストを指定した -sourcefile と -sourceblock)
-file には、カンマ区切りのリスト、glob、またはその両方を指定できます。glob 展開後のパスと完全に一致する実ファイルがある場合は、そのファイルが優先されます。
読み取り専用の操作(show、find、map)では、ファイルごとに ==> path <== ヘッダーが出力されます。
# Find TODO in every Go file in the current folder
fedit -file '*.go' -op find -match 'TODO'
# Map two files at once
fedit -file main.go,mcp.go -op map -lang go
- find は一致がないファイルをスキップし(grep と同様)、どのファイルにも一致がなかった場合にのみ終了コード 1 を返します。
- map は認識されない拡張子を SKIP 行でスキップします。
- 結果があったファイルの数を示すサマリー行が出力されます。
変更操作(replaceall、insertafter、insertbefore、delete、replace、write)は、各ファイルに個別に実行されます。
# Replace in every matching file
fedit -file '*.conf' -op replaceall -match 'old.example.com' -text 'new.example.com'
# Insert after the first match in each file
fedit -file a.yaml,b.yaml -op insertafter -match 'servers:' -text ' - new'
# Delete from a start line through an end line in each file (-endmatch is inclusive)
fedit -file '*.md' -op delete -match '' -endmatch ''
- 1 つのファイルで問題が発生した場合(一致なし、読み取り不可、読み取り専用、書き込み失敗)は SKIP として報告され、バッチ処理は停止しません。スキップされたファイルは変更されません。
- ファイルごとに OK または SKIP が報告され、その後に
N/M file(s) succeededが表示されます。1 つ以上のファイルで成功した場合の終了コードは 0、1 つも成功しなかった場合は 1 です。 - 使用できるのは -match(delete と replace では -endmatch も可)、-nth、-text/-textfile/-texthex のみです。また、insertafter と insertbefore では -sourcefile/-sourceblock/-lang も使用できます(v1.11.0 以降)。-match-regex は replaceall で使用でき、write には -match は不要で、すべてのファイルに同じ内容を書き込みます。-block、-line、-cleanfirst、-stream、-files は拒否されます。move と copy も、ファイルを読み取る前に拒否されます。
- MCP:fedit_replaceall、fedit_insertafter、fedit_insertbefore、fedit_delete、fedit_replace は、file にカンマ区切りのリストまたは glob を指定でき、同じルールが適用され、ファイルごとに結果が報告されます。block、line、stream、files は拒否されます。fedit_write の file は常に単一のパスとして扱われます。fedit_show、fedit_find、fedit_map にもリストを指定できます。
ファイル間のコピー、移動、置換 -- -dest(v1.9.0、MCP では v1.10.0 以降)
-dest は、-file のブロックをほかの 1 つ以上のファイルにコピーまたは移動します。既存のファイルをカンマ区切りで指定します(グロブは使用できません)。コピー元は通常どおり、-line/-end、-match/-endmatch、または -lang を指定した -block で選択します。コピー先のアンカーは各コピー先ファイル内で個別に解決され、-after、-before、-aftermatch、-beforematch、-afterblock、-beforeblock のいずれかを使用します(ブロックアンカーには -lang が必要です)。
# Copy a function into two other files, right after a named block in each
fedit -file a.go -op copy -block Helper -lang go -dest b.go,c.go -afterblock Init
# Move a config section into two files, before a marker line in each
fedit -file base.conf -op move -match '[cache]' -endmatch '[/cache]' -dest x.conf,y.conf -beforematch '[logging]'
# Paste 2 copies in each destination
fedit -file src.txt -op copy -line 5:+3 -dest a.txt,b.txt -aftermatch ANCHOR -times 2
- コピー先はそれぞれ個別に処理されます。いずれかのコピー先に問題(ファイルがない、アンカーが見つからない、読み取り専用、書き込みに失敗)があった場合は SKIP として報告され、そのファイルは変更されません。バッチ処理が中断されることはありません。
- move は、先にすべてのコピー先へ書き込みます。コピー先への書き込みが 1 つ以上成功した場合にのみ、コピー元のテキストが削除されます。すべてのコピー先で失敗した場合、コピー元は変更されないため、テキストが失われることはありません。
- レポートにはコピー先ごとに OK または SKIP が表示され、その後に
N/M file(s) succeededと表示されます。1 つ以上のコピー先で成功した場合は終了コード 0、どのコピー先でも成功しなかった場合は 1 です。 - コピー先にコピー元と同じファイルを指定した場合は SKIP になります。同じファイルを複数回指定しても、使用されるのは 1 回だけです。
- copy と move ではアンカーフラグとともに -dest を指定し、replace では -destblock(後述)とともに -dest を指定します。これ以外の op と組み合わせることはできません。また、ファイルを読み取る前に、-match-regex、-cleanfirst、-stream、-files との組み合わせは拒否されます。複数ファイルを指定した -file とは組み合わせられません。-file には単一のコピー元ファイルを指定する必要があります。
- ファイル間の転送で移動するのはテキストであり、依存関係ではありません。fmt.Println を呼び出す Go 関数は、fmt の import がないファイルにもテキストとしては正しく配置されますが、import を追加するまでそのファイルはコンパイルできません。v1.11.0 以降、-dest を指定した copy、move、replace では、転送された行で使用されている標準ライブラリの import が Go のコピー先にない場合、注意を促すメモが追加されます(あくまで参考情報であり、結果と終了コードは変わりません)。
- MCP:fedit_copy、fedit_move、fedit_replace は、同じアンカーと replace 用の destblock に対応する dest パラメーター(ファイルのカンマ区切りリスト)を受け取ります。ルールは同じで、コピー先ごとのレポートが出力されます。file には単一のパスを指定する必要があります。fedit_insertafter と fedit_insertbefore は sourcefile と sourceblock(lang を指定)を受け取ります。この場合、file にはカンマ区切りリストまたはグロブを指定できます。
ほかのファイルのブロックを置換する -- replace -dest と -destblock
replace -dest は、各コピー先の指定したブロックを -file のコピー元ブロックまたは範囲で上書きします。上書きするブロックは -destblock で指定する必要があります。コピー元は copy や move と同様に選択し、-lang を指定するとブロック名が解決されます。
# Overwrite Helper in two files with the Helper from a.go
fedit -file a.go -op replace -block Helper -lang go -dest b.go,c.go -destblock Helper -v
- コピー先にそのブロックがない場合は SKIP となり、挿入は行われません。各コピー先は copy や move と同様に個別に処理されます。
- -destblock は replace -dest と組み合わせた場合にのみ指定できます。
別のファイルからブロックを挿入する -- -sourcefile と -sourceblock
insertafter と insertbefore では、別のファイルにある指定ブロックの内容を挿入できます。-file は編集対象のファイルのままで、アンカーは通常どおり選択します。
# Insert Helper from a.go into b.go, after the line matching '// helpers'
fedit -file b.go -op insertafter -match '// helpers' -sourcefile a.go -sourceblock Helper -lang go -v
- -sourcefile と -sourceblock は必ずセットで使用し、-lang が必要です。-text、-textfile、-texthex とは組み合わせられません。
- -file にはカンマ区切りリストまたはグロブを指定できます(v1.11.0 以降)。ブロックは -sourcefile から一度読み込まれ、各ファイル内のそれぞれの -match の位置に挿入されます。レポートはファイルごとに出力されます。一致するものがないファイルは SKIP となり、変更されません。これは -dest による一括展開ではありません。各対象ファイルは、それぞれの -match の位置で編集されます。
- v1.11.0 以降、コピー元とコピー先がどちらも Go ファイルで、挿入するブロックが使用する標準ライブラリのパッケージをコピー先が import していない場合、ヒントが表示されます(CLI では stderr、MCP では OK メッセージ。あくまで参考情報であり、挿入は実行され、終了コードも変わりません)。ファイルリストの場合、ヒントは該当ファイルのレポート行に追加されます。
- MCP ツールでは、fedit_insertafter と fedit_insertbefore のパラメーターとして sourcefile と sourceblock を指定します(lang も指定します)。
guided — 自然な順序のエントリーポイント(v1.11.0 以降の CLI)
fedit guided は、ソース、動詞、宛先を自然な順序で指定すると、明示的な -op コマンドに変換し、実行前に stderr に出力します。これは CLI 専用のショートカットです。MCP ツールはなく、エンジンと明示的なフラグに変更はありません。
fedit guided SRCFILE SRCBLOCK copy|move DESTFILE [before TARGET | after TARGET | at-end] [silent|report-only]
fedit guided SRCFILE SRCBLOCK replace DESTFILE [TARGET]
fedit guided SRCFILE SRCBLOCK insertbefore|insertafter DESTFILE TARGET
fedit guided "new text" insertbefore|insertafter FILE TARGET
fedit guided
fedit guided a.go Helper copy b.go before Init
fedit guided a.go Helper move "b.go,c.go" after Init
fedit guided a.go "line 12-18" copy b.go at-end
fedit guided a.go Helper replace b.go
- ソースは名前付きブロック(言語はファイル拡張子から判定)または
"line N-M"です。 - 宛先が複数ある場合は、1 つのカンマ区切りリストとして引用符で囲みます(
"b.go,c.go")。そうしないと、PowerShell が分割してしまいます。 - 各宛先は個別に処理されます。ファイルが存在しない場合は作成され、アンカーが存在しない場合(または位置が指定されていない場合)は末尾に追加され、その旨が通知されます。移動では先にコピーを実行し、最後に移動するため、書き込みが成功した後にのみソースが消去されます。
- ブロック名は、ほかの箇所と同様に部分一致で照合されます。名前が複数のブロックに一致する場合は、完全一致するものが 1 つあればそれが優先され(その旨が通知されます)。それ以外の場合、ターミナルでは番号付きの選択肢が表示され、ターミナルがない場合は候補一覧が表示されて終了コード 2 が返されます。選択したブロックは、その後行番号で指定されます。
replaceは各宛先の TARGET(デフォルトではソースと同じ名前)を上書きし、TARGET がない宛先はスキップします。silentは-quietを指定してプランを実行します。エコーも通知もなく、すべてのファイルの処理が成功した場合はエンジンのレポートも表示されません(スキップとエラーは引き続き表示されます)。report-onlyは検証出力とエコー行を表示せずにプランを実行しますが、通知とエンジン独自のサマリーは保持されます。どちらの修飾子も最後に指定し、すべての動詞で使用できます。- 引数なしで
fedit guidedを実行すると、操作、ソースファイルとブロック、宛先、位置、修飾子の順に質問されます。操作と位置は名前または番号で回答でき、誤った選択をすると再度質問されます(3 回まで)。プロンプトは stderr に出力され、回答は stdin から 1 行ずつ読み取られるため、パイプ入力も使用できます。最後の回答の前に入力が終了した場合、変更は行われません。
-cleanfirst — 書き込み前に切り詰める(v1.6.0)
# Clear the file then insert fresh content at line 0
fedit -file output.txt -op insert -line 0 -cleanfirst -text "# regenerated"
-x — 機械可読な出力(v1.6.0)
# Get bare line numbers from find (stdout only, no context noise)
fedit -file main.go -op find -match "TODO" -x 2>$null
# Extract CSV column with no stats footer
fedit -file data.csv -op fields -col 2 -delim "," -x
v1.5.0:HCL/Terraform ブロックマッパー(-lang hcl)
行番号を指定せずに、Terraform ブロックを名前で移動、コピー、リファクタリングできます。
-lang hcl、-lang tf、または -lang terraform を受け付けます(すべて同じ意味です)。
対応するブロックの種類:resource、data、module、provider、variable、
output、locals、terraform、moved、import、check。
# Move a resource block before another
fedit -file main.tf -op move -block 'resource "aws_instance" "web"' \
-beforeblock 'resource "aws_s3_bucket" "data"' -lang hcl -v
# Copy a variable definition (scaffold new variable from existing)
fedit -file variables.tf -op copy -block 'variable "instance_type"' \
-after 20 -lang hcl -v
# Reorder provider blocks
fedit -file providers.tf -op move -block 'provider "google"' \
-beforeblock 'provider "aws"' -lang hcl -v
ネストされたブロック(例:resource 内の ingress {})は正しく無視され、
トップレベルのブロックのみが照合されます。
v1.5.0:Nix ブロックマッパー(-lang nix)
Nix 式ファイル内のトップレベル属性バインディングを移動、コピーします。
属性セット(name = { })、リスト(name = [ ])、および
ドット付き属性(programs.git = { })を処理します。
# Reorder home-manager program configs
fedit -file home.nix -op move -block "programs.git" \
-beforeblock "programs.ssh" -lang nix -v
# Copy a service config as a scaffold
fedit -file configuration.nix -op copy -block "services.nginx" \
-after 50 -lang nix -v
move — 行範囲を新しい位置に移動する
# Move lines 100-120 to after line 200 (explicit range)
fedit -file server.go -op move -line 100 -end 120 -after 200 -v
# Move a function block to before another function (content-matched)
fedit -file routes.go -op move -match "func OldHelper(" -end 45 -beforematch "func NewHelper(" -v
# Swap two nginx server blocks
fedit -file nginx.conf -op move -match "server {" -endmatch "# end server 1" -aftermatch "# end server 2" -v
# Cut once, scaffold 3 copies at destination
fedit -file main.go -op move -line 5 -end 12 -after 100 -times 3 -v
ルール:
- 宛先はソース範囲と重複してはなりません。fedit は行番号を示した正確なエラーを報告します。
-times N:1 回切り取り、N 回貼り付けます。差分の合計 = ブロックサイズ × (N−1)。デフォルトの times=1 では差分は 0 です。- ブロックをほかのファイルに移動するには、代わりに
-destを使用します(上記の「ファイル間のコピー、移動、置換」を参照)。
copy — 行範囲を新しい位置にコピーする
# Copy a config block to after a section header
fedit -file values.yaml -op copy -line 50 -end 65 -aftermatch "# staging" -v
# Duplicate a test fixture 10 times for parameterised tests
fedit -file fixtures_test.go -op copy -match "func TestCase(" -end 30 -after 200 -times 10 -v
# Reorder Python classes (copy source before target; overlap is allowed)
fedit -file processor.py -op copy -match "class ModuleProcessor_15" -endmatch "class ModuleProcessor_16" -beforematch "class ModuleProcessor_13" -v
ルール:
- スナップショット方式:書き込み前にソース範囲を 1 回読み取ります。宛先がソースと重複していても、N 個のコピーはすべて元の内容と同一です。
- ブロックをほかのファイルにコピーするには、代わりに
-destを使用します(上記の「ファイル間のコピー、移動、置換」を参照)。 - 差分の合計 = ブロックサイズ × times。
delete — 行を削除する
# Delete a single line
fedit -file hosts -op delete -line 12 -end 12 -v
# Delete a block (lines 40-55)
fedit -file config.yaml -op delete -line 40 -end 55 -v
write — ファイルを作成または上書きする
# Create a new file
fedit -file /tmp/note.txt -op write -text "Deployment started" -v
# Write multi-line content from another file
fedit -file /etc/motd -op write -textfile new-motd.txt -v
map — ファイルの構造概要
# Map a Go file — see all functions, types, imports
fedit -file main.go -op map -lang go
# Map a Dockerfile — see stages and instructions
fedit -file Dockerfile -op map -lang dockerfile
# Map a Makefile — see variables, targets, duplicates
fedit -file Makefile -op map -lang makefile
対応しているマップ言語(21)
| 言語 | 検出される主な構造 |
|---|---|
| go | package、imports、types、interfaces、functions |
| python | imports、classes、functions、decorators |
| javascript | imports、exports、classes、functions、arrows |
| typescript | (javascript と同じ) |
| css | imports、custom properties、selectors、@media、@keyframes。重複したセレクターはコンテナーブロックごとにカウントされるため、異なる @media または @keyframes ブロックにある同じセレクターは重複として扱われません(v1.11.0 以降) |
| rust | use、mod、struct、enum、trait、impl、fn、macro_rules! |
| java | package、imports、classes、interfaces、enums、methods |
| csharp | using、namespace、classes、interfaces、records、properties |
| html | doctype、head/body、見出し、scripts、links、forms、ids |
| sql | CREATE、ALTER、DROP、INSERT、SELECT、indexes、triggers |
| yaml | ドキュメント区切り、トップレベルキー |
| toml | テーブル、配列テーブル、トップレベルキー |
| markdown | 見出し(フェンス付きコードはスキップされるため、シェルのコメントは見出しとして列挙されません)、コードブロック、リンク。重複した見出し(大文字と小文字を区別せず、テキスト、レベル、親が同じもの)には警告が付けられます(v1.11.0 以降) |
| ruby | requires、modules、classes、methods、attributes |
| php | namespace、use、classes、interfaces、traits、functions |
| dockerfile | FROM ステージ、すべての命令。重複するステージ名(大文字と小文字を区別しない)と、同じステージ内で繰り返される CMD、ENTRYPOINT、HEALTHCHECK には警告が付けられます(v1.11.0 以降) |
| makefile | includes、variables、.PHONY、targets |
| json | ルート型、トップレベルキー、ネストの深さ、オブジェクト内の重複キー、不正なファイルのエラー |
| csv | 行、列、ヘッダー一覧、行の不揃い、重複したヘッダー列、空のフィールド |
| hcl | 種類ごとのトップレベルブロック(terraform、provider、variable、locals、data、resource、module、output、moved、import、check)、重複ブロック。terraform と tf は同じものとして扱われます(v1.11.0 以降) |
| nix | トップレベルの属性ブロックと単純な属性、重複する属性パス。インデントされていない行のみが対象です(v1.11.0 以降) |
ほとんどのマッパーは重複(関数、テーブル、キー、ヘッダー列、ブロック、属性、セレクター、見出し、Dockerfile のステージ)を検出し、警告を表示します。
フラグ一覧
| フラグ | 説明 |
|---|---|
| -file PATH | 対象ファイル(必須)。show/find/map および replaceall/insertafter/insertbefore/delete/replace/write では、カンマ区切りのリストまたは glob を指定できます |
| -dest PATH,PATH | ファイル間のコピー、移動、置換:宛先ファイルのカンマ区切りリスト。各ファイルにアンカーフラグ(-after、-before、-aftermatch、-beforematch、-afterblock、-beforeblock)のいずれかが必要です。replace では -destblock を使用します(v1.9.0、MCP では v1.10.0 以降) |
| -op OP | 実行する操作(必須) |
| -line N | 開始行番号(1 始まり)。N:+M は範囲、-N は末尾から、-N:= は末尾から N 行、:=EOF はファイル末尾を指定します |
| -end N | 範囲の終了行。-N はファイル末尾から数えます |
| -text "s" | インラインテキストの内容 |
| -textfile F | ファイルから内容を読み込みます |
| -match "s" | 検索する部分文字列 |
| -nth N | 対象とする出現箇所(デフォルトは 1、-1 は最後) |
| -lang LANG | map および -block 操作用の言語 |
| -v | 検証:編集後に影響を受けた行を表示します |
| -endmatch "s" | 範囲の終端を示す内容アンカー(show/replace/delete/move/copy) |
| -quiet | 成功時の出力を抑制します。複数ファイルおよび -dest 実行時のファイルごとのレポートも抑制します(スキップとエラーは引き続き表示されます)。終了コードで結果を示します(v1.11.0 以降) |
| -texthex HEX | シェルの引用符処理を回避する、UTF-8 コンテンツの 16 進エンコード(v1.6.0) |
| -matchhex HEX, -endmatchhex HEX | 二重引用符を含むアンカー用の、-match および -endmatch アンカーの 16 進エンコード(v1.8.1) |
| -match-regex P | replaceall:キャプチャグループ($1 $2)を使う正規表現 |
| -files GLOB | glob に一致するすべてのファイルに対して replaceall を実行します(その他の操作では、-file にカンマ区切りのリストまたは glob を指定します) |
| -stream | replaceall および find の大容量ファイルモード(v1.4.0) |
| -cleanfirst | 挿入または書き込みの前にファイルを切り詰めます(v1.6.0) |
| -raw | show:行番号やフッターを付けず、コンテンツのみを出力します。fwencode へのパイプに使用します(v1.7.0) |
| -x | find:行番号のみを出力します。fields:統計情報のフッターを表示しません(v1.6.0) |
| -col N, -delim CHAR | fields:列番号(1 始まり)とフィールド区切り文字(デフォルトはタブ)(v1.4.0) |
| -extract SPEC, -get REGEX, -wdelim CHAR | find:行内の抽出(単語および文字のスライス)、正規表現による事前フィルター、単語の区切り文字(v1.7.0。MCP では、無効な get 正規表現はエラーになります。v1.11.0 以降) |
| -block NAME | 行番号の代わりに、名前付きの関数、クラス、またはリソースを対象にします(-lang が必要)。ブロックの終端判定では、文字列、複数行文字列、コメントをスキップします。下記「ブロック終端の判定方法」を参照してください(v1.11.0 以降) |
| -after N, -before N | move/copy の宛先:行 N の後または前(0 はファイルの先頭) |
| -aftermatch TEXT, -beforematch TEXT | move/copy の宛先:TEXT を含む最初の行の後または前 |
| -afterblock NAME, -beforeblock NAME | move/copy の宛先:名前付きブロックの後または前(-lang が必要)。insertafter および insertbefore では、-block を案内するエラーを出して拒否されます(v1.11.0 以降) |
| -times N | move/copy:N 回貼り付けます(move では 1 回だけ切り取ります) |
| -destblock NAME | replace -dest 専用:各宛先で上書きするブロック(必須)。この指定がない宛先はスキップされます(v1.9.0、MCP では v1.10.0 以降) |
| -sourcefile F, -sourceblock NAME | insertafter/insertbefore:別のファイルにある名前付きブロックから内容を取得します(-lang が必要。-text、-textfile、-texthex との併用不可)。-file にはリストを指定でき、Go のインポートヒントを指定できます(いずれも v1.11.0 以降)。フラグ自体は v1.9.0 から、MCP では v1.10.0 から利用できます |
ブロックの終了位置の検出方法(v1.11.0 以降)
-block NAME(および -sourceblock、-destblock、-beforeblock、-afterblock)を指定すると、ブロックの範囲は言語ごとのスキャナーによって決まります。Python と Ruby のブロックでは波括弧の数を数えず、この影響を受けません。Go、JS と TS、Rust、Java、C#、PHP、HCL、Nix では波括弧を数え(Nix では角括弧も数え)、次のものはカウント対象になりません。
- 文字列。複数行のものも含みます。バッククォート文字列(Go の raw 文字列、JS のテンプレートリテラル)、C# の逐語的文字列(
@"...")と raw 文字列(""")、Java のテキストブロック、Rust の raw 文字列(r"..."、r#"..."#)、HCL の heredoc(<<EOT、<<-EOT)、PHP の heredoc と nowdoc(<<<EOT、<<<'EOT'。終了マーカーの前にインデントを付けることもできます)、Nix のインデント付き文字列(二重の単一引用符)。Java のテキストブロックではバックスラッシュが次の文字をエスケープするため、エスケープされた\"""でブロックが終了することはありません。 - Rust の文字リテラル、ライフタイム、ループラベル。
- コメント。
//と/* */(Rust ではネスト可能)、および PHP、HCL、Nix の#(PHP では#[は属性の開始であり、コメントではありません)。Nix に//コメントはありません。//は更新演算子だからです。
既知の制限:エスケープされていない /* を含む JS の正規表現、およびどのブロックの外でも始まるブロックコメントです。このようなブロックの場合は、まず show で範囲を確認し、-line に切り替えてください。
実際の使用例
デプロイスクリプトで Nginx の設定を修正する
#!/bin/bash
# Update upstream server and reload
fedit -file /etc/nginx/conf.d/app.conf \
-op replaceall \
-match "server 10.0.1.50:8080" \
-text "server 10.0.1.51:8080" -v
nginx -t && systemctl reload nginx
crontab に cron ジョブを追加する
fedit -file /etc/crontab \
-op insertafter \
-match "# Custom jobs" \
-text "0 2 * * * root /opt/backup.sh" -v
複数ファイルのバージョンを一括更新する
for f in Makefile config.yaml package.json; do
fedit -file "$f" -op replaceall -match "1.1.0" -text "1.2.0" -v
done
編集前に Dockerfile を確認する
fedit -file Dockerfile -op map -lang dockerfile
# See the structure, then surgically edit:
fedit -file Dockerfile -op insertafter -match "FROM alpine" -text "RUN apk add --no-cache curl" -v
設定からブロックを削除する
# First, find the lines
fedit -file app.conf -op find -match "deprecated-feature"
# Output says lines 44-49, so:
fedit -file app.conf -op delete -line 44 -end 49 -v
PowerShell のワークフロー(Windows システム管理者向け)
# Set an alias
$f = "C:\tools\fedit.exe"
# Find all TODO comments in Go code
& $f -file main.go -op find -match "TODO"
# Replace a config value
& $f -file config.toml -op replaceall -match 'debug = true' -text 'debug = false' -v
# Map a file to understand its structure
& $f -file main.go -op map -lang go
ヒント
- 変更時は必ず -v を使ってください。コストはかからず、確認せずに編集する事態を防げます
- 置換の前に検索してください。正確な行番号を先に取得できます
- insert より insertafter/insertbefore を優先してください。ハードコードされた行番号よりも、一致条件を使うほうが柔軟です
- 一致箇所の最後を対象にするには -nth -1 を使ってください
- 複数行の挿入には -textfile を使ってください。シェルの引用符に関する煩雑さを避けられます
- 見慣れないファイルは編集前に map を実行してください。まず構造を確認できます
LLM ベンチマーク
現在の LLM は、ファイル全体を書き直す場合と比べて、fedit をどの程度うまく使えるでしょうか?
565~1206 行のファイルを対象に、現実的な編集タスクを 7 件用意し、Claude (Sonnet 4.6)、ChatGPT (GPT-4o)、Gemini (2.5 Pro) をテストしました。各タスクでモデルを 2 回テストしました。1 回はファイル全体を出力するよう依頼し(「raw」)、もう 1 回はfedit コマンドのみを出力するよう依頼しました(「fedit」)。
結果
凡例:PASS+ = 最適な 1 行の解決策 | PASS = 正解 | PASS* = 内容は正しいが、書式に問題あり | PARTIAL = 意図は正しいが、行番号が 1 行ずれている、または不安定 | FAIL = 出力が誤り
| テスト | ファイル | タスク | Claude raw | Claude fedit | GPT raw | GPT fedit | Gemini raw | Gemini fedit |
|---|---|---|---|---|---|---|---|---|
| T1 | processor_600.go (575 L) | 特定の構造体メソッドの後にメソッドを挿入 | PASS | PARTIAL | FAIL | PARTIAL | PASS | FAIL |
| T2 | config_800.yaml (1059 L) | 24 行のデプロイブロックを置換 | PASS | PASS | FAIL | FAIL | PASS | FAIL |
| T3 | styles_500.css (565 L) | CSS ルールブロックを検索して削除 | PASS | PASS | PASS* | FAIL | PASS* | FAIL |
| T4 | system_1000.go (980 L) | 一括置換(36 箇所) | PASS | PASS+ | FAIL | PASS+ | PASS* | PASS+ |
| T5 | analytics_700.py (682 L) | 3 段階の連続処理(挿入+削除+置換) | PASS | PARTIAL | FAIL | FAIL | PASS | FAIL |
| T6 | dashboard_900.html (891 L) | 3 番目に一致するボタンの前に挿入(-nth) | PASS | PARTIAL | FAIL | PASS+ | PASS | FAIL |
| T7 | engine_1200.go (1196 L) | Map の実行後、指定したメソッドの後に挿入 | PASS | PASS | FAIL | FAIL | PASS | FAIL |
概要数値
| モデル | 生モード | Fedit モード |
|---|---|---|
| Claude | 7/7 PASS | 4 PASS, 3 PARTIAL |
| ChatGPT | 1/7 PASS* | 2 PASS+, 1 PARTIAL, 4 FAIL |
| Gemini | 7/7 PASS* | 1 PASS+, 6 FAIL |
主な調査結果
1. ChatGPTは大きなファイルを確実に出力できません。
生モードのテスト7件中6件で出力が途中で切れました。特に顕著な失敗はT6で、有効なHTMLの途中に文字どおりのプレースホルダー行[... TRUNCATED FOR BREVITY ...]を挿入しました。これは、出力が構造上は完成しているように見える一方でプレースホルダー文字列を含むという、特に危険な失敗パターンです。T7では1206行が166行に短縮されました。
2. LLMは行番号を幻覚し、チェーンが長くなるほど誤差が大きくなります。 Geminiの行番号の誤りは一連のテストを通じて大きくなりました。T2(単一置換)では36~56行ずれ、T3では45行、そしてT5(3ステップのチェーン)では73行ずれました。ChatGPTもT5で同様のずれを示しました。行番号付きの実行可能なコマンドを一貫して生成できたのはClaudeだけでした。
3. 内容一致を使う操作は、幻覚による誤りの影響を受けません。
Geminiは行番号が必要なfeditテスト(T1、T2、T3、T5、T6、T7)すべてに失敗しましたが、内容一致を使ったreplaceallを使用するT4には合格しました。同じモデル、同じタスクの複雑さでも、信頼性は大きく異なります。ボトルネックは理解ではなく、数えることです。
4. 関数宣言に対するinsertafterは、OPENING行に一致します。
モデルは、関数の終了後に内容を挿入しようとして、繰り返しinsertafter -match "func MyFunc()"を試しました。これはfeditの正しい動作(マッチした行の後に挿入)ですが、新しいコードを関数本体のINSIDEに挿入してしまいます。回避策は、次の構造要素の前にinsertbeforeすることです。T1とT7で確認されました。
5. Claudeでさえ行番号の方向を間違えます。
T6では、30行目にある3つ目のボタンの前にバナーを追加するため、Claudeはinsert -line 30を使いました。しかし、insert -line NはN行目の後に内容を追加します。正しいコマンドはinsertbefore -match "View Details" -nth 3でした。最も優秀なモデルでさえ、行番号を使う単一ステップの操作では約6回に1回、方向を間違えます。
6. -matchが単一行のみを対象にするのは、利点でもあります。
ChatGPTはT3のfeditで、複数行のCSSブロックをリテラルな\nエスケープとともに-matchに渡そうとしました。feditは-match内のエスケープを解釈せず、単一行だけにマッチします。そのため、この操作は脆弱な複数行パターンが誤ってマッチするのではなく、安全に実行されませんでした(一致は0件で、編集も行われません)。
7. Markdownのレンダリングは、見えにくい敵です。
ChatGPTとGeminiの出力は、チャットUIでレンダリングすると__name__がnameに、__init__が**init**になり、CSSやPythonのインデントも失われました。直接ダウンロードした場合、元のファイルは正しい状態でした。これはコピー&ペーストのワークフローには影響しますが、API連携には影響しません。最良の結果を得るには、モデルの「コードをコピー」ボタンまたはダウンロードリンクを使い、レンダリングされた出力を選択してコピーすることは避けてください。
8. 3つの異なるモデルが、T4で同じ1行のコマンドにたどり着きました。
Claude、ChatGPT、Geminiはそれぞれ独立して、fedit -op replaceall -match "FetchUser" -text "GetAccount"を生成しました。適切なツールが明らかな場合、モデルはそのツールを選びます。feditは、内容に基づく編集で適切なツールが明確になるように設計されています。
LLM 駆動のワークフローに関する推奨事項
これらの結果に基づき、LLM から fedit コマンドを生成する際は、行番号を指定する操作よりもコンテンツに一致する操作を優先してください。
insert -line Nではなく、insertbefore -match "next anchor"を使用しますreplace -line N -end Mではなく、replaceall -match "old" -text "new"を使用します- 行番号を指定する操作を行う前に、
find -matchとshowを使って行番号を確認します - 行番号を指定する操作は、MCP に接続された LLM が直前に
fedit_findまたはfedit_showを実行し、前後の文脈で行を確認した場合に限って使用します -block/-langを使用すると、行番号を使わずに名前付きの関数や構造体を指定できます
最良の結果を得るには、fedit の MCP 接続(MCP サーバーモードを参照)を LLM に提供し、変更を加える前に fedit_find と fedit_show を実行できるようにしてください。これにより、行番号の幻覚が発生するケースを完全に排除できます。また、Claude が recon を利用できた場合、一貫して選んだ方法でもありました。
方法論
- 各テストは、元のファイルをアップロードした状態で新しいチャットで実行しました
- モデル間でプロンプトは同一とし、「raw」と「fedit」の指示方法だけを変えました
- 出力をそのまま保存し、
Compare-Objectを使って正解データと差分を比較しました - fedit コマンドをローカルで実行し、出力を再度読み取って正解データを検証しました
Compare-Objectの結果が空で、すべてのテストに合格した raw 出力は 7 件でした(正解データとバイト単位で一致):Claude T2、T3、T4、T5、T6、T7 + Gemini T5、T6、T7PASS*は、チャット UI の表示時にインデントが削除されたことによるバイト単位の差異を示します。内容の構造は正しく、保存したファイルに対して fedit 操作を再実行して検証済みです
テストコーパス
Go、YAML、CSS、Python、HTML を対象とする 7 個の合成ファイル(565~1206 行)。 すべての結果、正解データのファイル、テストプロンプト、7 個のファイルからなるコーパスについては、amalexhandler.com/fedit#benchmarkを参照してください。
MCP サーバーモード
fedit には組み込みのModel Context Protocol(MCP)サーバーが含まれているため、AI コーディングアシスタントは fedit をツールとして使用し、ファイルを正確に編集できます。
fedit mcp
これにより、stdin/stdout 上で JSON-RPC 2.0 サーバーが起動します。このサーバーは、14 個すべての編集操作を MCP ツールとして公開します。
| ツール | 説明 |
|---|---|
fedit_show | ファイルの内容を表示します(全体または行範囲)。file にはカンマ区切りのリストまたは glob を指定できます |
fedit_insert | 行番号を指定して、その行の後に内容を挿入します |
fedit_delete | 1 行以上を削除します。file にはカンマ区切りのリストまたは glob を、match とともに指定できます |
fedit_replace | 行範囲または名前付きブロックを置換します。file にはカンマ区切りのリストまたは glob を、match とともに指定できます。dest + destblock を指定すると、別のファイルにある名前付きブロックを上書きします |
fedit_replaceall | グローバルな検索と置換を行います。正規表現には match_regex、置換テキストには textfile を使用します(どちらも v1.11.0 以降)。file にはカンマ区切りのリストまたは glob を指定できます |
fedit_write | ファイルを作成または上書きします |
fedit_writeraw | エスケープ展開を行わず(バックスラッシュをそのまま扱って)ファイルを作成または上書きします |
fedit_map | 構造の概要を表示します(21 言語に対応。lang を省略すると拡張子から判定します)。file にはカンマ区切りのリストまたは glob を指定できます |
fedit_find | 部分文字列に一致する行を検索します。file にはカンマ区切りのリストまたは glob を指定できます |
fedit_insertafter | 一致する行または名前付きブロックの後に挿入します。sourcefile + sourceblock + lang を指定すると、別のファイルからブロックを挿入します(v1.11.0 以降、Go のインポート候補をヒントとして表示)。file にはカンマ区切りのリストまたは glob を指定できます |
fedit_insertbefore | 一致する行または名前付きブロックの前に挿入します。sourcefile + sourceblock + lang を指定すると、別のファイルからブロックを挿入します(v1.11.0 以降、Go のインポート候補をヒントとして表示)。file にはカンマ区切りのリストまたは glob を指定できます |
fedit_move | 行範囲を新しい位置に移動します。移動先との重複は拒否されます。dest を指定すると、ブロックを別のファイルに移動します |
fedit_copy | 行範囲をコピーします。スナップショットセマンティクスで、重複が許可されます。-times N を指定できます。dest を指定すると、別のファイルにコピーします |
fedit_fields | CSV/TSV/区切り文字付きファイルから列 N を抽出します(-col N -delim CHAR)。常にストリーミング処理を行います |
Claude Desktop での設定
claude_desktop_config.json に追加します。
{
"mcpServers": {
"fedit": {
"command": "fedit",
"args": ["mcp"]
}
}
}
セットアップの完全なガイド(Windows のパス、トラブルシューティング、Cursor/Cline/Windsurf の設定例)については、CLAUDE_DESKTOP.md をご覧ください。
Cursor での設定
プロジェクトのルートにある .cursor/mcp.json に追加します。
{
"mcpServers": {
"fedit": {
"command": "fedit",
"args": ["mcp"]
}
}
}
MCP を使う理由
fedit がない場合、LLM はファイル全体を書き換えるため、トークンを消費し、差分が生じます。MCP ツールとして fedit を使うと、モデルは fedit_map を呼び出して構造を確認し、fedit_find で対象を特定し、fedit_replace または fedit_insertafter で的を絞った編集を行います。変更のたびに統計情報(行数の増減、経過時間)が返されるため、モデルは作業内容を検証できます。
FAQ
チームにしっかりした PR レビュープロセスがある場合、fedit は必要ですか?
差分をすべてレビューする人間主導の編集には、おそらく必要ありません。fedit が特に役立つのは、次の 2 つのケースです。
-
長い設定ファイル全体の書き換え。 LLM が 600 行の
values.yamlを再生成して 1 つのキーを変更する場合、差分は技術的にはレビュー可能ですが、412 行目までスクロールしてほかの箇所が変わっていないことを確認する人は、実際にはほとんどいません。fedit を使えば、N 行の変更に対する差分を正確に N 行にできます。 -
人間が介在しないエージェントのループ。 エージェントを半自律的に実行し(issue → branch → PR を作成し、最後にレビューする場合)、エージェントに「ファイル全体を書き換える」代わりに、的を絞ったツール(
fedit_replace、fedit_insertafter)を使わせることで、レビュー対象の範囲を大幅に減らせます。
ワークフローですでにこうした問題に対処できている場合、CLI は過剰です。それでも、MCP サーバーはエージェントのプリミティブとして役立つ場合があります。
fedit はすべての操作でストリーミングに対応していますか?
現在、replaceall と find は -stream モードに対応しています。move と copy では、ソースとコピー先の両方の範囲を読み込む必要があるため、ファイル全体をメモリに保持する必要があります。map では構造の分析が必要です。fields は常にストリーミングで処理されます。
fedit が処理できるファイルの最大サイズはいくつですか?
デフォルトの(メモリ内)モードでは、利用可能な RAM に制限されますが、通常は数百 MB まで問題なく処理できます。-stream を使う場合、サイズに上限はありません。fedit は 1 行ずつ処理し、行ごとに 10 MB のバッファーを使用します。
fedit は Terraform/HCL に対応していますか?
はい。v1.5.0 以降で対応しています。-lang hcl(または -lang tf/terraform)を -block、-beforeblock、-afterblock と組み合わせると、名前を指定して Terraform ブロックを移動またはコピーできます。トップレベルのブロック型 11 種すべてに対応しています。map 操作は v1.11.0 以降、HCL/Terraform と Nix に対応しています。.tf、.hcl、.nix ファイルに対して(または -lang hcl、terraform、tf、nix を指定して)fedit -op map を実行すると、トップレベルのブロック(HCL)または属性(Nix)が一覧表示され、重複も示されます。fedit_map を使えば MCP 経由でも同様の操作ができます。
fedit はコメントと書式を保持しますか?
はい。設計上、保持します。fedit は解析して再整形するのではなく、行単位で生のテキストバイトを処理します。
replace -line 47 -end 49 を実行すると、1~46 行目と 50 行目から EOF までは、コメント、行末の空白、混在したインデント、BOM マーカーを含め、バイト単位で変更されず、そのまま保持されます。これが、fedit が AST ベースではなく行単位で指定できる主な理由です。AST による往復処理では、末尾のカンマ、コメントの位置、キーの順序、空行の間隔などが失われすぎるためです。
これは特に、ディレクティブの存在理由を示すインラインコメントがある nginx 設定、YAML アンカーとマージキーを使う Ansible プレイブック、人間が選んだ書式が意味を持つあらゆるファイルで重要です。
MCP サーバーは Claude 専用ですか、それとも Cursor 専用ですか?
どちらでもありません。オープンな MCP 仕様を対象としています。公開されている Model Context Protocol スキーマに準拠し、標準的な JSON-RPC 2.0 を stdin/stdout 経由で使用します。特定ベンダー向けの要素はありません。
Claude Desktop でテスト済みです。仕様に準拠した任意の MCP クライアント(Cursor、Continue、Cline、カスタム統合)で動作するはずです。接続する前に公開されている機能を確認したい場合、ツール定義と JSON Schema は mcp.go にあります。
対象文字列がファイル内に複数回出現する場合はどうすればよいですか?
-nth N フラグを使います:
-nth 1(デフォルト) — 最初の一致-nth 2— 2 番目の一致-nth -1— 最後の一致- 任意の正の整数で、その出現箇所を指定できます
3 番目の http.Redirect 呼び出しを対象にする例:
fedit -file router.go -op insertbefore -match "http.Redirect" -nth 3 -textfile patch.txt -v
一致する箇所の数がわからない場合は、まず find を実行してください。変更を加える前に、すべての一致箇所がコンテキスト付きで一覧表示され、対象を特定できます:
fedit -file router.go -op find -match "http.Redirect"
コマンドを連続して実行すると行番号がずれますか?
いいえ。fedit の各呼び出しではファイルを新たに読み込むため、行番号は常にディスク上の最新の状態を反映します。PowerShell では ;、bash では && を使って安全に操作を連続実行できます:
fedit -op replaceall -file f.conf -match "old.com" -text "new.com" -v ; fedit -op replace -file f.conf -line 42 -end 42 -text "fixed" -v
その代わり、操作ごとにディスクの読み込みが発生しますが、編集のワークフローでは無視できる程度です。
設計上、ずれを防ぎたい場合は、行番号ではなく、内容を基準にした対象指定(-match を使った insertafter/insertbefore/replaceall)を優先してください。これらは、それ以前の操作内容にかかわらず、呼び出しのたびに対象を解決します。
ライセンス
MIT — LICENSE をご覧ください
Amalex(ウェブサイト)が開発 — あらゆるファイルを転送するユニバーサルファイルトランスポーター、Amalex Handler の開発元です。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。