sasacode ドキュメント
README では書ききれない、画面の見方、権限の判定の流れ、設定と同梱プラグインの全項目、プラグインの共有、ヘッドレス実行、困ったときの対処をまとめた。v0.9.9 時点の内容。
目次
01はじめに
インストール
curl -fsSL https://sasanokusa.com/sasacode/install.sh | sh
macOS(Apple Silicon / Intel)と Linux(x64 / arm64、glibc / musl、AVX2 のない CPU 向けの baseline 版)の単一バイナリが ~/.local/bin/sasacode に入る。Bun も Node.js も要らない。Windows は WSL から使う。
- インストーラーとバイナリは GitHub Releases の最新版から取り、SHA256 を確かめてから置く。
- 版を固定する:
SASACODE_VERSION=v0.9.9。置き場所を変える:SASACODE_INSTALL_DIR=/usr/local/bin。 - 更新は
sasacode update(インストーラーと同じ検証つき。--checkで確かめるだけ)か、同じインストールコマンドをもう一度実行する。新しい版が出ると起動時に一度だけ知らせる(設定の"updateCheck": falseで止まる)。削除は~/.local/bin/sasacodeと~/.sasacode(設定・セッション・プラグイン)を消す。
最初の設定
sasacode --version # 初回起動で ~/.sasacode/.env ができる
$EDITOR ~/.sasacode/.env # 使うプロバイダーのキーだけ埋める
sasacode # 対話モードで始める
.env には対応するプロバイダーのキーが空欄で並んでいる。空欄は「未設定」として扱うので、使うものだけ埋めればよい。キーの代わりに OS のキーチェーンに入れることもできる(キーの探し方)。
どのモデルで始まるか
-m provider/model を付けたそれを使う。model~/.sasacode/config.json(信頼したプロジェクトならプロジェクトの設定も)。.env の上から順に見る。openai-codex/gpt-5.5。起動してからは /model で一覧から選び直せる。
02TUI(対話モード)
画面の構成
- 会話:あなたの入力(背景色つき)、推論(
∴、既定では最後の2行だけ)、ツール呼び出し(●の色:灰=待ち、黄=実行中、緑=完了、赤=エラー)、応答。ctrl+o で推論とツール出力の全文を開く。 - 状態:実行中の表示と、実行中に送った(次のターンに届く)メッセージ。
- フッター:左から、モデル、推論の深さ、権限モード、コンテキストの使用量(使用量/上限と割合)、セッション ID、料金(分かるときだけ)。2行目はプラグインの状態(TODO、ゴール、MCP の接続数、バックグラウンドジョブ、要約中など)。
キー操作
| キー | 動作 |
|---|---|
| enter / shift+enter・alt+enter | 送信 / 改行 |
| ↑ ↓ | 入力履歴(~/.sasacode/history.jsonl、直近 200 件) |
| tab | 補完:スラッシュコマンド、その引数(/model のモデル名など)、ファイルパス |
| esc | 生成・ツール実行を中断。中断したことは次の入力でモデルに伝わる |
| 実行中に enter | メッセージを予約し、次のターンで届ける |
| ctrl+o | ツール出力と推論の折りたたみを切り替え |
| shift+tab | 権限モードを順に切り替え |
| pageup pagedown・ホイール | 会話をスクロール。上に戻っている間は右端にスクロールバーと「最新へ」 |
| ctrl+↑ / ctrl+↓ | 前 / 次の自分の入力へ |
| ctrl+home / ctrl+end | 会話の先頭 / 最新へ |
| ctrl+shift+f | 会話の中を検索(enter で次、shift+enter で前、esc で閉じる) |
| ドラッグ | 選択し、離すとクリップボードへコピー。ダブルクリックで単語、トリプルクリックで行 |
/exit・ctrl+c 2回・ctrl+d | 終了。使用量と再開コマンドの要約が端末に残る |
/copy は直前の応答全体をコピーする。コマンド
| コマンド | 内容 | 提供元 |
|---|---|---|
/model | プロバイダーから取った一覧から選ぶ。文字を打つと絞り込む。/model <provider/model> で直接、/model --refresh で取り直し | コア |
/effort | 推論の深さ(詳細) | コア |
/resume /clear /fork /session | 過去のセッション / 新しいセッション / 過去のメッセージから分岐 / ID と保存先 | コア |
/copy /permission /help /exit | 直前の応答をコピー / 権限モード / ヘルプ / 終了 | コア |
/usage | 使用量、プランの残り、日別グラフ(詳細) | usage |
/goal | セッションのゴール | goal |
/bg | バックグラウンドジョブの一覧・詳細・停止 | background-sessions |
/reconnect | 接続の復旧を待って再開(status で確認だけ) | auto-reconnect |
/compact | 会話を要約してコンテキストを空ける | compaction |
/undo | write / edit によるファイルの変更を1件戻す(list で一覧) | checkpoints |
/image | 画像を次のメッセージに添付(引数なしでクリップボード、clear で取り消し)。@パス やドラッグ&ドロップでも付けられる | image-attach |
/task | サブエージェントの一覧・詳細、send <id> <内容> で指示、stop <id> で停止 | subagent |
/presets /jev | 権限プリセットの一覧 / Jev の状態と直近の判定(/jev on・/jev off で切り替え。jev-guard を入れたとき) | permission-presets / jev-guard |
/mcp /skills /skill:<name> /browsr | MCP の接続状態(/mcp reconnect [name] で再接続。落ちたときは数回まで自動で再接続する) / Skills の一覧 / Skill を明示して使う / browsr の状態 | mcp / skills / browsr |
TUI の設定
| 設定 | 既定 | 内容 |
|---|---|---|
tui.altScreen | true | false で従来の表示(会話を端末のスクロールバックに残す) |
tui.bell | true | 30 秒以上かかった実行が終わったら端末のベルを鳴らす |
SASACODE_AMBIGUOUS_WIDTH | 自動 | ①のような幅の曖昧な文字を何マスで数えるか(1 / 2)。起動時に端末に問い合わせて合わせる |
03モデルとプロバイダー
| provider | API 形式 | キー |
|---|---|---|
anthropic | Anthropic Messages | ANTHROPIC_API_KEY(空なら SDK の ant auth login) |
openai / openai-chat | OpenAI Responses / Chat Completions | OPENAI_API_KEY |
openrouter | Chat Completions | OPENROUTER_API_KEY |
commandcode(-responses / -anthropic) | Command Code の各形式 | CMD_API_KEY |
ollama | Chat Completions(localhost:11434) | 不要 |
openai-codex | ChatGPT プランの Codex バックエンド | 不要(sasacode login) |
キーの探し方
export ANTHROPIC_API_KEY=…~/.sasacode/.env空欄は無視。security add-generic-password -s sasacode -a <provider> -wLinux:
secret-tool store --label sasacode service sasacode account <provider>.env と bunfig.toml。リポジトリが接続先(ANTHROPIC_BASE_URL など)を差し替えたり、起動時にコードを実行させたりできないようにするため。セッションのログには、使っているキーを [REDACTED] に置き換えてから書く。自前のサーバー
sasacode endpoint add pgx http://gpu-box:8000/v1 # 形式を判別して保存
sasacode endpoint add mygw https://llm.example.com/v1 --key-env MYGW_KEY
sasacode endpoint list
sasacode -m pgx/<モデル名>
GET /v1/models の応答から、OpenAI 形式か Anthropic 形式かを判別し、URL も SDK に合わせて整える。llama.cpp は /props、Ollama は /api/show から実際のコンテキスト長も取る。判別の結果は ~/.sasacode/endpoints.json にキャッシュする。表にないモデルのコンテキスト長が違うときは modelOverrides で直す。
{ "modelOverrides": { "pgx/qwen3.8-flash-next": { "contextWindow": 262144, "maxOutput": 32000 } } }
ChatGPT プラン
sasacode login でブラウザが開き、ChatGPT アカウントでログインすると openai-codex/… のモデルが API キーなしで使える。利用分はプランの Codex の枠から引かれ、残りは /usage plan で見られる。SSH の先などブラウザがこのマシンに戻れないときは、ログイン後にブラウザが表示した URL を貼り付ける。認証情報は ~/.sasacode/codex-auth.json(本人だけが読める)に置き、期限が近づけば自動で更新する。
推論の深さ(/effort・--thinking)
off / low / medium / high / xhigh / max の6段階。既定は high。送り方は API 形式ごとに違う。
| API 形式 | 送るもの |
|---|---|
| Anthropic Messages | adaptive thinking と effort。off なら thinking を付けない |
| OpenAI Chat Completions(OpenAI 互換の自前サーバーを含む) | reasoning_effort。off も none として送る(vLLM などは送らないと推論する) |
| OpenAI Responses・ChatGPT プラン | reasoning.effort |
OpenAI 形式のサーバーは受け付ける値がまちまちなので、断られたら次の候補で送り直し、通った値を覚えて次からはそれを使う(サーバーとモデルごと)。
| 段階 | 試す順番(→ は断られたら次) |
|---|---|
off | none → minimal → low → 送らない |
low | low → minimal → 送らない |
medium | medium → 送らない |
high | high → xhigh → medium → 送らない |
xhigh | xhigh → high → 送らない |
max | max → xhigh → high → 送らない |
| 確かめたサーバー | 結果 |
|---|---|
| vLLM(Qwen 3.8) | off で推論が止まる。high は受け付けず(ストリームの最初のイベントで断る)、xhigh になる |
| Command Code(DeepSeek V4.1) | none を受け付けない。推論は止められないので、off は low になる |
| Ollama | 推論に対応しないモデルは断るので、送らずにやり直す |
| ChatGPT プラン | off で推論が止まる |
04権限
ツールを実行する前に、ルール・権限モード・プラグインの順に判定する。判定は実行前の確認であって、隔離(サンドボックス)ではない。
判定の流れ
tool_call フック(プラグイン)引数の書き換えや判定。ここで deny なら終わり。permission フックが「確認」まで下げられる。&& ; | でつないだ全部が許可されているときだけ通す。$(…)・バッククォート・> を含むものは通さない。permission フック(プラグイン)ここまでの判定を変える。厳しくするのは自由、緩めるのは下限まで(モードの既定は許可まで、softDeny は確認まで、ルールは緩められない)。jev-guard はここで働く。権限モード
| モード | 作業ディレクトリ内の read | 内の write / edit | bash・外への操作・その他 |
|---|---|---|---|
edits(既定) | 許可 | 許可 | 確認 |
ask | 確認 | 確認 | 確認 |
agent | 許可 | モデルが判定(安全なら許可、それ以外は確認) | |
auto | 許可 | 許可 | 許可(deny ルールと ask ルールは効く) |
agent モードで判定するのは呼び出しを作ったのと同じモデルで、呼び出しの引数も読むため、モデルを誘導する文が判定も誘導しうる。利便のための機能で、プロンプトインジェクションへの防御ではない(それには deny / ask ルールと guard プリセットを使う)。
切り替えは shift+tab、/permission <mode>、--permission、設定の permissions.mode。
ルールの書き方
| ルール | 当てはまるもの |
|---|---|
bash | bash の呼び出しすべて |
bash(git status*) | git status で始まるコマンド(* はワイルドカード) |
edit(**/.env) write(src/**) | パスの glob(シンボリックリンクをたどった先で照合) |
mcp__github__* | MCP サーバー github のツール全部 |
bg_start(make*) | プラグインのツールも同じ書き方。bg_start は permissionsAs: "bash" なので、bash のルールも当たる |
{
"permissions": {
"allow": ["bash(bun test*)", "bash(git diff*)"],
"ask": ["bash(git push*)"],
"deny": ["read(**/.env)", "edit(**/.env)", "write(**/.env)", "bash(curl * | sh)"],
"softDeny": ["bash(git reset --hard*)"]
}
}
パスのルールは書いたツールにだけ効くので、.env を守るなら read / edit / write を並べ、サブディレクトリも含めるには **/ を付ける。コマンドのルールはコマンドの文字列に合わせるだけなので、オプションの順を変えたり絶対パスで呼んだりすれば当たらない。間違いを防ぐ柵であって、完全な防御ではない。
プリセット
plugins.settings["permission-presets"].presets で選ぶ(既定 ["guard"])。/presets で一覧。
| プリセット | 中身 |
|---|---|
guard | deny:sudo *、rm -rf /・/*、mkfs*、dd *of=/dev/*、パイプ先の sh・bash・zsh、chmod -R 777 /*softDeny: rm -rf ~*・$HOME*、git push --force*・-f*ask(auto でも確認): ssh、scp、sftp、リモートへの rsync |
read-only-shell | 読み取りだけのコマンドを許可:ls、cat、head、tail、wc、rg、grep、tree、file、which、git status/diff/log/show/branch/rev-parse。ファイルを書き出すオプションやコマンドを実行させるオプション(rg --pre、git diff --output、tree -o など)を含むものは確認に回す |
tests | テストと型チェックを許可:bun/npm/pnpm/yarn test、cargo test、go test、pytest、tsc --noEmit、bun run typecheck |
できないこと
- 許可した bash コマンドの中身(スクリプトが何をするか)までは見ない。
- 判定から実行までの間にリンクを差し替えるような競合は防げない。
- 信頼できないコードを扱うときは、コンテナなど OS の側で隔離する。
- 中断(esc)した後は、承認済みでもまだ始まっていないツールは実行しない。
Jev による判定(配布プラグイン jev-guard)
判断専用モデル Jev に、呼び出しが安全かを確率で答えさせ、上の permission フックで判定を変えるプラグイン。0.9.5 までは同梱していたが、既定で無効でキーも要るので、配布プラグインに分けた。入れた後は TUI で /jev on と打てばそのセッションで有効になり(/jev off で無効。/resume 後も保たれる)、いつも使うなら設定に書く。0.9.5 までの設定はそのまま使え、設定があるのにプラグインが入っていなければ起動時に入れ方を知らせる。
sasacode plugin install sasacode-plugin-jev-guard
{ "plugins": { "settings": { "jev-guard": { "enabled": true } } } }
| 元の判定 | Jev が「安全」 | Jev が「要確認」 | Jev が「危険」 |
|---|---|---|---|
| 許可(allow ルール・auto モード) | 許可 | 確認 | 拒否 |
| 確認(agent モード) | 許可 | 確認 | 確認 |
| softDeny | 確認 | 拒否 | 拒否 |
| 確認(それ以外) | 変えない(確認ダイアログに Jev の判定を添える) | ||
送るのは、ハーネスが集めた事実(コマンド、変更されうるパスとその git の状態、作業ディレクトリの内か外か)と、ユーザー自身の直近の依頼だけ。ツールの出力やファイルの中身は送らない。キーやトークンらしい文字列は伏せる。設定の全項目は 下の表。
05プロジェクトの信頼
クローンしたリポジトリの .sasacode/ は、そのままでは「制限を強める」ことしかできない。コードを実行するか、データの送り先を変えうるものは、最初に一覧を出して信頼するかを尋ねる(ヘッドレスは --trust-project)。
| プロジェクトの設定 | 信頼なしで使う |
|---|---|
model(全体の設定にあるプロバイダー)、models、thinking、instructions | 使う |
deny / ask ルールの追加、ツールの無効化、より厳しい権限モード、小さい maxTurns・maxRetries、toolSearch、tui | 使う |
.sasacode/plugins のプラグイン | 信頼が必要 |
providers(エンドポイント)、modelOverrides、mcpServers | 信頼が必要 |
plugins(無効化と設定)、allow ルール、緩い権限モード、大きい上限、プロジェクトにしかないプロバイダーを指す model | 信頼が必要 |
trustedProjects | 全体の設定でしか読まない |
答えは ~/.sasacode/trust.json に保存し、上の設定かプラグインのコードが変わったら、また尋ねる。全体の設定の trustedProjects に入れたプロジェクトは尋ねずに信頼する。
06設定リファレンス
~/.sasacode/config.json(全体)と <project>/.sasacode/config.json(プロジェクト)を合わせ、プロジェクトが優先する。権限ルールと disabled の配列は両方を合わせるので、全体の deny や無効化をプロジェクトから消すことはできない。型の合わない値と未知のキーは、警告を出して無視する。
| キー | 型・既定 | 内容 |
|---|---|---|
model | 文字列 | 起動時のモデル(provider/model) |
models | 文字列の配列 | /model の一覧の先頭に出すモデル |
thinking | high | 推論の深さ |
lang | ロケールで決まる | 画面の言語(ja / en)。TUI・CLI・同梱プラグインの表示がそろう。環境変数 SASACODE_LANG が優先。モデルに渡す文は訳さない |
providers.<name> | オブジェクト | api(openai-chat / openai-responses / anthropic、省略で判別)、baseUrl、apiKeyEnv、headers、defaultModel |
modelOverrides.<provider/model> | オブジェクト | contextWindow、maxOutput、price(100 万トークンあたりの USD:input・output・cacheRead・cacheWrite)、reasoning、images |
permissions | オブジェクト | mode、allow、ask、deny、softDeny |
instructions | 文字列 | システムプロンプトに足す文 |
maxTurns | 200 | 1回の依頼でモデルに送るリクエストの上限(0 で無制限) |
maxRetries | 8 | API エラー(429・5xx)の再試行の回数(最大 20) |
plugins.disabled | 配列 | 読み込まないプラグイン(同梱も含む) |
plugins.settings.<name> | オブジェクト | プラグインに渡す設定(同梱プラグインの設定) |
tools.disabled | 配列 | 使わないツール(組み込みも含む) |
mcpServers.<name> | オブジェクト | stdio:command、args、env、cwd / HTTP:url、headers。共通:disabled、alwaysLoad。${VAR} は環境変数から展開 |
toolSearch | {"mode":"auto","percent":10,"count":30} | MCP とプラグインのツール定義が、コンテキストの percent% 以上か count 個以上で遅延ロードにする。mode は auto / always / never |
tui.altScreen / tui.bell | true / true | 全画面 / 長い実行の後のベル |
trustedProjects | 配列(全体の設定のみ) | 尋ねずに信頼するプロジェクト |
updateCheck | true | 起動時に新しい版を1日1回確かめ、あれば知らせる |
環境変数
| 変数 | 内容 |
|---|---|
SASACODE_HOME | ~/.sasacode の代わりに使う場所 |
SASACODE_VERSION / SASACODE_INSTALL_DIR | インストーラー:版の固定 / 置き場所 |
SASACODE_AMBIGUOUS_WIDTH | 幅の曖昧な文字を 1 か 2 マスとして数える |
SASACODE_PLUGIN_INDEX / SASACODE_NPM_REGISTRY | plugin search のおすすめ一覧の URL / npm のレジストリ |
| 各プロバイダーのキー | ANTHROPIC_API_KEY、OPENAI_API_KEY、OPENROUTER_API_KEY、CMD_API_KEY など |
ファイルの置き場所
07同梱プラグインと設定
設定は plugins.settings.<名前> に書く。どれも plugins.disabled で外せ、~/.sasacode/plugins やプロジェクトに同じ名前のプラグインがあれば、同梱版の代わりにそちらを読み込む。
{ "plugins": { "settings": { "compaction": { "threshold": 0.7 }, "loop-guard": { "noProgressTurns": 0 } } } }
小型モデル向けの修復と抑止
| プラグイン | 設定 | 既定 | 内容 |
|---|---|---|---|
tool-repair | json | true | 壊れた JSON(末尾カンマ、閉じ括弧、クォートのないキー、True/None、コードフェンス、二重エンコード)を直す |
schema | true | キー名(file → path)と型("20" → 20)を直す | |
names | true | ツール名の typo を直す(候補が1つのときだけ) | |
loop-guard | noteAt | 3 | 同じ呼び出し(か3手までの周期)が同じ結果で続いたら、この回で注意を添える |
blockAt | 5 | この回から、その周期の呼び出しを止める(ファイルの変更か次の依頼で解除) | |
noProgressTurns | 5 | ツールが1件も実行されないターンがこの回数続いたら実行を止める(0 で無効) | |
repetition-guard | minRepeats | 4 | 同じ文がこの回数以上続いたら止める |
minSpan / minUnit | 200 / 10 | 繰り返し全体の最小の長さ / 1単位の最小の長さ(文字) | |
shortMinSpan | 400 | 「なるほど。」のような短い単位を止めるのに要る長さ | |
maxStopsPerRun | 2 | 1回の実行で止める回数の上限(ツール引数用に toolcall… の同名の設定もある) |
文脈とエージェント
| プラグイン | 設定 | 既定 | 内容 |
|---|---|---|---|
compaction | threshold | 0.8 | コンテキストがこの割合に達したら古い履歴を要約する(上限に来たときも)。/compact [指示] で手動 |
agents-md | — | ~/.sasacode/AGENTS.md と、リポジトリのルートから作業ディレクトリまでの AGENTS.md を読む(CLAUDE.md は読まない) | |
subagent | — | task ツール。別の履歴で作業させ、報告だけを受け取る。background: true で待たずに続行し(メインを Esc で止めると一緒に止まる)、task_status・task_send・task_stop で見る・指示する・止める。ユーザーは /task で同じことができる | |
todo | — | todo_write ツール。進捗をフッターに出す | |
checkpoints | maxFileKB | 1024 | write / edit が変える直前の内容をセッションに控え、/undo で1回の呼び出しの分ずつ戻す(/undo list、/undo <path>)。bash の変更と、大きいファイル・テキストでないファイルは対象外 |
goal | — | /goal <目的>、done / pause / resume / clear。「これをゴールにして」と頼めばモデルが set_goal で設定する |
バックグラウンド実行(background-sessions)
モデルが bg_start で長いコマンドを裏で動かし、終わったら終了コードと出力の末尾が会話に届く(待機中なら続きを自動で始める)。bash と同じ権限ルールで判定する。sasacode を終了してもジョブは続き、次の起動で結果を知らせる。/bg で一覧、/bg <id> で詳細、/bg kill <id> で停止。POSIX のみ。
| 設定 | 既定 | 内容 |
|---|---|---|
dir | ~/.sasacode/background-sessions | 出力と状態の置き場所 |
pollMs | 1500 | 終了を確かめる間隔 |
tailLines | 30 | 終了通知に付ける出力の行数 |
keep | 40 | 残す終了済みジョブの数 |
autoNotify | true | false なら通知だけで、エージェントを起こさない |
foreignGraceMs | 10000 | 別のセッションで始めたジョブの通知を、元のセッションに譲る時間 |
接続の復旧待ち(auto-reconnect)
実行がエラーで終わり、使っているモデルの接続先に届かないとき、復旧を待ってから「中断した作業を再開して」と送る。オンラインで別の理由(キーの誤りなど)のエラーなら何もしない。
| 設定 | 既定 | 内容 |
|---|---|---|
checkUrl | 使用中モデルの接続先 | 疎通を確かめる URL(応答が返ればオンライン) |
checkIntervalMs / checkTimeoutMs | 5000 / 3000 | 確かめる間隔 / 1回のタイムアウト |
maxWaitMs | 600000(10分) | 待つ最大時間 |
retryMessage | (再開の指示) | 復旧後に送る文 |
quiet | false | 通知を出さない |
使用量(usage)
| コマンド | 内容 |
|---|---|
/usage | この起動の使用量、今日・7日・30日・全期間の合計、ChatGPT プランの残り |
/usage graph | 日ごとの使用量を GitHub の Contributions Graph のように(端末の幅に入るだけの週) |
/usage history [日数] | 日別の棒グラフと数値(既定 14 日) |
/usage models | モデル別の合計、割合、最終使用日 |
/usage plan | ChatGPT プランの 5 時間・週の枠と、リセットまでの時間 |
記録は ~/.sasacode/sessions のセッションログから読む。/compact の要約とサブエージェントの分はログに残らないので含まない。プランの残りは ChatGPT にログインしているときだけ出る。
Web
| プラグイン | 設定 | 内容 |
|---|---|---|
web-fetch | — | web_fetch ツール。URL を取ってテキストにする |
browsr | command、mode、config | browsr-4-agent で検索(search)と本文の閲覧(open)。browsr-agent が PATH にあれば自動で起動。別の場所なら command で指定 |
Jev(配布プラグイン jev-guard)の設定
| 設定 | 既定 | 内容 |
|---|---|---|
enabled | false | 有効にする |
backend | キーのある方 | commandcode(CMD_API_KEY)、typesafe(TYPESAFE_API_KEY)、openrouter、vercel、chat(sasacode の任意のモデル)。OpenRouter と Vercel は名前を指定したときだけ使う |
model / endpoint / apiKeyEnv | 接続先ごと | モデル名 / URL / キーの変数を変える(プロキシなど) |
timeoutMs | 5000(chat は 60000) | これを超えたら Jev なしの判定で続ける |
skip | ["todo_write","task"] | 判定しないツール(読み取りと作業ディレクトリ内の編集は元から判定しない) |
thresholds | allow 0.8、headlessAllow 0.9、deny 0.85、confidence 0.6、risk 0.6、flag 0.7、clear 0.3 | 判定の閾値 |
08プラグイン
探す・入れる・公開する
公開する人
sasacode plugin publish my-tool.ts --license MIT- package.json・README を組み立てて
npm publish - キーワード
sasacode-pluginが付く
置き場所
- npm:プラグインの本体
- GitHub:git で配るもの
- sasanokusa.com/sasacode/plugins.json:おすすめの一覧だけ(数 KB)
使う人
sasacode plugin search 語:一覧(★)と npm からsasacode plugin install 名前:中身を見て確認してからsasacode plugin update:最新へ
sasacode plugin search # 全部
sasacode plugin search 天気 # 語で絞る
sasacode plugin install sasacode-plugin-foo # npm
sasacode plugin install https://github.com/you/plugin # git
sasacode plugin install ./my-plugin # 手元のパッケージ(公開前の確認)
sasacode plugin install foo --project # このプロジェクトの .sasacode/plugins へ
sasacode plugin update [名前]
sasacode plugin list
sasacode plugin remove <名前>
入れる前に見せるもの
- npm:版、説明、公開者と公開日、ファイル数と大きさ、依存パッケージ、install スクリプトの有無(実行はしない)、
sasacodeフィールドの有無、ソースのリポジトリ。 - git:URL。入れた後にコミットを出す。
updateでは新しいコミットの一覧と変更の規模を見せてから更新する。 - 端末がない(スクリプトから実行する)ときは
--yesが要る。
公開する
sasacode plugin publish my-tool.ts --license MIT --dry-run # 中身の確認
sasacode plugin publish my-tool.ts --license MIT # 公開(npm へのログインが必要)
| オプション | 既定 | 内容 |
|---|---|---|
--name | sasacode-plugin-<ファイル名> | パッケージ名(@you/my-tool も可) |
--version | npm の最新版の次のパッチ(初回 0.1.0) | 版 |
--api | 使っている機能から | 対応するプラグイン API(permission フックなら ^1.7.0 など) |
--description | ファイル先頭のコメント | 説明文 |
--license | なし | 付けないと、ほかの人は再利用できない |
--otp | その場で聞かれる | npm の2段階認証のコード |
ほかのファイルを import しているプラグインは、package.json に sasacode フィールドを書いたフォルダごと sasacode plugin publish <フォルダ> で出す。おすすめ一覧に載せたいときは、site/plugins.json に1件足す pull request を送る。
{ "name": "my-tool", "source": "sasacode-plugin-my-tool", "description": "何をするか", "author": "you" }
書く
~/.sasacode/plugins/hello.ts に置くだけで読み込む(ビルド不要)。@sasacode/plugin-api は入れなくても import できる(型補完が欲しければ npm i -D @sasacode/plugin-api)。
import { text, type Plugin } from "@sasacode/plugin-api";
export default ((api) => {
api.registerTool({
name: "hello",
description: "Greet someone by name.",
parameters: { type: "object", properties: { name: { type: "string" } }, required: ["name"] },
kind: "read",
execute: async ({ name }) => ({ content: [text(`Hello, ${name}!`)] }),
});
api.registerCommand({ name: "hello", description: "挨拶する", run: ({ args }) => api.ui.notify(`こんにちは ${args}`) });
}) satisfies Plugin;
組み込みの Skill を使えば、モデルに書かせることもできる:/skill:tool-authoring 天気を返すツールを作って。
フックの順序
inject)や停止(stop)API の版
| 版 | 追加されたもの |
|---|---|
| 1.0 | ツール、コマンド、プロバイダー、基本のフック、ui / session / agent |
| 1.1 | ready(promise) |
| 1.2 | stream_delta、assistant_message、tool_call_raw、サンプリングの変更 |
| 1.3 | コマンドの引数の補完 |
| 1.4 | 実行されなかった呼び出しの tool_result、turn_end の stop。ここで締め切り、以後 1.x は追加だけ |
| 1.5 | Provider.listModels、Request.fetch |
| 1.6 | ツールの permissionsAs |
| 1.7 | permission フック、softDeny |
マニフェスト、API の全項目、互換性の約束は docs/plugins.md。
MCP と Skills
{
"mcpServers": {
"github": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-github"], "env": { "GITHUB_TOKEN": "${GITHUB_TOKEN}" } },
"remote": { "url": "https://example.com/mcp", "headers": { "Authorization": "Bearer ${REMOTE_TOKEN}" } }
}
}
- stdio と Streamable HTTP に対応。ツール名は
mcp__<server>__<tool>、prompts はスラッシュコマンドになる。接続はバックグラウンドで行うので、起動を待たせない。 - Skills は
~/.sasacode/skills/<name>/SKILL.md、.sasacode/skills/、プラグインのskillsから読む。システムプロンプトには名前と説明だけを載せ、本文はモデルが必要なときに読む。 - ツールが多いとき(定義がコンテキストの 10% 以上か 30 個以上)は、
tool_searchで必要なものだけ読み込ませる。
09セッション
会話は ~/.sasacode/sessions/<作業ディレクトリ>-<ハッシュ>/<日時>_<id>.jsonl に、1件ずつ追記して保存する。途中で強制終了しても、最後に保存したところから再開できる。
| やりたいこと | 方法 |
|---|---|
| このディレクトリの直近の会話を続ける | sasacode -c |
| ID を指定して続ける | sasacode -r <id>、TUI なら /resume |
| 1回ずつ続ける(tmux なしで会話する) | sasacode -r <id> -p "続き" |
| 過去の時点から分岐する | /fork |
| 保存しない | --no-session |
| コンテキストを空ける | /compact(自動でも 80% で要約する) |
- 結果が保存される前に止まったツール呼び出しは、「実行されたか分からない」としてモデルに伝え、状態を確かめてからやり直させる。
- 書きかけの最終行は
<ファイル>.tornに退避する。 - セッション ID は、フッター、
/session、終了時の要約、ヘッドレスの出力に出る。
10ヘッドレスと自動化
sasacode -p "テストを直して" # 答えは stdout、進捗は stderr
sasacode -p "…" --output jsonl # 全イベントを1行ずつ JSON で
git diff | sasacode -p "このdiffをレビューして" # パイプした入力は -p の後ろに付く
sasacode -p "…" --permission auto --trust-project # CI など確認できない環境で
- 終了コード:最後まで終われば 0、それ以外(中断、エラー、上限、プラグインによる停止)は 1。止まった理由は stderr に
[stopped: …]で出る。 - 確認が必要な呼び出しは実行せず、理由をモデルに返す。何を許すかはルールで決めておく(
--permission autoでも deny と ask のルールは効く)。 - MCP サーバーなどの起動処理は、最初のリクエストの前に待つ。
- テキストモードでは最後に
session <id> · continue: sasacode -r <id> -p "…"が stderr に出る。
JSONL のイベント
最初の行は {"type":"session","id":…,"path":…}。そのあとはイベントが1行ずつ出る。
| type | 内容 |
|---|---|
agent_start / agent_end | 実行の始まりと終わり(cause:done、aborted、error、refusal、context_limit、max_turns、stopped) |
turn_start / turn_end | モデルへの1リクエストごと |
message_start / message_update / message_end | 応答の開始 / 差分(テキスト・推論・ツール引数) / 確定したメッセージ(使用量を含む) |
tool_start / tool_update / tool_end | ツールの開始 / 途中の出力(bash の stdout など) / 結果 |
tool_repaired | 壊れた呼び出しを直した(元の形と直した内容) |
message_discarded | プラグインが再生成させた応答(捨ててよい) |
messages_replaced | 履歴が差し替えられた(要約など) |
context_limit / error / plugin_error | コンテキストの上限 / エラー / プラグインのエラー |
11困ったとき
推論(thinking)を off にしても推論が返ってくる
サーバーによっては推論を止められない。Command Code の DeepSeek は none を受け付けず、推論が必ず返るので、off は一番軽い low として送る。自前の vLLM などは off で止まる(0.9.3 以降)。推論の深さを参照。
文章がコピーできない・端末で選択できない
全画面では sasacode がマウスを受け取る。ドラッグして離すと sasacode がコピーする(0.9.1 以降)。端末の標準の選択を使いたいときは option / alt を押しながらドラッグするか、"tui": { "altScreen": false } にする。直前の応答全体は /copy。
表示が崩れる・罫線に文字が重なる
①や※のような幅の曖昧な文字の数え方が、端末とずれている可能性がある。SASACODE_AMBIGUOUS_WIDTH=2(CJK 向けの端末設定のとき)か 1 を付けて起動してみる。改行を含むコマンドで崩れる問題は 0.9.2 で直した。
/compact が何も言わない
要約はモデルへの1回の長い呼び出しで、画面には流れない。フッターに「履歴を要約中」と出ている間は待つ(0.9.2 以降)。ローカルのサーバーで履歴が長いと数分かかる。サーバーの同時処理数が埋まっていると、順番待ちになる。
自前サーバーのモデルでコンテキストの割合がおかしい
コンテキスト長が取れないモデルは 128k として扱う。modelOverrides で contextWindow を指定する(自前のサーバー)。
plugin install がスクリプトから動かない
入れる前の確認に答える端末がないため。--yes を付ける。
plugin publish が 404 や EOTP で失敗する
404:npm のログインが切れている。npm whoami で確かめ、npm login し直す(npm は権限のない相手に 404 を返す)。
EOTP:2段階認証のコードが要る。その場で聞かれるので入力するか、--otp <コード> を付ける(0.9.4 以降)。
プロジェクトのプラグインや設定が効かない
プロジェクトを信頼していない可能性がある。起動時の確認で信頼するか、ヘッドレスなら --trust-project、いつも使うなら全体の設定の trustedProjects に入れる(プロジェクトの信頼)。
同梱プラグインを自分で改造したい
同じ名前のプラグインを ~/.sasacode/plugins に置くと、同梱版の代わりにそちらを読み込む。同梱版のソースは packages/bundled/src。
ネットワークが切れて止まった
同梱の auto-reconnect が、接続先の復旧を待って自動で再開する(最大 10 分)。待ちきれないときや手動で再開するときは /reconnect。