**200 行以内で書く Claude スタイルプログラムの作り方**

1. **目標を定義する**  
   * プログラムが解決すべき問題(例:テキスト生成、データ分析など)を決める。  
   * 必要な入力・出力、および制約事項を概略化する。

2. **適切な言語とライブラリを選ぶ**  
   * 迅速なプロトタイピングには Python を推奨。  
   * `openai` や `anthropic` SDK を使用し、必要最低限のモジュール(例:`json`、`time`)のみインポートする。

3. **コード構成**  
   ```python
   # 1️⃣ インポート
   import os, json, time
   from anthropic import Anthropic

   # 2️⃣ 設定
   api_key = os.getenv("ANTHROPIC_API_KEY")
   client = Anthropic(api_key=api_key)

   # 3️⃣ コア関数
   def generate_text(prompt: str, max_tokens: int = 200) -> str:
       response = client.completions.create(
           model="claude-2.1",
           prompt=prompt,
           max_tokens_to_sample=max_tokens,
           temperature=0.7,
       )
       return response.completion

   # 4️⃣ ユーティリティ関数
   def save_output(text: str, path: str) -> None:
       with open(path, "w", encoding="utf-8") as f:
           f.write(text)

   # 5️⃣ メインフロー
   if __name__ == "__main__":
       prompt = input("Enter your prompt: ")
       result = generate_text(prompt)
       print("\nGenerated Text:\n", result)
       save_output(result, "output.txt")
   ```

4. **200 行以内に収める**  
   * 不要なコメントや冗長なログを避ける。  
   * 繰り返しコードの代わりに簡潔なヘルパー関数を使う。

5. **テストと検証**  
   * `generate_text` と `save_output` 用に単純なユニットテストを書く。  
   * 複数サンプルプロンプトでスクリプトが安定して動作するか確認する。

6. **パッケージング(任意)**  
   * `requirements.txt` を追加:
     ```
     anthropic==0.3.2
     python-dotenv==1.0.0
     ```
   * セットアップと使い方を簡潔に説明した README を用意する。

7. **最終チェックリスト**  
   * 未使用のインポートや変数がないこと。  
   * 文字列はすべて `utf-8` でエンコードされていること。  
   * 新しい環境でもエラーなく実行できること。

このテンプレートに沿えば、200 行以内でクリーンかつ機能的な Claude スタイルプログラムが完成します。実験・拡張・デプロイの準備は万端です。

2026/01/09 4:54

**200 行以内で書く Claude スタイルプログラムの作り方** 1. **目標を定義する** * プログラムが解決すべき問題(例:テキスト生成、データ分析など)を決める。 * 必要な入力・出力、および制約事項を概略化する。 2. **適切な言語とライブラリを選ぶ** * 迅速なプロトタイピングには Python を推奨。 * `openai` や `anthropic` SDK を使用し、必要最低限のモジュール(例:`json`、`time`)のみインポートする。 3. **コード構成** ```python # 1️⃣ インポート import os, json, time from anthropic import Anthropic # 2️⃣ 設定 api_key = os.getenv("ANTHROPIC_API_KEY") client = Anthropic(api_key=api_key) # 3️⃣ コア関数 def generate_text(prompt: str, max_tokens: int = 200) -> str: response = client.completions.create( model="claude-2.1", prompt=prompt, max_tokens_to_sample=max_tokens, temperature=0.7, ) return response.completion # 4️⃣ ユーティリティ関数 def save_output(text: str, path: str) -> None: with open(path, "w", encoding="utf-8") as f: f.write(text) # 5️⃣ メインフロー if __name__ == "__main__": prompt = input("Enter your prompt: ") result = generate_text(prompt) print("\nGenerated Text:\n", result) save_output(result, "output.txt") ``` 4. **200 行以内に収める** * 不要なコメントや冗長なログを避ける。 * 繰り返しコードの代わりに簡潔なヘルパー関数を使う。 5. **テストと検証** * `generate_text` と `save_output` 用に単純なユニットテストを書く。 * 複数サンプルプロンプトでスクリプトが安定して動作するか確認する。 6. **パッケージング(任意)** * `requirements.txt` を追加: ``` anthropic==0.3.2 python-dotenv==1.0.0 ``` * セットアップと使い方を簡潔に説明した README を用意する。 7. **最終チェックリスト** * 未使用のインポートや変数がないこと。 * 文字列はすべて `utf-8` でエンコードされていること。 * 新しい環境でもエラーなく実行できること。 このテンプレートに沿えば、200 行以内でクリーンかつ機能的な Claude スタイルプログラムが完成します。実験・拡張・デプロイの準備は万端です。

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

要約

Japanese Translation:

(to address missing elements while keeping clarity):**

本記事では、JSON形式のツール呼び出し(

read_file
list_files
edit_file
)を介してLLMと対話し、ディスク上のファイルを操作する軽量なコーディングエージェントの構築方法を示します。
エージェントのコアループは、ユーザーからの自然言語リクエストをLLMに送信し、そのJSONレスポンスからツール呼び出しを解析して対応するローカル関数を実行し、結果を会話へフィードバックします。ツールが要求されなくなるまでこのプロセスを繰り返します。各ツールは構造化された辞書を返します(
read_file
{file_path, content}
list_files
{path, entries}
edit_file
→ テキストの作成または置換)。
システムプロンプトは自動的に生成され、各ツールの名前・説明(docstringから取得)とシグネチャを列挙することでLLMが正しく呼び出せるようにします。例ではAnthropic API経由でClaude Sonnet 4を使用していますが、クライアント初期化部分を書き換えるだけで任意のLLMプロバイダーへ切り替え可能です。
実装はインポート、環境変数読み込み(
dotenv
)、ターミナルカラー補助関数、および
resolve_abs_path
ヘルパーを含めて約200行のPythonコードです。プロダクション向けエージェント(例:Claude Code)は、このパターンにgrep、bash、websearchなど追加ツールや高度なエラーハンドリング、ストリーミングレスポンス、要約機能、および破壊的操作の承認ワークフローを組み込んでいます。
読者は新しいツールを追加したりLLMプロバイダーを切替えたりして、最小限のボイラープレートで高度なコーディング支援が実現できることを体験できます。

この改訂された概要は主要なポイントをすべて網羅し、未支持の推測を避けつつメインメッセージを明確に保ち、あいまい表現を削除しています。

本文

今日のAIコーディングアシスタントはまるで魔法のようです。
あなたがほとんどまとまりのない英語で「こんにちは世界関数を持つ新しいファイルを作って」などと言うだけで、ツールはファイルを読み込み、プロジェクトを編集し、実用的なコードを書き出します。

しかし本当のところ、このようなツールの核心は魔法ではなく、200行程度のシンプルなPythonです。ここではゼロから機能するコーディングエージェントを作ってみましょう。


思考モデル

実際にコーディングエージェントを使うときに何が起こるか、コードを書く前に理解しておきます。要は「強力なLLM(大規模言語モデル)との会話」にすぎません。

  1. あなたがメッセージを送信
    (例:「こんにちは世界関数を持つ新しいファイルを作って」)
  2. LLM がツールの使用を検討し、構造化されたツール呼び出し(または複数)を返す
  3. あなたのプログラムがそのツール呼び出しをローカルで実行(実際にファイルを作成)
  4. 結果が LLM に戻る
  5. LLM が得たコンテキストを使って応答を継続

この一連の流れがすべてです。LLM 自体はファイルシステムに触れることはなく、あくまで「何かをしてほしい」と要求するだけで、実際に動作させるのはあなたのコードです。


必要な3つのツール

コーディングエージェントが基本的に必要とする機能は次の三つです:

  • ファイルを読む(LLM がコードを確認できるように)
  • ディレクトリ内のファイル一覧を取得(プロジェクト構造を把握するため)
  • ファイルを書き換える(新規作成や修正の指示を出すため)

これだけで十分です。Claude Code のような本番用エージェントは grep・bash・Web検索などを追加していますが、ここでは3つに絞ります。


スキャフォールドのセットアップ

まず基本的なインポートと API クライアントを準備します。以下は OpenAI を使った例ですが、任意の LLM プロバイダーでも動作します:

import inspect
import json
import os

import anthropic
from dotenv import load_dotenv
from pathlib import Path
from typing import Any, Dict, List, Tuple

load_dotenv()

claude_client = anthropic.Anthropic(api_key=os.environ["ANTHROPIC_API_KEY"])

出力を見やすくするための端末カラー:

YOU_COLOR = "\u001b[94m"
ASSISTANT_COLOR = "\u001b[93m"
RESET_COLOR = "\u001b[0m"

相対パスを絶対パスに変換するユーティリティ(例:

file.py
/Users/you/project/file.py
):

def resolve_abs_path(path_str: str) -> Path:
    """
    file.py -> /Users/you/project/file.py
    """
    path = Path(path_str).expanduser()
    if not path.is_absolute():
        path = (Path.cwd() / path).resolve()
    return path

ツールの実装

1. ファイルを読むツール

def read_file_tool(filename: str) -> Dict[str, Any]:
    """
    ユーザーが指定したファイルの全内容を取得します。
    :param filename: 読み込み対象ファイル名
    :return: ファイルパスとその内容
    """
    full_path = resolve_abs_path(filename)
    print(full_path)
    with open(str(full_path), "r") as f:
        content = f.read()
    return {"file_path": str(full_path), "content": content}

2. ファイル一覧を取得するツール

def list_files_tool(path: str) -> Dict[str, Any]:
    """
    ユーザーが指定したディレクトリ内のファイルを列挙します。
    :param path: 調べたいディレクトリパス
    :return: ディレクトリにあるファイルとフォルダの一覧
    """
    full_path = resolve_abs_path(path)
    all_files = []
    for item in full_path.iterdir():
        all_files.append({"filename": item.name, "type": "file" if item.is_file() else "dir"})
    return {"path": str(full_path), "files": all_files}

3. ファイルを書き換えるツール

def edit_file_tool(path: str, old_str: str, new_str: str) -> Dict[str, Any]:
    """
    指定した文字列をファイル内で置換します。old_str が空なら新規作成/上書き。
    :param path: 書き換え対象のファイルパス
    :param old_str: 置換対象文字列(空なら新規作成)
    :param new_str: 置換後の文字列
    :return: 実行結果を示す辞書
    """
    full_path = resolve_abs_path(path)
    if old_str == "":
        full_path.write_text(new_str, encoding="utf-8")
        return {"path": str(full_path), "action": "created_file"}
    original = full_path.read_text(encoding="utf-8")
    if original.find(old_str) == -1:
        return {"path": str(full_path), "action": "old_str not found"}
    edited = original.replace(old_str, new_str, 1)
    full_path.write_text(edited, encoding="utf-8")
    return {"path": str(full_path), "action": "edited"}

ツールレジストリ

TOOL_REGISTRY = {
    "read_file": read_file_tool,
    "list_files": list_files_tool,
    "edit_file": edit_file_tool
}

LLM にツール情報を教える

LLM がどんなツールがあるか、そしてどう呼び出すかを知る必要があります。関数のシグネチャと docstring から動的に生成します:

def get_tool_str_representation(tool_name: str) -> str:
    tool = TOOL_REGISTRY[tool_name]
    return f"""
Name: {tool_name}
Description: {tool.__doc__}
Signature: {inspect.signature(tool)}
"""

def get_full_system_prompt() -> str:
    tool_str_repr = ""
    for tool_name in TOOL_REGISTRY:
        tool_str_repr += "TOOL\n===" + get_tool_str_representation(tool_name)
        tool_str_repr += f"\n{'='*15}\n"
    return SYSTEM_PROMPT.format(tool_list_repr=tool_str_repr)

SYSTEM_PROMPT = """
You are a coding assistant whose goal is to help us solve coding tasks. 
You have access to a series of tools you can execute. Here are the tools you can execute:

{tool_list_repr}

When you want to use a tool, reply with exactly one line in the format: 'tool: TOOL_NAME({JSON_ARGS})' and nothing else.
Use compact single-line JSON with double quotes. After receiving a tool_result(...) message, continue the task.
If no tool is needed, respond normally.
"""

ツール呼び出しのパーサ

def extract_tool_invocations(text: str) -> List[Tuple[str, Dict[str, Any]]]:
    """
    'tool: name({...})' 行から (tool_name, args) のリストを抽出。
    期待する形式は単一行、コンパクトな JSON(ダブルクオート)です。
    """
    invocations = []
    for raw_line in text.splitlines():
        line = raw_line.strip()
        if not line.startswith("tool:"):
            continue
        try:
            after = line[len("tool:"):].strip()
            name, rest = after.split("(", 1)
            name = name.strip()
            if not rest.endswith(")"):
                continue
            json_str = rest[:-1].strip()
            args = json.loads(json_str)
            invocations.append((name, args))
        except Exception:
            continue
    return invocations

LLM 呼び出し

def execute_llm_call(conversation: List[Dict[str, str]]):
    system_content = ""
    messages = []

    for msg in conversation:
        if msg["role"] == "system":
            system_content = msg["content"]
        else:
            messages.append(msg)

    response = claude_client.messages.create(
        model="claude-sonnet-4-20250514",
        max_tokens=2000,
        system=system_content,
        messages=messages
    )
    return response.content[0].text

エージェントループ

def run_coding_agent_loop():
    print(get_full_system_prompt())
    conversation = [{"role": "system", "content": get_full_system_prompt()}]
    while True:
        try:
            user_input = input(f"{YOU_COLOR}You:{RESET_COLOR}:")
        except (KeyboardInterrupt, EOFError):
            break
        conversation.append({"role": "user", "content": user_input.strip()})
        while True:
            assistant_response = execute_llm_call(conversation)
            tool_invocations = extract_tool_invocations(assistant_response)
            if not tool_invocations:
                print(f"{ASSISTANT_COLOR}Assistant:{RESET_COLOR}: {assistant_response}")
                conversation.append({"role": "assistant", "content": assistant_response})
                break
            for name, args in tool_invocations:
                tool = TOOL_REGISTRY[name]
                resp = ""
                print(name, args)
                if name == "read_file":
                    resp = tool(args.get("filename", "."))
                elif name == "list_files":
                    resp = tool(args.get("path", "."))
                elif name == "edit_file":
                    resp = tool(
                        args.get("path", "."),
                        args.get("old_str", ""),
                        args.get("new_str", "")
                    )
                conversation.append({
                    "role": "user",
                    "content": f"tool_result({json.dumps(resp)})"
                })

構造の概要

  • 外側ループ:ユーザー入力を取得し、会話に追加。
  • 内側ループ:LLM を呼び出し、ツール呼び出しがあるか確認。
    • ツール不要 → 応答を表示して内側ループ終了。
    • ツール必要 → 実行後に結果を会話へ追加し再度 LLM を呼び出す。

内側ループは、LLM がツールの使用をやめるまで続きます。これで複数回のツールチェーン(ファイル読み込み→編集→確認)が可能です。


実行

if __name__ == "__main__":
    run_coding_agent_loop()

以下のような対話ができます:

  • ユーザー:「hello.py という新しいファイルを作って、こんにちは世界関数を書いて」
    エージェントは

    edit_file
    を呼び出し、
    path="hello.py"
    ,
    old_str=""
    ,
    new_str="print('Hello World')"
    を渡す。

    アシスタント:「完了! hello.py にこんにちは世界を実装しました。」

  • ユーザー:「hello.py を編集して、2つの数値を掛ける関数を追加して」
    エージェントは

    read_file
    で現在内容を取得し、次に
    edit_file
    で関数を追記。

    アシスタント:「multiply 関数を hello.py に追加しました。」


本番ツールとの比較

本例は約200行です。本格的な Claude Code 等では以下のような拡張が加えられます:

  • エラーハンドリングとフォールバック機能
  • ストリーミング応答で UX を向上
  • 長いファイルを要約してコンテキスト管理をスマート化
  • コマンド実行・コードベース検索などの追加ツール
  • 破壊的操作に対する承認ワークフロー

しかし核心となるループはまさに上記です。LLM が「何をすべきか」を決定し、あなたのコードがそれを実行して結果を戻す――これが全てです。


自分で試してみよう

全文は200行前後です。好きな LLM プロバイダーに置き換え、システムプロンプトを調整し、さらなるツールを追加してみてください。この単純なパターンがどれほど強力か、驚くことでしょう。

もしプロフェッショナルエンジニア向けの最先端 AI ソフトウェア開発手法に興味があるなら、オンラインコースもご覧ください。

同じ日のほかのニュース

一覧に戻る →

2026/01/09 5:37

**Sopro TTS:** CPU 上で動作し、ゼロショット音声クローン機能を備えた 1,690 万パラメータのモデル。

## Japanese Translation: ``` ## Summary Soproは、1億6900万パラメータで構築された軽量な英語テキスト・トゥー・スピーチシステムです。リアルタイムのストリーミング合成と、わずか数秒の参照音声からのゼロショットボイスクラーニングを提供します。そのアーキテクチャは重いTransformerをドリーテッドWaveNetスタイルの畳み込みと軽量なクロスアテンション層に置き換え、M3コアマシンでCPUリアルタイム係数0.25(約7.5秒で30秒分の音声生成)を達成します。モデルは依存関係が最小限で、PyTorch 2.6.0のみを必要とし、低スペックハードウェアでも効率的に動作します。 Soproは単純なPython API(`SoproTTS.synthesize`)、コマンドラインインターフェイス(`soprotts …`)、およびUvicornまたはDockerで起動できる対話型Webデモを通じて、非ストリーミング(`SoproTTS.synthesize`)とストリーミング(`SoproTTS.stream`)の両方のモードをサポートします。ストリーミング出力は非ストリーミングモードとビットレベルで完全に一致しないため、最高品質を求めるユーザーは非ストリーミング合成を使用することが推奨されます。 トレーニングにはEmilia YODAS、LibriTTS‑R、Mozilla Common Voice 22、およびMLSなどの公開コーパスからデータが採用され、WaveNet、Attentive Stats Pooling、AudioLM、CSMといった確立された手法を組み込んでいます。ボイスクラーニングの品質はマイクロフォンの品質に依存し、システムは略語よりも音素レベルの参照音声を好みます。 Soproは低リソースフットプリント、CPUフレンドリー、そして簡単な統合性を備えているため、チャットボット、アクセシビリティツール、組み込みデバイス、および軽量TTSと高品質ボイスクラーニングが必要なリアルタイムアプリケーションに最適です。 ```

2026/01/09 0:07

ボーズは古いスマートスピーカーをブリック化せず、オープンソースとして公開しています。

## Japanese Translation: **修正版要約** ボーズは、サウンドタッチスマートスピーカーのAPIドキュメントをオープンソース化することを発表し、公式クラウドサポートを2026年5月6日まで延長しました。これは元々計画されていた期間より約6か月長いものです。また、新しいサウンドタッチアプリの更新ではローカル制御が追加されるため、ユーザーはクラウドサービス終了後も機能を維持できます。Bluetooth、AirPlay、Spotify Connect、および物理的なAUX接続を通じて音楽ストリーミングを継続でき、グループ化、初期設定、構成などのリモートコントロール機能も動作します。APIをオープンソースにすることで、ボーズはクラウドサービス停止によって残されたギャップを埋めるカスタムツールを開発者が構築できるようにしています。この動きは、公式シャットダウン後にデバイス機能を維持したPebbleのRebble Allianceなど、コミュニティ主導の取り組みと共鳴します。

2026/01/09 4:00

**フーリエ変換の驚くべき有効性**

## Japanese Translation: > Joshua Wise の **Teardown 2025** 講演(OFDM、FFT、および DVB‑T に関するもの)は、彼の YouTube チャンネルで録画として無料で視聴でき、イベントページから直接ストリーミングすることも可能です。 > スピーカーはプレゼンテーションスライドの PDF を提供し、講演中にプロットを生成した Jupyter ノートブックを共有しています;コードは「実用化準備ができている」ではなく、あくまで「例示的」であるとラベル付けされています。 > Wise は期限切れの **US 3488445A** OFDM 特許(1966 年提出、1987 年失効)を参照し、Eugene Wigner の論文 *“The Unreasonable Effectiveness of Mathematics in the Natural Sciences”* とその他関連する研究を引用しています。 > さらに、同乗キャリアと時間オフセットの同時推定に関する研究論文を提示し、そのアルゴリズムを手動で実装して議論を呼びかけています。 > Wise が構築した DVB‑T デコーダーのサンプルはデモンストレーションとして共有されていますが、最適であると主張していません。 > より深い理解のために、FFT(高速フーリエ変換)を説明する高く評価されたビデオを見ることを推奨しています。 > 興味のある視聴者は **joshua@joshuawise.com** か彼のウェブサイト https://joshuawise.com、業務用メール **joshua@accelerated.tech**(サイト https://accelerated.tech)、または Fediverse 上で **@joshua@social.emarhavil.com** に連絡できます。 > これらのリソースは、エンジニア・研究者・学生に対し実用的なコード、理論的参照、および OFDM/DVB‑T デコーディングをさらに探求するためのディスカッションプラットフォームを提供します。

**200 行以内で書く Claude スタイルプログラムの作り方** 1. **目標を定義する** * プログラムが解決すべき問題(例:テキスト生成、データ分析など)を決める。 * 必要な入力・出力、および制約事項を概略化する。 2. **適切な言語とライブラリを選ぶ** * 迅速なプロトタイピングには Python を推奨。 * `openai` や `anthropic` SDK を使用し、必要最低限のモジュール(例:`json`、`time`)のみインポートする。 3. **コード構成** ```python # 1️⃣ インポート import os, json, time from anthropic import Anthropic # 2️⃣ 設定 api_key = os.getenv("ANTHROPIC_API_KEY") client = Anthropic(api_key=api_key) # 3️⃣ コア関数 def generate_text(prompt: str, max_tokens: int = 200) -> str: response = client.completions.create( model="claude-2.1", prompt=prompt, max_tokens_to_sample=max_tokens, temperature=0.7, ) return response.completion # 4️⃣ ユーティリティ関数 def save_output(text: str, path: str) -> None: with open(path, "w", encoding="utf-8") as f: f.write(text) # 5️⃣ メインフロー if __name__ == "__main__": prompt = input("Enter your prompt: ") result = generate_text(prompt) print("\nGenerated Text:\n", result) save_output(result, "output.txt") ``` 4. **200 行以内に収める** * 不要なコメントや冗長なログを避ける。 * 繰り返しコードの代わりに簡潔なヘルパー関数を使う。 5. **テストと検証** * `generate_text` と `save_output` 用に単純なユニットテストを書く。 * 複数サンプルプロンプトでスクリプトが安定して動作するか確認する。 6. **パッケージング(任意)** * `requirements.txt` を追加: ``` anthropic==0.3.2 python-dotenv==1.0.0 ``` * セットアップと使い方を簡潔に説明した README を用意する。 7. **最終チェックリスト** * 未使用のインポートや変数がないこと。 * 文字列はすべて `utf-8` でエンコードされていること。 * 新しい環境でもエラーなく実行できること。 このテンプレートに沿えば、200 行以内でクリーンかつ機能的な Claude スタイルプログラムが完成します。実験・拡張・デプロイの準備は万端です。 | そっか~ニュース