GitHub Actions でデバッグターミナルを起動する。

2026/01/12 21:25

GitHub Actions でデバッグターミナルを起動する。

RSS: https://news.ycombinator.com/rss

要約

Japanese Translation:

(以下は日本語訳です)

Summary

プロジェクトは、https://actions‑term.gripdev.xyz/ で失敗した GitHub Actions の実行をデバッグするための無料かつオープンソースの Web ターミナルを提供します。WebRTC ピア・ツー・ピア接続(UDP ホールパンチング、Tailscale/iRoh/WebRTC を介して)を確立することで、すべてのターミナルトラフィックがブラウザとランナー間で直接流れ、コストの高いサーバー経由ではなくなるため、データ転送コストをほぼゼロに保ちます。

認証は分離されています。ブラウザは GitHub OAuth を介して認証し、ランナーは GitHub Actions OIDC トークン を使用して GitHub の JWKS に対して検証します。軽量な Go シグナリングサーバーは接続メタデータのみを交換し、セッションマップ(

runIdToSessions
runIdRunnerSseClient
など)を保存した後、Server‑Sent Events (SSE) を通じてブラウザへ更新情報をプッシュします。

ターミナルのレンダリングは Ghostty(xterm.js と互換性のあるライブラリ)で行われます。これはブラウザのフォントメトリクスからターミナル寸法を計算し、PTY を生成する前にこのサイズ情報をランナーへ送信します。これにより、最初から正確な表示が保証されます。

ゼロトラストセキュリティのために、各ピアは共有シークレットから導出されたワンタイムパスワード(OTP)を提示します。ランナーはターミナルアクセスを許可する前にこの OTP を検証し、シグナリングサーバーが侵害されても悪用を防ぎます。

サービスは Railway.app 上で動作しており、実際の CPU/メモリ使用量のみ課金され、アイドル時には「スリープ」状態に入ります。ピークメモリ消費は約 20 MB にとどまり、月額コストはほぼゼロ(≈$0.00000)です。コールドスタートも短時間であるため、ユーザーはセッションを開始する際にわずかな遅延しか経験しません。

インパクト: 開発者は追加のインフラオーバーヘッドなしに CI の失敗を即座かつ無料でデバッグできるようになります。企業は運用コストを削減し、継続的インテグレーションパイプラインのセキュリティ姿勢を強化できます

本文

ネタバレ: GitHub Actions が失敗したときにインタラクティブな Web ターミナルを取得できる、無料かつオープンソースの方法を作成しました。試してみてください: https://actions-term.gripdev.xyz/ (コード 🔗)


作り方

「ビルドが Actions で失敗するけどローカルでは動く」という状況は誰もが経験したことがあると思います。結果として、以下のような遅いループに陥ります。

推測的変更をプッシュ
うまくいったか確認

そのループの中で、もっと良い方法を考え始めました。

ターミナルは明らかに便利ですが、どうすれば実現できるでしょう? さらに、大きなコストを発生させずに誰でも無料・オープンに保てる方法は?

  • ユーザーと Actions VM の間でトラフィックを転送するサービスを運用するとデータ転送料金が増加し、スケール作業も必要になります。
  • P2P 接続はどうでしょう? Tailscale、iroh、WebRTC は UDP ホールパンチングを利用して中継なしで P2P を確立します。これならサーバー側はセッションごとにほんの少しだけ情報交換すればよく、費用もほぼゼロです。

Actions VM がインターネット上にあり UDP アウトバウンドを許可していることが判明したので、動作するはずでした。簡単なスクリプトで検証しました:

// ... WebRTC ICE 候補交換 ...

セキュリティとアイデンティティ

次の問題:P2P 接続の両端が主張する通りに本人確認できるか?

  • ブラウザ側: GitHub で OAuth を使うことで認証済みユーザー名を取得します。

  • Actions VM 側: OIDC(Actions がクラウドプロバイダーへ認証する際によく使用)で署名付きトークンを発行し、以下を証明できます。

    • 実行中のリポジトリ
    • トリガーしたユーザーアカウント
    • 対象とするオーディエンス

ワークフローにこれを有効化します:

permissions:
  id-token: write

Action 内でトークンを要求(例):

const requestURL = process.env.ACTIONS_ID_TOKEN_REQUEST_URL;
const requestToken = process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN;
const SERVER_URL = 'https://actions-term.gripdev.xyz';
const url = new URL(requestURL);
url.searchParams.set('audience', SERVER_URL);

const resp = await fetch(url.toString(), {
  headers: {
    Authorization: `Bearer ${requestToken}`,
    Accept: 'application/json',
  },
});

JWKS を介してトークンを暗号的に検証します:

githubOIDCIssuer := "https://token.actions.githubusercontent.com"
githubJWKSURL   := "https://token.actions.githubusercontent.com/.well-known/jwks"

// JWKS を取得
keySet, err := jwkCache.Get(ctx, githubJWKSURL)
if err != nil {
    return "", "", "", fmt.Errorf("failed to fetch JWKS: %w", err)
}

// パースと検証(クロックスキュー許容)
parseOpts := []jwtx.ParseOption{
    jwtx.WithKeySet(keySet),
    jwtx.WithIssuer(githubOIDCIssuer),
    jwtx.WithValidate(true),
    jwtx.WithAcceptableSkew(2 * time.Minute),
    jwtx.WithAudience(oidcExpectedAudience),
}
token, err := jwtx.Parse([]byte(tokenStr), parseOpts...)
if err != nil {
    return "", "", "", fmt.Errorf("token validation failed: %w", err)
}

ピアを接続(=シグナリングサーバ)

ここまでで分かったこと:

  • Actions VM ↔ ブラウザ間に WebRTC 接続が確立できる。
  • 両端のアイデンティティ検証手段がある。

残るのは、二者を紹介するサーバです。

サーバは単に紹介だけを行い、ターミナルデータはピア同士で直接流れます。
VM とブラウザがサーバへ接続すると、Server‑Sent Events(SSE)でそれぞれ相手の接続情報を送信します。両者は OAuth 認証情報や OIDC トークンを提供してアイデンティティを証明します。

サーバ側状態:

runIdToSessions            = make(map[string]*Session)          // runId -> session
runIdToSessionsMu          sync.RWMutex

runIdRunnerSseClient       = make(map[string]*SSEClient)        // runId -> SSE client (Actions VM)
runIdRunnerSseClientsMu    sync.RWMutex

actorToBrowserSseClients   = make(map[string][]*SSEClient)      // actor -> list of browser SSE clients
actorToBrowserSseClientsMu sync.RWMutex

新しい Actions VM が接続すると、待機中のブラウザに通知します:

runIdRunnerSseClientsMu.Lock()
runIdRunnerSseClient[runId] = client
log.Printf("SSE: Runner connected for actor %s (total clients: %d)", actor, len(runIdRunnerSseClient))
runIdRunnerSseClientsMu.Unlock()

// ブラウザサブスクライバーへ新セッションを通知
sess, ok := runIdToSessions[runId]
if ok {
    notifyNewSession(sess)
}

ターミナルの表示

シグナリングサーバと P2P 接続が揃ったので、ターミナルを作成してデータをストリームします。

WebRTC の DataChannel を使い、Actions VM 側で PTY シェルを生成し、そこからデータを送信:

shell = pty.spawn(SHELL, [], {
    name: 'xterm-256color',
    cwd: process.env.GITHUB_WORKSPACE || process.cwd(),
    env: process.env as Record<string, string>,
});

shell.onData((shellData) => {
    dc.sendMessage(shellData);
});

ブラウザ側では Ghostty(xterm.js 互換)を使ってインタラクティブターミナルを表示します。

フォントサイズから端末サイズを推定し、設定用 JSON を送信して Actions VM が正しい寸法でシェルを起動できるようにしています。

信頼対ゼロトラスト

シグナリングサーバは、ユーザーが開始した Actions とのみ接続する必要があります。そうしないと誰かが接続を乗っ取れる恐れがあります。
対策として:

  1. ユーザーは Actions VM に秘密(自分だけ知っているもの)を渡します。
  2. P2P 接続確立時、Actions VM は有効な OTP が届くまで通信を拒否します。

OTP は 2FA のように使われる一回限りパスワードで、シグナリングサーバが侵害されても正しい OTP を持たないとコマンド実行できません。

フロー:

GitHub Runner <─── WebRTC 接続確立 ───────> ブラウザ
        ▲                                                │
        │    ブラウザが OTP を送信                        │
        │                                                ▼
Runner が秘密に対して OTP を検証 → 有効ならターミナルアクセス許可

シグナリングサーバは OTP もその秘密も受け取らないので、検証は Actions VM とブラウザの間で直接行われます。

シグナリングサーバのホスティング

無料で提供したい。サーバは Go バイナリを Docker イメージに入れただけなので、自前で簡単にローカルホストできます。
Railway.com なら実際に使用した CPU/メモリ分だけ課金されます(Azure/AWS のようにリザーブが必要なし)。

ピークメモリは約 20 MB で、費用はほぼゼロ($0.00000 程度)です。 Railway は「スリーピング」機能もあるため、アイドル時にはサーバを停止し、需要に応じて立ち上げることでコストを最小化できます。

クールスタートはほぼ無感覚で、サーバがスリープから復帰するときだけ短い遅延があります。

同じ日のほかのニュース

一覧に戻る →

2026/01/13 4:27

了解しました!内容は明確で簡潔に保ちます。余分な改行や不必要な記号は入れず、リストがある場合は読みやすいようにきちんとインデントします。他にご要望がございましたら、お気軽にお知らせくださいね!

## Japanese Translation: **改訂された概要** CoworkはClaude Maxをベースにしたリサーチプレビュー・ツールで、現在はmacOSアプリを通じてMaxサブスクライバー向けに利用可能です。ユーザーが自分のコンピュータ上の特定フォルダへのClaudeのアクセス権を付与すると、そのフォルダ内のファイルを読み取り・編集・作成できるようになります。これにより、ダウンロードの整理、スクリーンショットからスプレッドシートを生成すること、散在したメモからレポートをドラフトするなどのタスクが便利に行えます。 標準的なチャットとは異なり、CoworkはAIにより大きな主体性を与えます。AIはタスクを計画し、実行し、進捗状況を提供します。このツールはClaude Codeと基盤を共有しており、非コーディングの文脈でもコード風の対話が可能です。ユーザーは既存のコネクター(例:ドキュメントやプレゼンテーション)をリンクしたり、Chromeとのペアリングでウェブ閲覧を行ったりして機能を拡張できます。AIは複数タスクをキューに入れ、並列実行することで前後のチャットを減らします。 制御権はユーザーに残ります:Claudeが見るフォルダとコネクターを選択し、大きな操作を行う前にプロンプトが表示されます。ただし、誤った指示でファイルが削除されたり、プロンプトインジェクションが発生するリスクもあるため、安全対策は継続的に開発中です。 このプレビューはフィードバックを集めることを目的としており、将来のリリースではデバイス間同期、Windowsサポート、強化された安全機能、および拡張されたコネクターオプションが追加される可能性があります。Coworkは個人向けにファイル整理を効率化し、手動監視を保ちながらファイルベースのワークフローを自動化する制御可能なAIアシスタントとして設計されています。

2026/01/13 1:04

**TimeCapsuleLLM:** 1800年〜1875年のデータのみで訓練された大規模言語モデル (Note: The length is preserved while using natural, polite Japanese.)

## Japanese Translation: ``` ## Summary TimeCapsule LLM プロジェクトは、歴史的な英語データのみを使用して言語モデルをゼロから構築し、現代のバイアス(「Selective Temporal Training」)を排除します。 - **Model evolution** - *v0* (16 M パラメータ、nanoGPT ベース) は約187 MB の1800年代テキストで訓練され、1800年代風の言語を生成しましたが、一貫性のない文になりました。 - *v0.5* (123 M パラメータ、引き続き nanoGPT) はコーパスを約435 MB に拡張し、文法・句読点を改善しましたが、高い幻覚と OCR ノイズに悩まされました。 - *v1* (700 M パラメータ、Phi 1.5 ベース) は約6.25 GB のデータで訓練され、歴史的事件や人物を正確に思い出せるようになりました。 - *v2mini‑eval1* (300 M パラメータ、90 GB London コーパス全体の15 GBサンプル) はわずか10 K ステップで訓練され、トークナイズ問題により「Who is Charles Dickens?」のような文字化けした出力が生成されました。 - *v2mini‑eval2* (v2mini‑eval1 と同じサイズ・データ) はチャールズ・ダーウィンについて極めて不連続なテキストを生成しました。 - **Dataset** 完全版 v2 データセットは1800–1875 年のロンドン テキストで 90 GB を含み、136,344 ドキュメントから構成されています。15 GB のサンプルは Hugging Face(https://huggingface.co/datasets/haykgrigorian/TimeCapsuleLLM-London-1800-1875-v2-15GB)で公開されています。 - **Training setup** *v0/v0.5* は GeForce RTX 4060 GPU、i5‑13400F CPU、および 16 GB RAM を使用しました。 *v1* と *v2mini‑eval1* はレンタル NVIDIA A100 SXM GPU 上で訓練されました。 - **Tokenization & evaluation** 時代固有のスペリングと語彙に対応するカスタムトークナイザー(vocab.json & merges.txt)を構築しました。出力は言語的正確さ、幻覚率、およびトークナイズ品質で評価され、バイアス統計は別途 v2 バイアスレポートに記載されています。 - **Future work** 今後の計画として、完全版 90 GB v2 データセットへの拡張、トークナイザーパイプラインの改良、およびより深いバイアス分析を実施します。 - **Impact** このプロジェクトは、歴史家・教育者・AI‑ethics 開発者が時代に即した言語モデルを必要とする際に有益であり、現代バイアスを減らすための時間的選択訓練(temporal selective training)の具体例として NLP コミュニティにも貢献します。 ```

2026/01/13 5:26

ファブリス・ベルラール氏のTS Zip(2024)

## 日本語訳: **概要** ts_zip は、GPU を活用したテキスト圧縮ツールであり、RWKV 169M v4 大規模言語モデル(パラメータを 8 ビットに量子化し、BF16 で評価)を使用してトークン確率を予測し、その予測に基づいて算術符号化を適用します。従来のツールよりも高い圧縮率を達成しています: - alice29.txt – **1.142 bpb**(21,713 B) - book1 – **1.431 bpb**(137,477 B) - enwik8 – **1.106 bpb**(13,825,741 B) - enwik9 – **1.084 bpb**(135,443,237 B) - linux‑1.2.13.tar – **1.021 bpb**(1,196,859 B)。 RTX 4090 上では、ツールは約 1 MB/s の速度で圧縮し、同程度の速度で解凍します。システムに少なくとも **4 GB の RAM** があることが前提です。ts_zip は実験的なものであり、バージョン間の後方互換性は保証されません。また、その性能評価は GPU/CPU またはスレッド数に依存せず、決定論的に行われます。この手法はプレーンテキストファイルで最も効果を発揮し、バイナリデータではエントロピーの削減がほとんど得られません。主に英語で訓練されていますが、他言語やソースコードにも比較的適切に対応します。 ダウンロードリンク: - Linux tarball: `ts_zip‑2024‑03‑02.tar.gz` - Windows ZIP: `ts_zip‑2024‑03‑02-win64.zip` 将来のリリースでは、圧縮率をさらに向上させ、言語サポートを拡大し、可能ならファイルタイプの取り扱いを追加しつつ、ハードウェア間で評価が再現できるようにすることを目指します。GPU リソースを持つユーザー(データアーカイブ担当者や大量テキストコーパスを管理する開発者など)にとって、速度を犠牲にせず高い圧縮率を実現できる最適なツールです