temp-files について
エージェント間の一時的なファイル、ディレクトリ、サイトスナップショットの受け渡しに使うスキルです。パス単位で保存し、短縮リンクに対応します。保存データには期限があり、ユーザーとエージェントごとに領域が分かれています。
主な機能
- 01ファイルやディレクトリのアップロードと上書き
- 02リレースペースの一覧表示
- 03ファイルやディレクトリZIPのダウンロード
- 04ファイルとディレクトリの削除
- 05短縮リンクの作成と失効
- 06ダウンロードしたアーカイブの自動展開
活用シーン
- 01テスト用のスキルファイルを別のエージェントに渡す
- 02ステージングサイトのスナップショットを共有
- 03短縮リンクで受信側にファイルを取得させる
- 04受け渡し後に一時ファイルを削除
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ starchild-ai-agent/ official-skills --skill temp-filesインストール後、Claude Code で/temp-filesを入力して読み込まれたか確認します。
同梱ファイルscripts/tf.py
詳細
Temp-Files — Workroom ファイルリレー
このスキルを使うと、あるエージェントが一時ファイル、ディレクトリ、またはサイト全体のスナップショットを、長期バックアップの名前空間を汚すことなく、外部ファイルホストも使わずに別のエージェントへ渡せます。
| トリガー | フロー | 動作 |
|---|---|---|
/tf put、「このファイルをリレーに置いて」、「これをエージェント B と共有して」 | A. アップロード | パスへ書き込み → expires_at を返す |
/tf list、「リレーの中身を見せて」、「一時ファイルを一覧して」 | B. 一覧 | 1 階層の ls: ファイル + サブディレクトリ |
/tf get、「X を取ってきて」、「X をダウンロードして」 | C. ダウンロード | ファイルはそのまま / ディレクトリは zip で |
/tf rm、「リレーから X を削除して」 | D. 削除 | 単一ファイル、または --recursive でサブツリー |
/tf link、「エージェント B 用の一時リンクを作って」 | E. ショートリンク | tf_xxxx 形式の内部ショートリンクを発行 |
すべてのコマンドは同じサービス (sc-agent-backup.internal) にアクセスし、コンテナに組み込まれた CONTAINER_JWT で認証します。ID とパスは JWT から導出されます:
user_id = JWT.userInfoID、agent_scope = JWT.containerId (デフォルトは
default)。別のユーザーや別のエージェントに属するリレーファイルには、アクセスも参照も削除もできません。
backup スキルとの違い (必読)
| 観点 | backup スキル | temp-files スキル (これ) |
|---|---|---|
| 目的 | エージェントの長期状態 | 短期的な受け渡し、コラボレーションリレー |
| アドレッシング | サーバー生成の backup_id | 呼び出し側が指定するパス |
| モデル | 不変の tar.gz バンドル | パスベースのファイルシステム、上書き可能 |
| クォータ | ユーザーあたり 5 バンドル、ハード上限 | バイトクォータ + ファイルあたりのサイズ上限 |
| TTL | なし | デフォルト 7 日、アクセス/上書きでスライド更新、ハード上限 60 日 |
| エージェント間 | バンドル全体を復元 | ファイル単位 / ディレクトリ単位 + ショートリンク |
この 2 つを決して混同しないでください。「エージェント状態全体を復元する」→ backup を使います。
「成果物を 1 つ渡して、もう一方のエージェントが作業を続けられるようにする」→ このスキルを使います。
運用ルール
ルール 1 — リレーをファイルホストとして使わない
デフォルトのファイル TTL は 7 日です。上書き/ダウンロードによるスライド更新があっても、
ハード上限は 60 日です。存続させる必要があるものはすべて
backup または volume-backup を経由させてください。
ルール 2 — パスのホワイトリスト
サーバーは [A-Za-z0-9._\- ] に一致するセグメントのみを受け付けます。
..、絶対パス、空のセグメント、制御文字は拒否されます。単に相対パスを渡してください:
skills/my-skill/SKILL.md✅sites/staging/index.html✅../escape.txt❌ → 400 bad_path/abs/oops.mdは先頭のスラッシュが取り除かれます — 送らないほうがよいです
ルール 3 — ショートリンクは「内部のエージェント間」用であり、公開共有ではない
ファーストパスのショートリンクはケイパビリティ URL モデルに従います:
tf_xxxxxxxxを持つ者は誰でも取得できる (コード自体が資格情報 — 64 ビットのエントロピー)- ただし、6PN 内部ネットワーク + 有効な
CONTAINER_JWT(監査用) が依然として必要 - ブラウザや素の
curlにはトークンがないため 401 になります — これは想定どおりで、バグではありません - クロスユーザーのエージェントも取得できます。まさにそれが Workroom の受け渡しのユースケースだからです
正しいフロー:
- エージェント A が
/tf putを呼び出してアップロードする - エージェント A が
/tf linkを呼び出し、tf_xxxxxxxxを受け取る - エージェント A が Workroom 経由でエージェント B にショートリンクを送る
- エージェント B (Fly 内部にいて、自身の
CONTAINER_JWTを持ち、場合によっては別の ユーザー配下) がtf fetch tf_xxxxxxxxを呼び出して取得する
しないでください: http://sc-agent-backup.internal:8080/t/<code> をエンドユーザーに渡して
ブラウザで開かせること — 公開到達可能ではありません。公開共有が提供された場合は、
フェーズ B の公開リゾルバーを待ってください。
クリーンアップルール: 受け取り側がファイルを取得したと確認したら、送り側は
ただちに tf unlink <code> を実行してショートリンクを取り消し、トークンが残らないようにするべきです。
機密コンテンツは必ず unlink してください — TTL を最後の砦として頼らないでください。
ルール 4 — 失敗したら停止し、暗黙に再試行しない
tf.py のサブコマンドが非ゼロで終了した場合、ただちに停止し、stderr をそのまま
ユーザーに返してください。「代わりにもう一度試してみます」はしないでください。
インストールパス
このスキルは /data/workspace/skills/temp-files/ にインストールされます。すべてのコマンドは
エージェントの作業ディレクトリから実行します:
python3 skills/temp-files/scripts/tf.py <subcommand> ...
コマンドリファレンス
すべてのコマンド共通の環境変数:
CONTAINER_JWT— ai-agent によって注入される、必須TEMP_STORAGE_URL— 任意、デフォルトはhttp://sc-agent-backup.internal:8080
グローバル出力スイッチ(サブコマンドの前に指定します):
--verbose:完全なペイロード/エラーメタを出力します(デバッグ用)--json:安定した JSON エンベロープ、成功時と失敗時で同じキー- 成功時:
{ok: true, error: "", message: "ok", detail: "", data: {...}}dataはデフォルトでコマンドのコンパクトビュー(最小限の有用なフィールドセット)--verboseを付けると、dataはサーバーの生のペイロード(すべてのフィールド)になります
- 失敗時:
{ok: false, error: "<code>", message: "...", detail: "...", exit_code: N}errorはサーバーのエラーコード(例:bad_path/not_found/quota_exceeded)またはusage_error/http_error--verboseを付けると、metaサブ構造(HTTP ステータス/サーバーの元の message+detail)が含まれます
- 成功時:
- デフォルト(スイッチなし):コンパクト出力、最小限の有用なフィールドセット(人間とエージェントの両方が読めます)
注意:tf list と tf links は --json なしだと人間にやさしいテーブルを出力します。
--json を付けるとエンベロープを通り、data が完全な
entries/links 配列を保持します。
推奨デフォルト(クイックリファレンス)
| フラグ | 推奨値 | 理由 |
|---|---|---|
link --ttl-seconds | 3600(1 時間) | 受け取り側が一度取得するには十分長く、残留しない程度に短い |
put --ttl-days | 7(デフォルト) | 一般的なレビューサイクルをカバーします |
fetch --extract | 常に付ける | 自動展開、手順が 1 つ減り、zip-slip 対策が組み込まれています |
ディレクトリに対する get | --zip を必ず付ける | サーバーにプレーンなディレクトリダウンロードモードがありません |
受け渡し後の unlink | 受け取り側が確認したらすぐに呼び出す | ショートコード = 認証情報。機密コンテンツは必ず失効させる必要があります |
A. アップロード/上書き
python3 skills/temp-files/scripts/tf.py put <local-file> <remote-path> \
[--ttl-days N]
例:
python3 skills/temp-files/scripts/tf.py put ./SKILL.md skills/demo/SKILL.md
# → {"path": "...", "size_bytes": ..., "expires_at": ...}
同名のアップロードは上書きされます。レスポンスは新しい expires_at を返します。
B. 一覧
python3 skills/temp-files/scripts/tf.py list [--prefix PATH]
--prefix を付けない場合はルートを一覧します。--prefix sites/ はその下の 1 階層を一覧します。
C. ダウンロード
# Single file
python3 skills/temp-files/scripts/tf.py get <remote-path> <local-dest>
# Whole directory as a zip
python3 skills/temp-files/scripts/tf.py get <remote-dir> <local-dest.zip> --zip
ダウンロードに成功すると TTL が 7 日延びます。
D. 削除
# Single file / empty directory
python3 skills/temp-files/scripts/tf.py rm <remote-path>
# Non-empty directory
python3 skills/temp-files/scripts/tf.py rm <remote-dir> --recursive
E. ショートリンク
python3 skills/temp-files/scripts/tf.py link <remote-path> \
[--zip] [--ttl-seconds 3600]
# → {"code": "tf_xxxxxxxx", "url": "http://.../t/tf_xxxxxxxx", ...}
# List currently active short links
python3 skills/temp-files/scripts/tf.py links
# Revoke
python3 skills/temp-files/scripts/tf.py unlink <code>
ショートリンクの TTL はデフォルトで 1 時間、上限は 7 日です(ファイル自身の TTL とは独立しています)。
F. ショートリンク経由でデータを取得する(受け取り側のエージェントが実行するもの)
# Download + auto-unpack (strongly recommended)
python3 skills/temp-files/scripts/tf.py fetch <code> <local-dest> --extract
# Or specify the extract directory
python3 skills/temp-files/scripts/tf.py fetch <code> ./pack.zip --extract ./out
# Without --extract: download only, no unpack
python3 skills/temp-files/scripts/tf.py fetch <code> <local-dest>
有効な CONTAINER_JWT を持つ呼び出し元なら誰でも取得できます(ユーザーをまたいでも問題ありません)。
Zip 自動検出:サーバーが Content-Type: application/zip を返すと、
fetch と get は自動的にローカルファイル名の末尾を .zip にリネームし、
JSON 出力で "kind": "zip" により通知します。
自動展開(--extract):
- Python 組み込みの
zipfile/tarfileを使用します。システムのunzip/7zへの依存はありません - 対応フォーマット:
.zip/.tar/.tar.gz/.tar.bz2/.tar.xz(ファイルの拡張子ではなく マジックバイトで検出されます) - 組み込みの zip-slip / tar-slip 対策:
..セグメントは拒否されます。シンボリックリンクの メンバーは拒否されます - 値を付けない場合:兄弟ディレクトリ(アーカイブ名からサフィックスを除いたもの)に展開します。値を 付ける場合:指定したディレクトリに展開します
- 展開に成功すると、JSON 出力に
extracted_kind/extracted_to/extracted_topが含まれます
JSON 出力の例(--extract 付き):
{
"saved": "output/tf_from_4814.zip",
"kind": "zip",
"bytes": 7363,
"sha256": "...",
"content_type": "application/zip",
"server_filename": "temp-files-share.zip",
"extracted_kind": "zip",
"extracted_to": "output/tf_from_4814",
"extracted_top": ["temp-files-share/"]
}
したがって受け取り側のエージェントは:
- デフォルトで
--extractを付けてfetchを呼び出す - stdout の JSON から
extracted_toを読み取る — ファイルはそのディレクトリにあります - JSON に
extract_skippedまたはextract_errorが含まれる場合は、savedパスにフォールバックし、kindに基づいて手動で処理する
典型的なシナリオ
シナリオ 1:エージェント A がエージェント B にテスト用のスキルを渡す
# A:
python3 skills/temp-files/scripts/tf.py put ./my-skill.zip skills/my-skill.zip
python3 skills/temp-files/scripts/tf.py link skills/my-skill.zip --ttl-seconds 3600
# Receive tf_xxxxxxxx, post it to B in Workroom
# B: (recommended: fetch + auto-unpack in one shot)
python3 skills/temp-files/scripts/tf.py fetch tf_xxxxxxxx ./inbox.zip --extract
# The fetch JSON already includes sha256 — no need to rerun sha256sum
# cd into JSON.extracted_to to test; write a report
python3 skills/temp-files/scripts/tf.py put ./test-report.md reports/test-report.md
python3 skills/temp-files/scripts/tf.py link reports/test-report.md --ttl-seconds 1800
# Send the report short link back to A
# Once A has the report:
python3 skills/temp-files/scripts/tf.py unlink tf_xxxxxxxx # revoke the original skill short link
シナリオ 2:エージェント A がエージェント B にステージングサイトを渡す
# A:
cd ./staging-site/
python3 skills/temp-files/scripts/tf.py put-dir . sites/foo --ttl-days 14
python3 skills/temp-files/scripts/tf.py link sites/foo --zip
# B receives a directory-zip link
# B:
python3 skills/temp-files/scripts/tf.py fetch tf_xxxxxxxx ./foo.zip --extract
cd ./foo
# Edit, then push back
python3 skills/temp-files/scripts/tf.py put-dir . sites/foo
セキュリティ境界チートシート
- 6PN のみ: サービスはパブリックインターネット上で 403 を返します
- JWT は有効で、
type ∈ {container, access}である必要があります - 各ユーザーは分離された名前空間を持ち、そのユーザー配下の各エージェントは独自のサブスコープを持ちます
/temp-files/...への直接パスアクセスはユーザーごとに分離されています (他のユーザーの領域には到達できません)/t/<code>のショートリンクはケイパビリティです: コードを知っている人は誰でも取得できます (それでも 6PN と監査用の有効な JWT が必要です)- パスは
..と制御文字を拒否します - ファイル単位の上限は 200 MB、ユーザー単位のクォータは 2 GiB (サーバーで調整可能)
よくあるエラー / トラブルシューティング
まず
ERROR + DETAILを読み、それがパラメータの問題なのか、 権限の問題なのか、存在しないオブジェクトなのかを判断してください。 コマンドが非ゼロで終了した場合は、ハウスルールに従ってください: 停止し、黙ってリトライしないこと。
| シナリオ | 典型的な stderr | 根本原因 | 対応 |
|---|---|---|---|
不正なパス (../空セグメント/不正な文字) | HTTP 400 + DETAIL: error=bad_path, message=... | remote-path がホワイトリストに違反している | 通常の相対パスに切り替えてください。例: skills/demo/SKILL.md |
| オブジェクトが存在しない | HTTP 404 + DETAIL: error=not_found, message=... | 対象のファイル/ディレクトリが存在しない | tf list --prefix ... を実行して確認し、再試行してください |
| TTL が範囲外 | ERROR: --ttl-days must be <= 60 または --ttl-seconds ... | CLI 引数が範囲外 (事前チェック) | 許容範囲内の値を使用してください |
| 認可されていない | HTTP 401/403 | CONTAINER_JWT が欠落/無効、または内部ネットワーク外で実行している | Fly マシン内で実行し、JWT が注入されていることを確認してください |
--zip なしでディレクトリをダウンロードした | HTTP 400 (DETAIL がダウンロードモードに言及) | サーバーはディレクトリに zip モードを要求する | tf get <dir> out.zip --zip |
| recursive なしで空でないディレクトリを削除した | HTTP 400/409 | ディレクトリが空でないのに --recursive が渡されていない | tf rm <dir> --recursive |
| ファイルが大きすぎる、またはディレクトリの zip が上限を超えている | HTTP 413 | サーバーのサイズ上限を超えている | ディレクトリ/ファイルを分割して再度アップロードしてください |
最小リグレッションチェックリスト (P1 ゲート)
CLI の出力またはエラーハンドリングを変更するたびに、少なくとも次の 5 つを実行してください:
- デフォルト出力はコンパクト (
--verboseなし) だが、put/get/fetch には引き続きsha256が含まれ、link には引き続きurlが含まれる --verboseは完全なフィールドセットを出力する (エンベロープのdata= サーバーの生ペイロード)- 成功時の
--jsonにはすべてのキーが含まれる:ok, error, message, detail, data - 失敗時の
--jsonにはすべてのキーが含まれる:ok, error, message, detail, exit_code(errorはサーバーのエラーコード) - 終了コードは一貫している: 成功 = 0、ビジネス上の失敗 = 1、使用法エラー = 2
tf --json listとtf --json linksはエンベロープを経由する (サブパーサーの--jsonに上書きさせないこと)
クイックトリアージフロー (共同作業者と共有)
tf list --prefix <target-prefix>: オブジェクトが実際に存在することを確認します。- 失敗したコマンドの元の stderr を保存します (特に
DETAIL:)。 - 4xx の場合: 引数を修正してください — 同じコマンドをリトライしないでください。
- 5xx / ネットワークエラーの場合: 少し待ってから、一度だけリトライしてください。
備考
- ファイルの TTL はデフォルトで 7 日です。ダウンロード/上書きのたびに 7 日延長されます。ハード上限は 60 日です
- ショートリンクの TTL はデフォルトで 1 時間で、上限は 7 日です
- TTL を強制的に短くするには: アップロード時に
--ttl-days 1を渡します (それでも上限によって制限されます) - ディレクトリ zip のデフォルト上限: 5000 ファイル / 500 MB。どちらかの上限を超えると → 413