- https://github.com/rtk-ai/rtk というやつ便利そうなので、公私ともに便利に使っていきたいぞ
- ところで rtk って安心して安全に使えるものなのか気になった
- Claude Code とか Codex が rtk ls とか rtk git したとき、コマンドラインとか、実コマンドの標準入出力を勝手に外部送信してたら困る
- 私は Rust の読み書きはできないんだな
- Codex くんに質問して読解してもらいつつ、見様見真似で Rust コード読解してみた。正直キツかった。だいぶわからなかった
- ghq get して取れた今日時点の main の HEAD の
a69935746172d913fcbd282d720d2daf5025e5e9で読解してもらった - rtk は外部送信やってなさそうな気配を感じた
- rtk がコマンド実行の統計データ保管する SQLite ファイルは、うっかり漏洩しないよう厳重保管として扱うのが安全そう
- macOS なら
"/Users/$USER/Library/Application Support/rtk/history.db"に転がってた
- macOS なら
- なんなら時々 SQLite ファイル削除するくらいでいいんじゃないかな
- SQLite 保管を停止する機能は存在しない
-
-
Save sasasin/96778b869ad14f692a8f4fb6349c6171 to your computer and use it in GitHub Desktop.
このプロダクトのソースコードから、これが何をするプログラムなのか、フォルダ構成、プログラミング言語、利用しているライブラリ、アーキテクチャを把握して、 reading/001.md として文書化してほしい。
このプロダクトは RTK (Rust Token Killer) という CLI ツールで、LLM エージェントや開発者が実行する各種コマンドの出力を、意味を保ちながら圧縮・要約・整形してトークン消費を減らすためのプロキシです。
典型的には git status や cargo test、pnpm, pytest, docker, aws, grep, read などの出力をそのまま LLM に渡す代わりに、RTK が間に入り、
- ノイズ除去
- エラー中心の抽出
- 同種メッセージのグルーピング
- 重複排除
- 大量出力の切り詰め
- JSON やログの構造化表示
を行います。
その結果、README やアーキテクチャ文書上では 60〜90% 程度のトークン削減を狙う設計になっています。
また、このツールは単なる手動 CLI ではなく、Claude Code / Codex / Cursor / Copilot / Windsurf などの AI コーディングエージェント向け hook システムを持っており、git status のような生コマンドを自動的に rtk git status に書き換える用途も担っています。
コードベースを読む限り、このリポジトリは次の 4 本柱で構成されています。
-
CLI プロキシ本体 外部コマンドを実行し、その出力をフィルタして返す Rust バイナリ。
-
コマンド書き換えシステム LLM エージェントの hook から呼ばれ、通常のコマンドを
rtk ...へ変換する仕組み。 -
トークン削減の記録と分析 実行結果を SQLite に保存し、
rtk gainなどで削減量を可視化する仕組み。 -
フィルタ定義の拡張機構 Rust 実装の高機能フィルタに加えて、TOML ベースの宣言的フィルタも持ち、未対応コマンドもある程度カバーできる仕組み。
主言語は Rust です。src/ 以下に 99 個の .rs ファイルがあり、CLI 本体・ルーティング・フィルタ・hook 管理・分析機能の中核は Rust で実装されています。
補助的に次の言語も使われています。
- TypeScript
openclaw/とscripts/benchmark/に存在。OpenClaw 向けプラグインとベンチマーク支援コード。 - Shell
install.sh,scripts/*.sh,hooks/*/*.sh。インストール、テスト、hook 配布用。 - TOML
Cargo.tomlとsrc/filters/*.toml。Rust パッケージ定義と組み込みフィルタ DSL。 - Markdown README 群、ガイド、保守者向けドキュメントが非常に充実しています。
つまり、実行エンジンは Rust、周辺統合と配布は Shell/TypeScript、設定と簡易フィルタは TOML という構成です。
Cargo.toml から確認できる主要依存は次の通りです。
clapCLI 定義とサブコマンド解析。anyhowエラーハンドリング。regex,lazy_static出力解析、ルールマッチ、コマンド書き換え判定。serde,serde_jsonJSON 入出力の解析・整形。rusqlite(bundled) トラッキング DB の永続化。SQLite を内包して配布しやすくしている。toml設定ファイルと TOML フィルタ DSL の読み書き。chronoタイムスタンプ処理。tempfilehook インストールや設定更新時の安全な一時ファイル操作。sha2hook 整合性検証用のハッシュ計算。ureq軽量 HTTP 通信。テレメトリやネットワーク取得系に利用される設計。flate2圧縮データ処理。quick-xmlXML 系出力の解析補助。which実行コマンドの検出。ignore,walkdir,dirsファイル探索やユーザーディレクトリ解決。coloredCLI 表示の色付け。automodディレクトリ単位で Rust モジュールを自動公開する補助。
Rust 依存の選び方からも、非同期サーバではなく 軽量・単一バイナリ・高速起動の CLI を重視していることが読み取れます。
リポジトリの重要ディレクトリは次の通りです。
src/アプリケーション本体。docs/アーキテクチャ、利用方法、メンテナ向け資料。hooks/各 AI ツール向けに配布する hook スクリプトやルール。scripts/テスト、ベンチマーク、インストール補助。tests/fixtures/パーサやフィルタの検証用フィクスチャ。openclaw/OpenClaw 向けプラグイン実装。TypeScript ベース。Formula/Homebrew 配布用 formula。reading/今回のような読解メモ置き場。
src/main.rsCLI エントリポイント。clapでサブコマンドを解釈し、各モジュールへルーティングする。src/cmds/実際のコマンド実行と出力フィルタを担当する中心レイヤー。src/core/設定、トラッキング、共通ユーティリティ、TOML フィルタ、表示補助などの基盤。src/hooks/rtk init,rtk rewrite, hook 整合性検証、trust 管理など。src/discover/コマンド書き換えルール判定と、過去履歴からの適用可能コマンド分析。src/analytics/SQLite に蓄積した削減実績の分析表示。src/learn/失敗コマンドと修正コマンドの対を学習して、CLI ミスの傾向を検出。src/parser/JSON/構造化出力を段階的に解釈する共通パーサ基盤。src/filters/TOML DSL による宣言的フィルタ群。
このディレクトリはエコシステム別に整理されています。
git/git,gh,gt, diff 系。rust/cargo,err,testなど Rust 開発向け。js/npm,pnpm,vitest,tsc,next,prettier,playwright,prisma, lint 系。python/ruff,pytest,mypy,pip。go/go,golangci-lint。ruby/rake,rspec,rubocop。dotnet/dotnet,trx,binlog, format report。cloud/aws,docker,kubectl,curl,wget,psql。system/ls,tree,read,grep,find,json,log,env,deps,summaryなど汎用系。
この構成から、RTK は単一用途のツールではなく、開発現場で頻出する CLI 群の出力圧縮プラットフォームとして作られていると分かります。
アーキテクチャは 「hook + コマンド分類 + 実行/フィルタ + トラッキング」 の 4 層です。
-
Hook 層 AI エージェントが実行しようとする生コマンドを捕捉する。
-
Rewrite / Discover 層 そのコマンドを RTK で処理できるか判定し、
rtk git statusのように書き換える。 -
Command Filter 層 実コマンドを起動し、出力をコマンド固有ロジックで圧縮する。
-
Core / Tracking 層 フィルタ結果を表示し、入出力文字量や削減率を SQLite に記録する。
標準的な流れは次の通りです。
- LLM エージェントやユーザーがコマンドを実行する。
- hook が
rtk rewrite "<元コマンド>"を呼ぶ。 src/discover/registry.rsがルールに基づいて書き換え可否を判定する。src/main.rsがclapでrtkのサブコマンドを解析する。- 対応する
src/cmds/...モジュールが実コマンドを実行する。 - フィルタ関数がノイズ除去・要約・集約を行う。
src/core/tracking.rsが元出力と加工後出力を比較して DB に保存する。src/analytics/の各コマンドがその記録を可視化する。
文書とコードから、次の設計方針が明確です。
- 単一バイナリ ランタイム依存を抑え、配布しやすくしている。
- 高速起動 開発ループで何度も呼ばれるため、起動オーバーヘッドを極小化している。
- Fail-safe フィルタ失敗時は raw 出力へフォールバックする。
- 終了コードの保持 もとのコマンドの exit code を極力壊さず返す。
- 未知コマンドも通す 未対応コマンドは passthrough や TOML フィルタへ流す。
- 構造化出力を優先 JSON/NDJSON/XML が取れるツールではそれを使って賢く圧縮する。
main.rs は巨大な CLI ルータです。Commands enum に各サブコマンドを定義し、match で各実装モジュールへ渡します。つまりアプリケーションの中心はここですが、実際の知能は cmds, discover, core, hooks 側に分散しています。
最も重要なレイヤーです。各モジュールは外部 CLI を Command::new(...) で実行し、その stdout/stderr をツール固有のルールで圧縮します。
ここには大きく 2 種類あります。
- Rust フィルタ JSON 解析、ステートマシン、ルール別集約などの高度な処理。
- 共有 runner に乗る実装
共通の実行・追跡・終了コード処理を
core/runner.rsに委譲する実装。
アプリ共通基盤です。特に重要なのは次です。
tracking.rsトークン削減記録の永続化。runner.rsコマンド実行の共通フロー。toml_filter.rs宣言的フィルタ実行。config.rs設定読み込み。tee.rsフィルタ失敗時やトランケーション時の救済出力。utils.rsANSI 除去、コマンド解決、トークン推定などの横断ユーティリティ。
AI エージェントへの組み込みを担当します。単に shell script を置くだけでなく、
- hook インストール
- 設定ファイルの patch
- SHA-256 による hook 改ざん検知
- rewrite 用 CLI ブリッジ
- trust / verify / audit
まで管理しており、運用レイヤーとしてかなり重要です。
このプロダクトの「自動書き換え頭脳」です。コマンドの字句解析、複合コマンド分解、rewrite ルール適用、履歴分析がここにあります。
特に &&, ||, |, redirect, quote を含むコマンドを安全に扱うため、単純な split ではなく lexer ベースで処理している点が特徴です。
トラッキング DB を読み取って、どれだけトークンを削減したかをダッシュボードとして見せる層です。設計上は read-only で、記録は core/tracking、可視化は analytics と責務分離されています。
Claude Code のセッション履歴から、「誤った CLI 実行 → 修正コマンド」のパターンを検出して学習する機能です。これは単なる出力圧縮ツールから一歩進んで、エージェントの操作ミス改善支援まで視野に入れていることを示しています。
ツール出力を
- Full parse
- Degraded parse
- Passthrough
の 3 段階で扱う共通インフラです。ツールバージョン差異やフォーマット崩れに強くするための設計で、堅牢性を高めています。
- CLI 体験に特化した非常に明快な責務分離
- フィルタ失敗時のフォールバックを前提にした安全設計
- LLM エージェント統合まで含めた実運用志向
- SQLite による計測基盤があり、効果を定量化できる
- Rust 実装と TOML DSL 実装を併用し、拡張性と開発速度を両立している
このプロダクトは「単なるコマンドラッパー」ではなく、
- AI エージェント向けの出力最適化ミドルウェア
- CLI 出力圧縮フレームワーク
- トークン節約の観測基盤
を兼ねたツールだと理解するのが適切です。
このリポジトリは、Rust 製の高性能 CLI プロキシとして、
- 開発系コマンドの出力を圧縮し
- AI エージェントの hook と連携して自動利用させ
- 削減効果を SQLite に蓄積・分析し
- 必要に応じて TOML ベースのフィルタでも拡張できる
ように設計されています。
中心となるアーキテクチャは main.rs のルーティングを起点に、
src/cmds/が各種コマンドの実行・圧縮、src/core/が共有基盤、src/hooks/がエージェント統合、src/discover/が rewrite 判定、src/analytics/が可視化、src/learn/が履歴学習
を分担する形です。
コードベース全体としては、「LLM に渡す CLI 出力を最適化するための Rust 製プラットフォーム」 という理解でほぼ間違いありません。
このプログラムを利用するにあたりセキュリティ監査的な観点で大丈夫なものか見極めたい。rtk コマンド経由で実プログラムを実行したとき、たとえば、「渡されたコマンドラインを、どこか外部サーバーに送信している」とか「コマンド実行結果を、どこか外部サーバーに実行している」ような箇所が存在しているか、ソースコード読解して調べてほしい。調べた結果を reading/002.md として保存してほしい。
ソースコードを読む限り、rtk が 実行したコマンドライン全文やコマンド実行結果本文を、常時どこかの外部サーバーへ送信する実装 は見当たりませんでした。
ただし、例外として telemetry(匿名利用統計) の送信機能は存在します。これは run_cli() の冒頭で毎回 maybe_ping() を呼ぶ実装になっていますが、実際に送信されるのは
- ビルド時に telemetry URL が埋め込まれている
- ユーザーが明示的に同意している
RTK_TELEMETRY_DISABLED=1で無効化していない
という条件を満たした場合だけです。根拠: src/main.rs:1284-1286, src/core/telemetry.rs:20-66
送信内容もコード上は 集計済みメタデータ中心 で、少なくともこの実装では
- コマンド出力本文
- フルのコマンドライン引数
- ソースコード本文
を telemetry payload に直接入れていません。根拠: src/core/telemetry.rs:106-150, src/core/tracking.rs:912-923, src/core/tracking.rs:960-1003
外部 HTTP 通信をしている本体コードは、調べた範囲では telemetry の 1 系統です。
src/core/telemetry.rs:14-15RTK_TELEMETRY_URL/RTK_TELEMETRY_TOKENはoption_env!()でビルド時注入src/core/telemetry.rs:20-66同意・設定・環境変数・23時間間隔を確認し、条件を満たす時だけ別スレッドで送信src/core/telemetry.rs:106-150ureq::post(url)で JSON を POST
送信 payload に含まれるのは、コード上は主に以下です。
device_hashversion,os,arch,install_method- 24時間のコマンド数
- 上位コマンド名
- 節約トークン数や節約率
- passthrough 上位、parse failure 件数
- hook 種別、設定有無、プロジェクト数
- ecosystem の比率、meta command 使用回数
根拠: src/core/telemetry.rs:106-140
rtk telemetry forget 実行時には、サーバー側削除要求として別の POST もあります。
src/core/telemetry_cmd.rs:143-180
ここで送るのは
device_hashaction: "erasure"
のみです。
rtk は多くの実行経路で標準出力・標準エラーをいったんメモリ上で受け取りますが、それをそのまま DB に保存しているわけではありません。
共通実行器では raw や filtered を timer.track(...) に渡していますが、Tracker::record() に保存されるのは
original_cmdrtk_cmdproject_pathinput_tokensoutput_tokenssaved_tokenssavings_pctexec_time_ms
です。出力本文そのものを格納するカラムはありません。根拠: src/core/runner.rs:68-121, src/core/tracking.rs:263-272, src/core/tracking.rs:351-385
rtk proxy でも子プロセスの stdout/stderr を取り込みますが、最終的に tracking に渡すだけで、保存先は同じ token 集計テーブルです。根拠: src/main.rs:2116-2210, src/core/tracking.rs:351-385
telemetry 用の集計では、フルコマンドではなく短縮した情報だけを使う意図がコードにあります。
top_commands()はrtk_cmdから 2語目だけを抜いて command name にしている 根拠:src/core/tracking.rs:912-923top_passthrough()はoriginal_cmdの先頭語だけを使う 根拠:src/core/tracking.rs:960-975low_savings_commands()はrtk_cmdを最大3語に切り詰める 根拠:src/core/tracking.rs:989-1003ecosystem_mix()は command を category 化して比率だけ送る 根拠:src/core/tracking.rs:1076-1138
つまり、ローカル DB には比較的詳しい文字列が残る一方、telemetry payload はそれを集計・短縮してから送る実装です。
「外部送信は限定的」とはいえ、ローカル保存 はあります。
commands テーブルには
original_cmdrtk_cmdproject_path
が保存されます。根拠: src/core/tracking.rs:263-289, src/core/tracking.rs:368-381
また parse_failures テーブルには
raw_commanderror_message
が保存されます。根拠: src/core/tracking.rs:312-318, src/core/tracking.rs:401-418
そのため、
- ローカル端末上の履歴 DB にフルコマンドが残る
- parse failure の文脈によってはエラーメッセージに機微情報が混ざる可能性がある
という点は、外部送信とは別のローカル情報管理リスクとして認識しておくべきです。
送信先 URL は option_env!("RTK_TELEMETRY_URL") でビルド時埋め込みなので、このリポジトリのソースだけでは
- 実際の送信先ホスト
- 手元の配布バイナリに URL が埋め込まれているか
は断定できません。根拠: src/core/telemetry.rs:14, src/core/telemetry_cmd.rs:162-165
つまり、このソースコードから言えるのは「送信機構はあるが、送信先はビルド成果物依存」 までです。
rtk は curl, wget, aws, npm, pnpm など、もともとネットワーク通信を行う CLI もラップします。これらの通信は RTK が勝手に追加した送信ではなく、子コマンド本来の通信 です。
今回の監査対象である「rtk 自身が裏でコマンドラインや出力を外へ送るか」という点では、主に telemetry を見ればよい、という整理になります。
現時点の評価は次の通りです。
- NG と断じるほどの隠し送信実装は見当たらない
- ただし opt-in telemetry 実装は存在する
- telemetry payload はコード上、集計情報中心で、出力本文やフル引数は直接送っていない
- 一方で ローカル SQLite にはフルコマンドや project path が保存される
- 配布済みバイナリの最終挙動は、ビルド時埋め込みの telemetry URL 有無に依存する
したがって、セキュリティ監査的には
- ソースだけを見る限り、
rtkは「常時コマンド内容や実行結果を外部送信するタイプ」ではない - ただし telemetry を完全に嫌うなら、
rtk telemetry disableまたはRTK_TELEMETRY_DISABLED=1を使うのが安全 - さらに厳密に見るなら、利用中バイナリに
RTK_TELEMETRY_URLが埋め込まれているかをバイナリ解析で確認するとよい
という結論です。
公式ドキュメント側も、telemetry は
- デフォルト無効
- 明示同意が必要
- フルコマンドや引数、ファイルパスは送らない
と説明しています。根拠: docs/TELEMETRY.md:3, docs/TELEMETRY.md:24-27, docs/TELEMETRY.md:109-117, docs/TELEMETRY.md:119-133
今回のコード読解結果は、少なくとも主要実装についてはこの説明と大きく矛盾していません。
このプログラムを利用するにあたり SQLite ファイルはどこに生成されるのか知りたい。セキュリティ監査観点で、この SQLite ファイルをどのように扱うことが望ましいか見極めたい。SQLite ファイル中身のデータベーススキーマ構成を知りたい。それぞれテーブルに、 rtk をどのように実行したとき、どのような情報が保管されるのか知りたい。rtk gain したとき、どのようなクエリで、どのように集計しているのか知りたい。以上をソースコード読解して調べてほしい。調べた結果を reading/003.md として保存してほしい。なお既にこのパソコン内に rtk コマンドはインストール済であり、手元で rtk ls などと実行した結果がある。SQLite ファイルの中身を覗き込んで調査の補助として使ってよい。
- SQLite ファイルの保存先は、優先順位つきで決まります。
-
- 環境変数
RTK_DB_PATH
- 環境変数
-
config.tomlの[tracking].database_path
-
- OS 既定の local data dir 配下の
rtk/history.db
- OS 既定の local data dir 配下の
- 根拠:
src/core/tracking.rs:1156-1171,src/core/constants.rs:1-6
-
- この macOS 環境では、実際に
history.dbは/Users/${USER}/Library/Application Support/rtk/history.dbにありました。rtk configが示した設定ファイルは/Users/${USER}/Library/Application Support/rtk/config.tomlでした。 - 追跡 DB には少なくとも
commandsとparse_failuresの 2 テーブルがあります。 rtk gainは、この DB を読んで集計するだけで、集計 SQL の大半はsrc/core/tracking.rsにあります。表示整形はsrc/analytics/gain.rsです。- セキュリティ監査観点では、この DB は「出力本文」は持たない一方で、「実行コマンド文字列」「カレントディレクトリ由来の絶対パス」「parse error 文字列」は保存するため、ローカル機微情報の塊として扱うのが妥当です。
get_db_path() は次の順で DB パスを決めています。
RTK_DB_PATHconfig.tomlのtracking.database_pathdirs::data_local_dir()/rtk/history.db
根拠:
src/core/tracking.rs:1156-1171src/core/constants.rs:1-6src/core/config.rs:34-49
つまり、デフォルト名は tracking.db ではなく history.db です。コードコメントや一部 docs には古い tracking.db 表記が残っていますが、現行コードの定数は HISTORY_DB = "history.db" です。
rtk --versionはrtk 0.36.0rtk configは/Users/${USER}/Library/Application Support/rtk/config.tomlを表示- 同ディレクトリに
history.dbが存在
確認できたファイル:
/Users/${USER}/Library/Application Support/rtk/history.db
実 DB の .schema とコードの CREATE TABLE は一致していました。
CREATE TABLE commands (
id INTEGER PRIMARY KEY,
timestamp TEXT NOT NULL,
original_cmd TEXT NOT NULL,
rtk_cmd TEXT NOT NULL,
input_tokens INTEGER NOT NULL,
output_tokens INTEGER NOT NULL,
saved_tokens INTEGER NOT NULL,
savings_pct REAL NOT NULL,
exec_time_ms INTEGER DEFAULT 0,
project_path TEXT DEFAULT ''
);
CREATE INDEX idx_timestamp ON commands(timestamp);
CREATE INDEX idx_project_path_timestamp ON commands(project_path, timestamp);根拠:
src/core/tracking.rs:262-309- 実 DB
.schema
CREATE TABLE parse_failures (
id INTEGER PRIMARY KEY,
timestamp TEXT NOT NULL,
raw_command TEXT NOT NULL,
error_message TEXT NOT NULL,
fallback_succeeded INTEGER NOT NULL DEFAULT 0
);
CREATE INDEX idx_pf_timestamp ON parse_failures(timestamp);根拠:
src/core/tracking.rs:311-323- 実 DB
.schema
実測では以下でした。
commands: 5 件parse_failures: 1 件
TimedExecution::track() または TimedExecution::track_passthrough() が呼ばれると、Tracker::record() に流れて commands へ INSERT されます。
根拠:
src/core/tracking.rs:1292-1305src/core/tracking.rs:1328-1333src/core/tracking.rs:351-385
この設計なので、各種 src/cmds/* でフィルタ成功時だけでなく、fallback や passthrough 系でも記録されます。main.rs の fallback 経路でも track() / track_passthrough() が呼ばれています。
根拠:
src/main.rs:1145-1151src/main.rs:1173-1175src/core/README.md:116-117
id- 連番の主キー
timestampUtc::now().to_rfc3339()で入る UTC 時刻
original_cmd- 素のコマンド文字列
- 例:
ls -la /path
rtk_cmd- RTK 側での表示用コマンド文字列
- 例:
rtk ls -la /path
project_path- 記録時点の
current_dir().canonicalize()結果 - つまり実行時 cwd の絶対パス
- 記録時点の
input_tokens- 生出力文字列の概算 token 数
output_tokens- RTK 出力文字列の概算 token 数
saved_tokensinput_tokens - output_tokens
savings_pct(saved_tokens / input_tokens) * 100
exec_time_msTimedExecution開始からの経過ミリ秒
根拠:
src/core/tracking.rs:359-380src/core/tracking.rs:1201-1222src/core/tracking.rs:1292-1305
厳密 tokenizer ではなく、ceil(text.len() / 4.0) の近似です。
根拠:
src/core/tracking.rs:1201-1222
track_passthrough() は input_tokens=0, output_tokens=0 で保存します。したがって saved_tokens=0, savings_pct=0.0 です。
根拠:
src/core/tracking.rs:1328-1333
これは「出力を捕捉していない interactive/streaming 系コマンドでも、実行時間だけは残す」ための扱いです。
このマシンの commands には実際に次のような値が入っていました。
original_cmd:ls -la /Users/${USER}/tmp/pstree-mem/dist/rtk_cmd:rtk ls -la /Users/${USER}/tmp/pstree-mem/dist/project_path:/Users/${USER}/tmp/pstree-meminput_tokens:81output_tokens:22saved_tokens:59savings_pct:72.8395061728395exec_time_ms:4
ここから分かるのは、ファイル内容本文は入っていないが、実行対象パスや作業プロジェクトの絶対パスはそのまま入る ということです。
Clap で想定外のサブコマンドや引数になって fallback 経路へ入ったとき、record_parse_failure_silent() 経由で parse_failures に書かれます。
根拠:
src/main.rs:1076-1180src/core/tracking.rs:1193-1199src/core/tracking.rs:401-418
timestamp- 記録時刻
raw_command- ユーザーが打ったコマンド文字列
error_message- parse error 文字列
fallback_succeeded- fallback 実行に成功したら
1 - コマンド自体を起動できなければ
0
- fallback 実行に成功したら
このマシンでは 1 件あり、内容は次でした。
raw_command:showerror_message:error: unrecognized subcommand 'show' ...fallback_succeeded:0
このテーブルも、入力されたコマンド文字列とエラーテキストがそのまま残る 点が監査上のポイントです。
rtk gain の既定表示は src/analytics/gain.rs の run() から tracker.get_summary_filtered(...) を呼びます。
根拠:
src/analytics/gain.rs:15-63
ただし総計は SQL の SUM(...) 一発ではなく、まず次のクエリで全行を取り、Rust 側で合計しています。
SELECT input_tokens, output_tokens, saved_tokens, exec_time_ms
FROM commands
WHERE (?1 IS NULL OR project_path = ?1 OR project_path GLOB ?2)その後 Rust 側で:
total_commandstotal_inputtotal_outputtotal_savedtotal_time_ms
を加算し、
avg_savings_pct = total_saved / total_input * 100avg_time_ms = total_time_ms / total_commands
を計算します。
根拠:
src/core/tracking.rs:508-566
重要なのは、平均節約率は「各行の savings_pct の平均」ではなく、総保存 token / 総入力 token の比率 だということです。
既定表示の「By Command」は次の SQL です。
SELECT rtk_cmd, COUNT(*), SUM(saved_tokens), AVG(savings_pct), AVG(exec_time_ms)
FROM commands
WHERE (?1 IS NULL OR project_path = ?1 OR project_path GLOB ?2)
GROUP BY rtk_cmd
ORDER BY SUM(saved_tokens) DESC
LIMIT 10根拠:
src/core/tracking.rs:569-595
つまりコマンド別には、
- 件数
- saved token 合計
savings_pct平均exec_time_ms平均
を出しています。
グラフ用の by_day は次の SQL です。
SELECT DATE(timestamp), SUM(saved_tokens)
FROM commands
WHERE (?1 IS NULL OR project_path = ?1 OR project_path GLOB ?2)
GROUP BY DATE(timestamp)
ORDER BY DATE(timestamp) DESC
LIMIT 30根拠:
src/core/tracking.rs:597-619
これを Rust 側で reverse() して古い日付から描画します。
rtk gain --history は最近 N 件を次で取得します。
SELECT timestamp, rtk_cmd, saved_tokens, savings_pct
FROM commands
WHERE (?1 IS NULL OR project_path = ?1 OR project_path GLOB ?2)
ORDER BY timestamp DESC
LIMIT ?3根拠:
src/core/tracking.rs:868-898src/analytics/gain.rs:220-248相当の表示処理
ここでは original_cmd や project_path は表示に使っていませんが、DB には残っています。
SELECT
DATE(timestamp) as date,
COUNT(*) as commands,
SUM(input_tokens) as input,
SUM(output_tokens) as output,
SUM(saved_tokens) as saved,
SUM(exec_time_ms) as total_time
FROM commands
WHERE (?1 IS NULL OR project_path = ?1 OR project_path GLOB ?2)
GROUP BY DATE(timestamp)
ORDER BY DATE(timestamp) DESCRust 側で:
savings_pct = saved / input * 100avg_time_ms = total_time / commands
を計算。
根拠:
src/core/tracking.rs:643-692
SELECT
DATE(timestamp, 'weekday 0', '-6 days') as week_start,
DATE(timestamp, 'weekday 0') as week_end,
COUNT(*) as commands,
SUM(input_tokens) as input,
SUM(output_tokens) as output,
SUM(saved_tokens) as saved,
SUM(exec_time_ms) as total_time
FROM commands
WHERE (?1 IS NULL OR project_path = ?1 OR project_path GLOB ?2)
GROUP BY week_start
ORDER BY week_start DESC根拠:
src/core/tracking.rs:716-767
SELECT
strftime('%Y-%m', timestamp) as month,
COUNT(*) as commands,
SUM(input_tokens) as input,
SUM(output_tokens) as output,
SUM(saved_tokens) as saved,
SUM(exec_time_ms) as total_time
FROM commands
WHERE (?1 IS NULL OR project_path = ?1 OR project_path GLOB ?2)
GROUP BY month
ORDER BY month DESC根拠:
src/core/tracking.rs:791-840
rtk gain --failures は parse_failures を見ます。中では少なくとも次を実行しています。
SELECT COUNT(*) FROM parse_failures;
SELECT COUNT(*) FROM parse_failures WHERE fallback_succeeded = 1;
SELECT raw_command, COUNT(*) as cnt
FROM parse_failures
GROUP BY raw_command
ORDER BY cnt DESC
LIMIT 10;
SELECT timestamp, raw_command, error_message, fallback_succeeded
FROM parse_failures
ORDER BY timestamp DESC
LIMIT 10;根拠:
src/core/tracking.rs:421-488src/analytics/gain.rs:359-406
rtk gain -p は resolve_project_scope() で現在ディレクトリを正規化し、その絶対パスを project_path フィルタに流します。
根拠:
src/analytics/gain.rs:29-30src/analytics/gain.rs:90-98src/analytics/gain.rs:290-296
SQL 側では
WHERE (?1 IS NULL OR project_path = ?1 OR project_path GLOB ?2)になっており、現在ディレクトリそのものか、その配下サブディレクトリも対象にします。LIKE ではなく GLOB を使っているので、パス中の _ や % がワイルドカード扱いされません。
根拠:
src/core/tracking.rs:40-55src/core/tracking.rs:508-520
実際に history.db に対して rtk gain 相当の集計を走らせると、以下でした。
- 総コマンド数:
5 - 総 input tokens:
339 - 総 output tokens:
62 - 総 saved tokens:
277 - 総実行時間:
19ms
日次・週次・月次はすべて 2026-04-11 / 2026-04-06..2026-04-12 / 2026-04 の 1 バケットにまとまっていました。rtk gain --daily --weekly --monthly の出力もこれと一致しました。
この DB は「生の標準出力本文」を持たないので、ログ全文保存 DB ほど重くはありません。ただし、次はそのまま入ります。
original_cmdrtk_cmdproject_pathraw_commanderror_message
つまり、以下の漏えいは普通に起こり得ます。
- 開発対象ディレクトリ名、社名、案件名、ユーザー名
- コマンド引数に含めたパス、ブランチ名、ファイル名
- 誤って引数に載せた secret 断片
- parse error に含まれる内部パスやコマンド断片
監査観点では、少なくとも次の扱いが妥当です。
history.dbを「個人端末ローカル限定の機微データ」とみなす- バックアップ対象にするなら暗号化ストレージ前提にする
- サポート依頼や不具合報告時に、この DB をそのまま第三者へ渡さない
- MDM / EDR / DLP の監査対象に入れる
- 共有端末ではユーザーごとのホーム権限を厳密に分ける
- CI や共有 VM では
RTK_DB_PATHを隔離パスへ向けるか、利用ポリシー自体を決める
Config には tracking.enabled がありますが、今回読んだ範囲では Tracker::record() や TimedExecution::* がこれを参照していません。検索上も database_path 以外で tracking.* が使われていませんでした。
根拠:
src/core/config.rs:34-49src/core/tracking.rs:1156-1166
したがって、設定ファイルに enabled = false を書いても、少なくとも現行実装では tracking 停止にならない可能性が高い です。
削除期限は DEFAULT_HISTORY_DAYS 定数で固定されており、config.tracking.history_days を読んでいません。
根拠:
src/core/constants.rs:6src/core/tracking.rs:388-397
したがって、設定ファイルで retention を変えられるように見えても、現行実装では 90 日固定運用の可能性が高い です。
これは監査上、「設定と実装がずれている」点として押さえておく価値があります。
- 保存先の実体は現行コード上
history.db - 保存場所は
RTK_DB_PATH→config.toml→ OS 既定 data dir の順 - この macOS では
/Users/${USER}/Library/Application Support/rtk/history.db - 主要テーブルは
commandsとparse_failures commandsにはコマンド文字列、cwd 絶対パス、概算 token 数、節約率、実行時間が入るparse_failuresには parse 失敗時の生コマンドとエラー文字列が入るrtk gainはこの DB を read-only に集計して表示する- 出力本文は常設保存していない
- ただしコマンド文字列とパスは十分に機微なので、ローカル秘密情報として扱うべき
- さらに
tracking.enabled/history_daysはコード上は期待どおり効いていない可能性がある
SQLite ファイルを削除したり、SQLite ファイル内のテーブルを削除する機構は、rtk コマンドのサブコマンドやオプションとして存在していますか。ソースコード読解して調べてほしい。調べた結果を reading/004.md として保存してほしい。
rtkに SQLite ファイル自体を削除するサブコマンド は存在します。rtk telemetry forget
- ただしこれは「tracking DB 専用メンテナンスコマンド」というより、telemetry 忘却処理の一部としてローカル DB ファイルを削除する 実装です。
- 一方で、SQLite ファイル内のテーブルを削除するサブコマンドやオプションは、コード上見当たりません。
DROP TABLE commandsDROP TABLE parse_failures- テーブル全消去のための
DELETE FROM ...を明示的に実行する CLI VACUUM,TRUNCATE,reset-dbのような CLI は見つかりませんでした。
- なお内部実装としては、追記のたびに 90日より古い行を
DELETEする自動クリーンアップ はあります。ただしこれはユーザーが明示的に叩くサブコマンドではありません。
あります。TelemetrySubcommand に Forget が定義されています。
根拠:
src/core/telemetry_cmd.rs:4-10src/main.rs:546-550
run_forget() の中で、ローカル tracking DB を std::fs::remove_file() で削除しています。
let db_path = dirs::data_local_dir()
.unwrap_or_else(|| std::path::PathBuf::from("."))
.join(super::constants::RTK_DATA_DIR)
.join(super::constants::HISTORY_DB);
if db_path.exists() {
match std::fs::remove_file(&db_path) {
Ok(()) => println!("Local tracking database deleted: {}", db_path.display()),
Err(e) => eprintln!("rtk: could not delete {}: {}", db_path.display(), e),
}
}根拠:
src/core/telemetry_cmd.rs:109-158
したがって、SQLite ファイル丸ごとの削除機構は rtk telemetry forget として存在する、が答えです。
ここは注意点があります。
tracking DB を通常開くときは、get_db_path() が次の優先順位でパスを決めます。
RTK_DB_PATHconfig.tomlのtracking.database_path- OS 既定パスの
rtk/history.db
根拠:
src/core/tracking.rs:1156-1171
しかし rtk telemetry forget は get_db_path() を使っていません。dirs::data_local_dir()/rtk/history.db を直接組み立てて削除しています。
根拠:
src/core/telemetry_cmd.rs:131-140src/core/constants.rs:1-2
つまり、少なくとも現行コードでは:
- 既定パスの
history.dbは削除対象 RTK_DB_PATHで別場所に置いた DB は削除対象外tracking.database_pathで別場所に置いた DB も削除対象外
と読むのが自然です。
これは「DB 削除機構はあるが、カスタム DB パスを完全には考慮していない」という実装差分です。
コード上、見当たりません。
DROP TABLE commandsDROP TABLE parse_failuresDROP TABLE- テーブル初期化専用のサブコマンド
rtk gain --resetrtk telemetry clear-dbrtk config reset-tracking
少なくとも src/main.rs のコマンド定義と src/core/telemetry_cmd.rs を見る限り、公開 CLI で tracking DB のテーブルを削除する導線はありません。
根拠:
src/main.rs:543-550src/core/telemetry_cmd.rs:4-18
TelemetrySubcommand は以下の 4 つだけです。
statusenabledisableforget
Tracker::record() と record_parse_failure() は最後に cleanup_old() を呼びます。
根拠:
src/core/tracking.rs:351-385src/core/tracking.rs:401-418
cleanup_old() は 90 日より古い行を削除します。
DELETE FROM commands WHERE timestamp < ?1
DELETE FROM parse_failures WHERE timestamp < ?1根拠:
src/core/tracking.rs:388-398
ただしこれは ユーザー向けサブコマンドではなく、レコード追加時に内部で自動実行される housekeeping です。
ここでやっているのは行削除だけです。
DELETE FROM commands WHERE timestamp < ?1DELETE FROM parse_failures WHERE timestamp < ?1
であって、
DROP TABLE commandsDROP TABLE parse_failures
ではありません。
つまり、DB を空にする機構ではないし、テーブルそのものを消す機構でもありません。
今回の読解範囲では、ありません。
gain は tracking DB を読むためのコマンドで、削除系オプションは見当たりません。実装も Tracker::new() のうえで集計関数を呼ぶ read path 中心です。
根拠:
src/analytics/gain.rs:15-63
また、main.rs 上も tracking DB メンテナンス専用の別サブコマンドは見当たりません。
ドキュメントには次の記述があります。
rtk telemetry forgetでローカルデータ削除docs/TELEMETRY.md:127-154
- DB を消したければ手動で
rm ~/.local/share/rtk/history.dbdocs/guide/analytics/gain.md:128-131
つまり docs 上も基本スタンスは:
- CLI で消すなら
rtk telemetry forget - それ以外は手動で DB ファイルを削除
であり、テーブル単位削除の公式 CLI は想定されていない ように見えます。
監査用に短くまとめると次の通りです。
- SQLite ファイル削除機構
- あり
rtk telemetry forget- ただし telemetry 忘却フローの一部
- SQLite 内テーブル削除機構
- 公開 CLI としては見当たらない
- 内部の行削除機構
- あり
- 新規記録時に 90 日超の古い行だけ自動削除
- 実装上の注意点
rtk telemetry forgetは既定パスのhistory.dbを直接削除しており、RTK_DB_PATHやtracking.database_pathのカスタム DB までは消さない可能性が高い
質問への直接回答は次です。
-
SQLite ファイルを削除する機構はあるか
- ある
rtk telemetry forget
-
SQLite ファイル内のテーブルを削除する機構はあるか
- 少なくとも公開サブコマンドやオプションとしては存在しない
-
その他の削除系挙動はあるか
- ある
- ただし内部の retention cleanup で、古い行を
DELETEするだけ
rtk が生成する SQLite ファイルの中身のデータは無期限に保管され肥大化していくのか知りたい。reading/*.md によれば 90 日経過したレコードは削除するとのことだった。それは rtk コマンドで何をしたタイミングで発動するのか知りたい。ソースコード読解して調べてほしい。
commandsテーブルとparse_failuresテーブルのレコードは、設計上は無期限保存ではありません。- 実装では
DEFAULT_HISTORY_DAYS = 90になっており、90 日より古い行を削除する自動クリーンアップがあります。- 根拠:
src/core/constants.rs:6,src/core/tracking.rs:388-397
- 根拠:
- ただしこの削除は、
rtkのあらゆる起動時に走るわけではありません。 - 実際に発動するのは、新しい tracking レコードを書き込むときです。
commandsに INSERT した直後parse_failuresに INSERT した直後- 根拠:
src/core/tracking.rs:351-385,src/core/tracking.rs:402-418
- したがって、たとえば
rtk gainのような DB を読むだけのコマンドでは cleanup は発動しません。- 根拠:
src/analytics/gain.rs:29-40
- 根拠:
- さらに、今回読んだ範囲では
VACUUMやauto_vacuumの設定は見当たりません。そのため、古い行が削除されても SQLite ファイルサイズが即座に小さくなるとは限りません。
あります。保持期間は DEFAULT_HISTORY_DAYS 定数で 90 日です。
pub const DEFAULT_HISTORY_DAYS: i64 = 90;根拠:
src/core/constants.rs:6
削除処理本体は Tracker::cleanup_old() です。
fn cleanup_old(&self) -> Result<()> {
let cutoff = Utc::now() - chrono::Duration::days(DEFAULT_HISTORY_DAYS);
self.conn.execute(
"DELETE FROM commands WHERE timestamp < ?1",
params![cutoff.to_rfc3339()],
)?;
self.conn.execute(
"DELETE FROM parse_failures WHERE timestamp < ?1",
params![cutoff.to_rfc3339()],
)?;
Ok(())
}根拠:
src/core/tracking.rs:388-398
つまり、少なくともコード上は
commandsparse_failures
の両方について、90 日より古い行は削除対象です。
Tracker::record() は commands へ INSERT したあと、必ず self.cleanup_old()? を呼びます。
根拠:
src/core/tracking.rs:351-385
該当箇所:
self.conn.execute(
"INSERT INTO commands (...) VALUES (...)",
...
)?;
self.cleanup_old()?;したがって、通常の tracking 記録が 1 件でも発生したタイミングで、90 日超の古い行の削除が走ります。
Tracker::record_parse_failure() も parse_failures へ INSERT したあと、同じく self.cleanup_old()? を呼びます。
根拠:
src/core/tracking.rs:402-418
つまり、parse failure を 1 件記録したタイミングでも cleanup が走ります。
多くのコマンド実装は TimedExecution::track() を使って最後に tracking を記録します。
TimedExecution::track() は内部で Tracker::new() を作り、tracker.record(...) を呼びます。
根拠:
src/core/tracking.rs:1292-1305
したがって、たとえば rtk git ..., rtk ls ..., rtk cargo ... などで tracking が記録される経路を通れば cleanup も一緒に走る、という理解でよいです。
TimedExecution::track_passthrough() も内部で tracker.record(...) を呼びます。
根拠:
src/core/tracking.rs:1328-1333
そのため、token 数を 0/0 で記録する passthrough 系の tracking でも cleanup は走ります。
run_fallback() では、成功時も失敗時も record_parse_failure_silent(...) が呼ばれます。これは内部で tracker.record_parse_failure(...) を呼びます。
根拠:
src/main.rs:1145-1157src/main.rs:1173-1180src/core/tracking.rs:1193-1198
したがって、Clap 解析に失敗して fallback 経路へ入ったケースでも cleanup が走ります。
Tracker::new() は DB を開いてテーブルや index を用意するだけで、cleanup_old() は呼びません。
根拠:
src/core/tracking.rs:249-326
つまり、DB を開くだけでは古い行は削除されません。
rtk gain は Tracker::new() で DB を開いたあと、集計メソッドを呼んで表示するだけです。ここには cleanup 呼び出しがありません。
根拠:
src/analytics/gain.rs:29-40
したがって、
rtk gainrtk gain --historyrtk gain --failures
のような 読むだけの操作では、90 日削除の housekeeping は発動しない と読むのが自然です。
コードの意図としては、commands と parse_failures のレコードは 直近 90 日ぶんに保つ設計です。
そのため、「新しい tracking が継続的に発生する」前提なら、行数は基本的に 90 日窓で頭打ちになります。
cleanup は「経過時間だけ」で自動実行されるのではなく、次回の record / parse failure 記録時にまとめて走る方式です。
したがって、
- 100 日前の行がある
- その後しばらく
rtk gainしか使わない
という状況では、古い行はその間ずっと DB に残ります。
次に tracking を伴う rtk 実行が発生した時点で、そこで初めて削除されます。
今回読んだ範囲では、
VACUUMPRAGMA auto_vacuumPRAGMA incremental_vacuum
は見当たりませんでした。確認できた PRAGMA は journal_mode=WAL と busy_timeout だけです。
根拠:
src/core/tracking.rs:255-260src/core/tracking.rs:388-397
そのため、古い行を DELETE しても、SQLite ファイル自体のサイズがすぐ小さくなる保証はありません。 この点では「データ行は 90 日で掃除される」が、「ファイルサイズは運用次第でじわじわ大きく見える可能性がある」と整理するのが正確です。
質問への直接回答を短くまとめると次の通りです。
-
rtkの SQLite データは無期限保存ではないか- 設計上は無期限保存ではない
commands/parse_failuresの 90 日超レコードを削除する実装がある
-
90 日削除は何のタイミングで発動するか
- 新しい tracking レコードを書いた直後
- 新しい parse failure レコードを書いた直後
-
rtk gainを実行したタイミングで発動するか- 少なくとも現行コード上はしない
rtk gainは DB を読むだけで cleanup を呼ばない
-
SQLite ファイルは肥大化しないか
- レコード件数は 90 日窓で抑える意図
- ただし cleanup は write 時のみ
- さらに
VACUUMが見当たらないので、ファイルサイズは DELETE 後も即縮小しない可能性が高い
rtk コマンドを利用するが、SQLite ファイルを生成させない、記録させない、という利用方法は存在するか調べてほしい。rtk コマンドで特定のオプションで 1 を付けて 1 回だけ実行するとか、設定ファイルを置くとか、環境変数の何かに 1 を設定するとか。ソースコード読解して調べてほしい。
- 公式に用意された「tracking を無効化する CLI オプション / 環境変数 / 設定」は、現行コード上は見当たりませんでした。
config.tomlには[tracking].enabledという項目が存在し、ドキュメントも「enable/disable token tracking」と説明しています。- しかし、実装側でこの値を参照して tracking を止めるコードは見つかりませんでした。
- 根拠:
src/core/config.rs:35-48と、tracking.enabledの参照検索結果
- 同様に
tracking.history_daysも設定項目として存在しますが、cleanup 側は 固定のDEFAULT_HISTORY_DAYS = 90を使っており、実装上は設定値を使っていません。- 根拠:
src/core/config.rs:35-48,src/core/tracking.rs:388-389
- 根拠:
- したがって、正攻法として「SQLite を生成しない・記録しない」利用方法は、ソースコード上は実装されていないと結論づけるのが妥当です。
ただし、実装の癖を使った非公式な回避策はあります。
- tracking は
Tracker::new()に失敗すると静かに諦める実装です。- 根拠:
src/core/tracking.rs:1195-1198,src/core/tracking.rs:1297-1305,src/core/tracking.rs:1331-1333
- 根拠:
- そのため、
RTK_DB_PATHを「SQLite を開けないパス」に向けると、コマンド実行自体は続くが tracking だけ失敗して記録されない動きになります。 - ただしこれは正式サポートされた使い方ではなく、実装依存のワークアラウンドです。
少なくとも main.rs 上、--no-track, --disable-tracking, --no-history のような tracking 無効化専用 CLI フラグは見当たりませんでした。
根拠:
src/main.rsのオプション検索
つまり、
rtk --no-track ...rtk --disable-tracking ...rtk gain --no-history
のような「1 回だけ記録しない」ための公開オプションは、現行コードには見当たりません。
Config の TrackingConfig には次のフィールドがあります。
pub struct TrackingConfig {
pub enabled: bool,
pub history_days: u32,
pub database_path: Option<PathBuf>,
}デフォルトも enabled: true です。
根拠:
src/core/config.rs:35-48
ドキュメントにも次のように書かれています。
[tracking]
enabled = true # enable/disable token tracking
history_days = 90 # retention in days (auto-cleanup)
database_path = "/custom/path/tracking.db"根拠:
docs/guide/getting-started/configuration.md:24-29src/core/README.md:64-67
コード全体を見ても、config.tracking.enabled を参照して
Tracker::new()を呼ばないrecord()をスキップする- SQLite を作らない
といった分岐は見当たりませんでした。
一方で get_db_path() は database_path だけを見ています。
fn get_db_path() -> Result<PathBuf> {
if let Ok(custom_path) = std::env::var("RTK_DB_PATH") {
return Ok(PathBuf::from(custom_path));
}
if let Ok(config) = crate::core::config::Config::load() {
if let Some(db_path) = config.tracking.database_path {
return Ok(db_path);
}
}
...
}根拠:
src/core/tracking.rs:1156-1171
つまり、[tracking] enabled = false を設定しても、現行コード上は tracking 停止にはつながりません。
tracking に関係する環境変数として実装上確認できたのは、少なくとも以下です。
RTK_DB_PATH- DB ファイルの保存先を変えるだけ
RTK_TELEMETRY_DISABLED- telemetry の送信停止用
このうち RTK_TELEMETRY_DISABLED=1 は ネットワーク telemetry を止めるだけで、SQLite tracking の停止ではありません。
根拠:
src/core/tracking.rs:1157-1165src/core/telemetry.rsREADME.md:443
つまり、
RTK_TELEMETRY_DISABLED=1rtk telemetry disable
では ローカル SQLite 記録は止まりません。
RTK_DB_PATH は最優先で DB パスを差し替えます。
根拠:
src/core/tracking.rs:1157-1159
これは本来、
- デフォルト位置に置きたくない
- 任意の場所に history.db を置きたい
ためのもので、tracking を無効化する目的の公式機能ではありません。
tracking 実装は TimedExecution::track() と TimedExecution::track_passthrough() に集約されています。
track() は毎回 Tracker::new() を作って record() を呼びます。
if let Ok(tracker) = Tracker::new() {
let _ = tracker.record(...);
}track_passthrough() も同様です。
根拠:
src/core/tracking.rs:1292-1305src/core/tracking.rs:1328-1333
さらに fallback 系の parse failure 記録も
if let Ok(tracker) = Tracker::new() {
let _ = tracker.record_parse_failure(...);
}です。
根拠:
src/core/tracking.rs:1195-1198
この設計から見ると、tracking を止める公式スイッチがない限り、通常の rtk 実行は記録しようとする構造です。
Tracker::new() は
- DB パスを決める
- 親ディレクトリを
create_dir_all Connection::open(&db_path)?
という流れです。
根拠:
src/core/tracking.rs:249-255
そして、track() / track_passthrough() / record_parse_failure_silent() は、Tracker::new() が失敗した場合にエラーを上に返さず黙って tracking を諦めます。
根拠:
src/core/tracking.rs:1195-1198src/core/tracking.rs:1297-1305src/core/tracking.rs:1331-1333
なので例えば、
env RTK_DB_PATH=/dev/null/history.db rtk ls readingのように、SQLite を開けないパスへ向けると、tracking 初期化に失敗して記録されない挙動になります。
この環境でも上のコマンドを軽く試したところ、rtk ls reading 自体は動作しつつ、tracking 側は失敗させられる構図でした。
ただしこれは次の意味で非推奨のワークアラウンドです。
- 実装依存であり将来壊れうる
rtk gainなど tracking DB を読むコマンドは当然壊れる- エラーパスを利用しているだけで、正式な disable 機能ではない
同じ理屈で、RTK_DB_PATH または tracking.database_path を
- 書けないディレクトリ
- 作成不能なパス
に向けても、tracking は失敗して黙ってスキップされる可能性があります。
ただしこれも正式サポートではなく、環境依存なので、「そういう実装上の逃げ道はある」以上の意味は持たせない方がよいです。
今回の読解では、少なくとも次のズレがありました。
-
tracking.enabled- ドキュメントでは enable/disable と説明
- しかし実装では参照されていない
-
tracking.history_days- ドキュメントでは設定可能と説明
- しかし cleanup は
DEFAULT_HISTORY_DAYS = 90固定を使用
根拠:
docs/guide/getting-started/configuration.md:24-29src/core/README.md:64-67src/core/config.rs:35-48src/core/tracking.rs:388-389
つまり、ドキュメントや config struct が示しているより、現行実装は tracking の ON/OFF や retention 設定に未対応と読むのが自然です。
質問への直接回答を短くまとめると次の通りです。
-
rtkを普通に使いつつ、SQLite を生成させない・記録させない公式な方法はあるか- 現行コード上は見当たらない
-
rtkの CLI オプションで 1 回だけ無効化できるか- 見当たらない
-
設定ファイルで無効化できるか
tracking.enabled = falseという項目はある- ただし 実装上は使われていないので無効化できない
-
環境変数で無効化できるか
- telemetry を止めるものはある
- しかし tracking/SQLite を止める専用環境変数は見当たらない
-
実装依存の回避策はあるか
- ある
RTK_DB_PATHを SQLite を開けないパスへ向けると、tracking 初期化失敗により記録されない- ただし これは非公式ワークアラウンド