惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Attack and Defense Labs
Attack and Defense Labs
Y
Y Combinator Blog
阮一峰的网络日志
阮一峰的网络日志
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - 聂微东
V
Visual Studio Blog
量子位
博客园 - 三生石上(FineUI控件)
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Jina AI
Jina AI
宝玉的分享
宝玉的分享
Hacker News: Ask HN
Hacker News: Ask HN
小众软件
小众软件
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Hacker News - Newest:
Hacker News - Newest: "LLM"
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
W
WeLiveSecurity
Google Online Security Blog
Google Online Security Blog
AI
AI
Schneier on Security
Schneier on Security
大猫的无限游戏
大猫的无限游戏
WordPress大学
WordPress大学
I
InfoQ
A
Arctic Wolf
月光博客
月光博客
Last Week in AI
Last Week in AI
Hugging Face - Blog
Hugging Face - Blog
Cloudbric
Cloudbric
Google DeepMind News
Google DeepMind News
Security Latest
Security Latest
GbyAI
GbyAI
N
Netflix TechBlog - Medium
TaoSecurity Blog
TaoSecurity Blog
Blog — PlanetScale
Blog — PlanetScale
Scott Helme
Scott Helme
www.infosecurity-magazine.com
www.infosecurity-magazine.com
T
The Exploit Database - CXSecurity.com
博客园 - 【当耐特】
博客园 - 司徒正美
The Hacker News
The Hacker News
Cisco Talos Blog
Cisco Talos Blog
I
Intezer
云风的 BLOG
云风的 BLOG
T
Threatpost
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
C
Cyber Attacks, Cyber Crime and Cyber Security
罗磊的独立博客
Security Archives - TechRepublic
Security Archives - TechRepublic
T
Tenable Blog

Hacker News - Newest: "AI"

AI can't read an investor deck AI as an attorney? Student uses ChatGPT, Gemini to sue UW over alleged racial discrimination Hacking MCP Servers in AI Systems – The Rug Pull: Tool Changes After Approval GitHub - MeepCastana/KubeezCut: Free Web based video editor GitHub - GenAI-Gurus/awesome-eu-ai-act: Curated tools, official sources, OSS, templates, and guides for EU AI Act compliance. Can AI judge journalism? A Thiel-backed startup says yes, even if it risks chilling whistleblowers Coming soon: 10 Things That Matter in AI Right Now DARPA built an AI to fact-check enemy weapons claims What explains heterogeneity in AI adoption? When AI Meets Muscle: Context-Aware Electrical Stimulation Promises a New Way to Guide Human Movements - Department of Computer Science AI Changed How We Build. It Did Not Change What Matters. Linux rules on using AI-generated code - Copilot is OK, but humans must take 'full responsibility for the… Meta spins up AI version of Mark Zuckerberg to engage with employees Code Mode: Let Your AI Write Programs, Not Just Call Tools | TanStack Blog GitHub - Delavalom/graft: Go framework for building AI agents. Type-safe tools, multi-provider (OpenAI, Anthropic, Gemini, Bedrock), zero vendor SDKs. India's TCS tops estimates, says new AI models did not dent services demand Gen Z's fading AI hype Strong feeling: we are in a folded AI reality GitHub - machinarii/total-recall-catalog: A reference catalog of latest knowledge retrieval, memory & RAG systems GitHub - mensfeld/code-on-incus: Give each AI agent its own isolated machine with root, Docker, and systemd. Active defense detects and stops threats automatically.. Quantization, LoRA, and the 8% Problem: Benchmarking Local LLMs for Production AI Iran war: We spoke to the man making Lego-style AI videos that experts say are powerful propaganda Powell, Bessent discussed Anthropic's Mythos AI cyber threat with major U.S. banks GitHub - immartian/bellamem: Persistent belief-graph memory for AI agents. Retrieves decisive context by importance — not recency, not RAG, not /compact. recursive-mode: The Repo-Native Operating System for AI Engineering After the attack on Sam Altman's home, will AI CEO's go on the offensive? The biggest advance in AI since the LLM Opus 4.6 vs GPT 5.4 One Prompt Unity World Generation Test “AI polls” are fake polls Client Challenge Can AI be a 'child of God'? Inside Anthropic's meeting with Christian leaders How to Switch AI Chatbots and Why You Might Want To GitHub - MattMessinger1/agentic_refund_guardrail: Safe refund policy layer for AI agents — Python + TypeScript. Same behavior, shared tests. Adam/papers/emergent_values_whitepaper.md at master · strangeadvancedmarketing/Adam Ask HN: How do you stop playing 20 questions with your AI coding tools How far can automation and AI support psychotherapy? - @theU GitHub - stagas/rtdiff: realtime git diff gui and AI-assisted commits A Mac Studio for Local AI — 6 Months Later A History of the Early Years of AI at the University of Edinburgh Why AI Coding Tools Still Feel Stuck on Localhost MSN AI Datacenters Are Becoming Strategic Targets twitter.com Penn Researchers Use AI to Surface Unreported GLP-1 Side Effects in Reddit Posts Show HN: MoodSense AI (ML and FastAPI and Gradio, Deployed on Hugging Face) Moodsense Ai - a Hugging Face Space by aman179102 AI models are terrible at betting on soccer—especially xAI Grok GitHub - xialeistudio/echoic GitHub - HimashaHerath/github-dev-wrapped: AI-powered weekly GitHub activity reports deployed to GitHub Pages GitHub - alejandrobalderas/claude-code-from-source: Architecture, patterns & internals of Anthropic's AI coding agent — reverse-engineered from source maps AI and Tech brief: Ireland ascendant GitHub - Titovilal/context0: Context0 - Never Surrender Training for a Marathon with an AI Coach: What Worked and What Didn't Cyber Pulse: Agentic Intel - Apps on Google Play I Built an AI PR Reviewer That Catches Bugs by Not Looking for Bugs Gen Z workers are so fearful AI will take their job they’re intentionally sabotaging their company’s AI rollout | Fortune How AI Is Reimagining the Game of Golf–For Both Players and Courses GitHub - nattergabriel/reseed: A CLI tool for managing and distributing agent skills across projects Is SVG the final frontier? My AI workflow evolved from prompts to a near-autonomous workflow MLSharp Help - 3DGS Viewer & Generator I put my cognitive field based AI's runtime on GitHub Is Numble the first AI-proof game? A3: Kubernetes for autonomous AI agent fleets | Emergent Principles Deepali Vyas ("The Elite Recruiter") GitHub - msmarkgu/RelayFreeLLM: A restful API designed to route user prompts to various AI model providers. Unionized ProPublica staff are on strike over AI, layoffs, and wages Unleashing the Advantage of Quantum AI We're heading for an AI-fueled 'dementia crisis,' brain scientist warns The AI-Assisted Breach of Mexico's Government Infrastructure [pdf] GitHub - stef41/lmscan: 🔍 Detect AI-generated text and fingerprint which LLM wrote it. Open-source GPTZero alternative. Zero dependencies, works offline. MSN GitHub - visionscaper/collabmem: Enabling long-term collaboration with Agentic AI - building up episodic and world model memory over time with in-context awareness We gave an AI a 3 year retail lease in SF and asked it to make a profit | Andon Labs AI Code is Hollowing Out Open Source, and Maintainers are Looking the Other Way What leaked "SteamGPT" files could mean for the PC gaming platform's use of AI AI is the boss at this retail store. What could go wrong? GitHub - Wuzu11517/agentic-proxy: Local proxy meant to help reduce With Drones, Geophysics and ArtificiaI Intelligence, Researchers Prepare to Do Battle Against Land Mines A Single Operator, Two AI Platforms, Nine Government Agencies: The Full Technical Report 在 Steam 上购买 FriedrichAI: Offline AI 立省 10% GitHub - inevolin/resume-cli: Hit Claude usage limits? Resume any AI coding session elsewhere. Switch tools at zero friction. GitHub - atripati/ark: AI Runtime Kernel — a context operating system for AI agents. Eliminates tool bloat, loads only what’s needed, and gives LLMs their reasoning space back. How to Build a Secure AI PR Reviewer with Claude, GitHub Actions, and JavaScript This Startup Wants You to Pay Up to Talk With AI Versions of Human Experts Intel Arc Pro B70 Brings 32GB VRAM to Local AI for $949 WordPress 7.0: The Good, the AI, and the Still Missing AI on the couch: Anthropic gives Claude 20 hours of psychiatry IatroBench: Pre-Registered Evidence of Iatrogenic Harm from AI Safety Measures AI Agents Know About Supabase. They Don't Always Use It Right. The history and future of AI at Google, with Sundar Pichai Inside an AI‑enabled device code phishing campaign How Meta Used AI to Map Tribal Knowledge in Large-Scale Data Pipelines AI for Systems: Using LLMs to Optimize Database Query Execution Forecasting the Economic Effects of AI Introducing Tinker: Play with AI, bring your ideas to life AI sheds light on an ancient gaming mystery People really hate AI but not as much as Iran—or Democrats | Fortune What is an AI Product Engineer? Phoebe Gates wants her $185 million AI startup to succeed with 'no ties to my privilege or my last name': 'I have a chip on my shoulder' | Fortune
Claude Agent SDK: Build Your Own AI Terminal in 10 Minutes
ankitg12 · 2026-03-14 · via Hacker News - Newest: "AI"

You've used Claude Code from the terminal. Now build your own.

That's the pitch for the Claude Agent SDK — same engine that powers Claude Code, but programmable. You get the full agent loop — file reading, bash execution, web search, code editing — wrapped in a for await loop you control.

The question everyone asks: why would I use this instead of just calling the Claude API directly?

The answer: you don't have to implement the tool loop yourself.

And the most compelling use case for that? Building your own TUI.

Demo repo: github.com/mager/claude-tui-demo — clone it and follow along.

The SDK vs. The API: What's the Actual Difference

With the standard Anthropic client SDK, you implement tool execution yourself:

// You write this loop. Every time.
let response = await client.messages.create({ ...params });
while (response.stop_reason === "tool_use") {
  const result = yourToolExecutor(response.tool_use);
  response = await client.messages.create({ tool_result: result, ...params });
}

With the Agent SDK:

import { query } from "@anthropic-ai/claude-agent-sdk";

for await (const message of query({
  prompt: "Find and fix the bug in auth.ts",
  options: { allowedTools: ["Read", "Edit", "Bash"] }
})) {
  console.log(message);
}

Claude reads the file, finds the bug, edits it. You stream the output. No tool loop, no executor, no boilerplate.

Built-in tools you get for free:

ToolWhat it does
ReadRead any file
WriteCreate files
EditPrecise edits
BashRun commands, git ops
GlobFind files by pattern
GrepRegex file search
WebSearchSearch the web
WebFetchFetch + parse URLs

That's Claude Code's entire toolset, programmable.

Why a TUI?

The Claude Code CLI is great for general use. But the moment you have a specific domain — a codebase with custom conventions, a workflow with specialized steps, a team with different permission needs — you want your own interface.

A custom TUI lets you:

  • Pre-load context your team cares about (architecture docs, style guides)
  • Lock down tools — a read-only reviewer can't accidentally edit prod
  • Surface domain-specific shortcuts — one keystroke to run your whole test suite
  • Pipe output into your CI/CD or logging infrastructure
  • Add hooks — audit every file change, block destructive operations, require approval

You're not replacing Claude Code. You're building the version of Claude Code that fits your workflow exactly.

Let's Build It

Clone the demo and install:

git clone https://github.com/mager/claude-tui-demo.git
cd claude-tui-demo
npm install
export ANTHROPIC_API_KEY=your-key

API credits: You'll need an Anthropic API key with credits. Top up at platform.claude.com/settings/billing.

I'm using Ink for the terminal UI. If you know React, you already know Ink — same component model, same hooks (useState, useEffect), same JSX. But instead of rendering to the DOM, it renders to your terminal. Box is your div. Text is your span. Flexbox and colors work exactly as you'd expect. It's the cleanest way to build interactive terminal UIs in TypeScript.

Note on the runner: The demo uses tsx instead of ts-node. tsx is zero-config — it handles .tsx, JSX, and ESM out of the box without loader flags. Also make sure "type": "module" is in your package.json — Ink's layout engine (yoga-layout) uses top-level await, which requires ESM mode. You'll hit a cryptic error without it.

Step 1: The Message Stream

// agent.ts
import { query } from "@anthropic-ai/claude-agent-sdk";

export async function* runAgent(prompt: string) {
  for await (const message of query({
    prompt,
    options: {
      allowedTools: ["Read", "Glob", "Grep", "Bash"],
    },
  })) {
    yield message;
  }
}

What's async function*? The * makes this a generator function — instead of computing everything and returning at once, it hands you one value at a time via yield, pausing between each. async means it can also await internally. On the consumer side, for await handles the async stream one message at a time. This is how the tool calls and responses stream to your UI as they happen, not after everything finishes.

Step 2: The TUI Component

Ink gives us React-style components for the terminal. Box handles layout, Text handles output with color and style support.

// App.tsx
import React, { useState, useEffect } from "react";
import { Box, Text, useInput, useApp } from "ink";
import { runAgent } from "./agent.js";

type LogLine = { type: "user" | "agent" | "tool" | "result"; text: string };

function formatToolCall(block: any): string {
  return `⚙ ${block.name}(${JSON.stringify(block.input).slice(0, 60)})`;
}

function handleAssistantMessage(msg: any, setLines: React.Dispatch<React.SetStateAction<LogLine[]>>) {
  for (const block of msg.message.content) {
    if (block.type === "text") {
      setLines((prev) => [...prev, { type: "agent", text: block.text }]);
    }
    if (block.type === "tool_use") {
      setLines((prev) => [...prev, { type: "tool", text: formatToolCall(block) }]);
    }
  }
}

export function App({ prompt }: { prompt: string }) {
  const [lines, setLines] = useState<LogLine[]>([]);
  const [done, setDone] = useState(false);
  const { exit } = useApp();

  useEffect(() => {
    setLines([{ type: "user", text: `> ${prompt}` }]);

    (async () => {
      for await (const msg of runAgent(prompt)) {
        if (msg.type === "assistant") handleAssistantMessage(msg, setLines);
        if (msg.type === "result") {
          setLines((prev) => [...prev, { type: "result", text: `✓ ${msg.result}` }]);
          setDone(true);
        }
      }
    })();
  }, []);

  useInput((_, key) => {
    if (key.escape || (key.ctrl && _.toLowerCase() === "c")) exit();
  });

  const colors: Record<LogLine["type"], string> = {
    user: "cyan",
    agent: "white",
    tool: "yellow",
    result: "green",
  };

  return (
    <Box flexDirection="column" padding={1}>
      <Box marginBottom={1}>
        <Text bold color="cyan">◆ My AI Terminal</Text>
        <Text color="gray">  (esc to quit)</Text>
      </Box>
      {lines.map((line, i) => (
        <Text key={i} color={colors[line.type]}>{line.text}</Text>
      ))}
      {!done && <Text color="gray">▸ thinking...</Text>}
    </Box>
  );
}

Message types: The SDK streams several message types — assistant (Claude's response), result (final outcome), system (init event with the session ID), and user (echoed input). Log msg.type during development to see everything flowing through.

Step 3: The Entry Point

// index.tsx
import React from "react";
import { render } from "ink";
import { App } from "./App.js";

const prompt = process.argv.slice(2).join(" ") || "What files are in this directory?";

render(<App prompt={prompt} />);

process.argv.slice(2) grabs everything after node and the script path — your actual typed arguments. .join(" ") reassembles multi-word prompts. Seven lines. That's the whole entry point.

Run it:

npm start "What files are in this directory?"

Claude TUI running — tool calls stream in yellow, result in green

You'll see Claude's tool calls stream in real-time — ⚙ Bash({"command":"ls"}) in yellow, the response in white, ✓ done in green. That's a working AI TUI in ~80 lines.

Level Up: The Forever Loop (REPL Mode)

The single-prompt TUI is great for one-shot tasks. But what if you want Claude to just... keep responding? Like the real Claude Code experience — type a prompt, get a response, type another?

That's a REPL, and it's a while (true) loop:

// repl.ts
import { query } from "@anthropic-ai/claude-agent-sdk";
import * as readline from "readline";

let sessionId: string | undefined;

const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
const ask = (prompt: string) => new Promise<string>((resolve) => rl.question(prompt, resolve));

async function runTurn(userPrompt: string) {
  for await (const msg of query({
    prompt: userPrompt,
    options: { allowedTools: ["Read", "Glob", "Grep", "Bash"], resume: sessionId },
  })) {
    if (msg.type === "system" && msg.subtype === "init") sessionId = msg.session_id;
    if (msg.type === "assistant") {
      for (const block of msg.message.content) {
        if (block.type === "text") process.stdout.write(`\n🤖 ${block.text}\n`);
        if (block.type === "tool_use") {
          process.stdout.write(`⚙  ${block.name}(${JSON.stringify(block.input).slice(0, 80)})\n`);
        }
      }
    }
  }
}

console.log("◆ Claude REPL — type your prompt, ctrl+c to quit\n");

while (true) {
  const input = await ask("\n> ");
  if (!input.trim()) continue;
  await runTurn(input.trim());
}

Run it with npm run repl. Type anything. Claude responds. Type again — it still has context from everything before. That's the resume: sessionId doing its job.

REPL demo — asking Claude why Chicago dyes the river green on St. Patty's Day

REPL demo — follow-up question about St. Patty's Day traditions in the midwest

Level Up: Hooks

The real power is hooks — callbacks that fire at key points in the agent lifecycle. This is how you add audit logs, approval gates, or custom UI feedback:

// agent.ts (with hooks)
import { query } from "@anthropic-ai/claude-agent-sdk";
import { appendFile } from "fs/promises";

const auditHook = async (input: any) => {
  const tool = input.tool_name ?? "unknown";
  const args = JSON.stringify(input.tool_input ?? {}).slice(0, 100);
  await appendFile("./audit.log", `${new Date().toISOString()}  ${tool}  ${args}\n`);
  return {};
};

for await (const message of query({
  prompt: "Refactor the auth module",
  options: {
    allowedTools: ["Read", "Edit", "Bash"],
    hooks: {
      PostToolUse: [{ matcher: ".*", hooks: [auditHook] }],
    },
  },
})) {
  // render to your TUI
}

Every tool call gets logged to audit.log with a timestamp. matcher: ".*" catches everything — narrow to "Edit|Write" if you only care about mutations.

Other hooks worth knowing: PreToolUse to block operations before they run, Stop to detect when the agent finishes, UserPromptSubmit to pre-process or validate input.

Level Up: Persistent Sessions

The agent remembers context across multiple query() calls. Capture the session ID from the first run, pass it to the next:

let sessionId: string | undefined;

// First turn — Claude reads the file
for await (const msg of query({ prompt: "Read the auth module" })) {
  if (msg.type === "system" && msg.subtype === "init") {
    sessionId = msg.session_id;
  }
}

// Second turn — zero tool calls, Claude already knows
for await (const msg of query({
  prompt: "Now find everything that calls it",
  options: { resume: sessionId },
})) {
  // ...
}

The money detail: the second turn fires zero tool calls — Claude already has the file in context. No re-reading, no extra API calls. It just answers.

Persistent session demo — same session ID across both turns, Turn 2 needs no tool calls

Run the demo: npm run session.

Bonus: Level Up with Rezi

Ink is great for quick TUIs. But if you want richer widgets — tables, command palettes, split panes, charts, modals — Rezi is the upgrade path. Still TypeScript, still Node.js, but native-backed rendering through a C engine and 50+ built-in widgets.

Where Ink feels like React (hooks, JSX, component tree), Rezi is state-driven: you define a view function that maps state → UI, and call app.update() to change state. Same mental model as Bubble Tea's Elm Architecture, but in TypeScript.

Install it:

npm install @rezi-ui/core @rezi-ui/node

Here's the same Claude TUI rebuilt in Rezi:

// rezi/rezi-app.ts
import { ui } from "@rezi-ui/core";
import { createNodeApp } from "@rezi-ui/node";
import { query } from "@anthropic-ai/claude-agent-sdk";

type LineKind = "user" | "agent" | "tool" | "result";
type LogLine = { kind: LineKind; text: string };
type State = { lines: LogLine[]; done: boolean };

const prompt = process.argv.slice(2).join(" ") || "What files are in this directory?";

const app = createNodeApp<State>({
  initialState: { lines: [{ kind: "user", text: `> ${prompt}` }], done: false },
});

const kindVariant: Record<LineKind, string> = {
  user: "info",
  agent: "body",
  tool: "warning",
  result: "success",
};

app.view((state) =>
  ui.page({
    p: 1,
    gap: 1,
    header: ui.header({ title: "◆ My AI Terminal", subtitle: "q to quit" }),
    body: ui.panel("Output", [
      ...state.lines.map((line, i) =>
        ui.text(line.text, { key: String(i), variant: kindVariant[line.kind] as any })
      ),
      ...(!state.done ? [ui.spinner({ label: "thinking…", key: "spinner" })] : []),
    ]),
  })
);

app.keys({ q: () => app.stop(), escape: () => app.stop() });

// Kick off the agent stream
(async () => {
  for await (const msg of query({
    prompt,
    options: { allowedTools: ["Read", "Glob", "Grep", "Bash"] },
  })) {
    if (msg.type === "assistant") {
      for (const block of msg.message.content) {
        if (block.type === "text") {
          app.update((s) => ({ ...s, lines: [...s.lines, { kind: "agent", text: block.text }] }));
        }
        if (block.type === "tool_use") {
          const preview = JSON.stringify(block.input).slice(0, 60);
          app.update((s) => ({
            ...s,
            lines: [...s.lines, { kind: "tool", text: `⚙ ${block.name}(${preview})` }],
          }));
        }
      }
    }
    if (msg.type === "result") {
      app.update((s) => ({
        ...s,
        lines: [...s.lines, { kind: "result", text: `✓ ${msg.result}` }],
        done: true,
      }));
    }
  }
})();

await app.start();

The key differences from the Ink version:

  • No Reactapp.view() is a pure function of state, not a component tree
  • No useEffect — the agent stream runs outside the view; app.update() pushes state changes in
  • ui.spinner() built in — no manual blinking text
  • Semantic variants (info, warning, success) — Rezi handles the colors per-theme

The full Rezi version lives in rezi/rezi-app.ts in the demo repo:

cd rezi
npm install
export ANTHROPIC_API_KEY=your-key
npm start "What files are in this directory?"

Ink vs Rezi at a glance:

InkRezi
Mental modelReact hooks + JSXState-driven, pure view fn
StateuseStateapp.update()
Side effectsuseEffectRun outside the view
StylingColor/bold propsSemantic variants + 6 built-in themes
Widget libraryMinimal (Text, Box)50+ (tables, modals, charts, command palette)
RenderingNode.jsNative C engine via Zireael
Best forQuick TUIs, React devsProduction tools, rich UIs

Both work perfectly with the Agent SDK stream. Ink is the fastest on-ramp; Rezi is where you go when you outgrow it.

Real-World Example: The Email Agent

Anthropic ships a reference implementation of this pattern — an email agent that reads your inbox, drafts replies, and sends them. It's a great study in how hooks + persistent sessions compose in production: PreToolUse to require approval before sending, PostToolUse to log every action, session resume to maintain context across a multi-step triage workflow. The same ~80-line skeleton we just built, extended into something genuinely useful.

When to Use the SDK vs. the CLI

ScenarioUse
Daily development, one-off tasksClaude Code CLI
CI/CD pipelinesSDK
Custom team toolsSDK
Domain-specific workflowsSDK
Production automationSDK
Audit trails + permission controlSDK

The workflows translate directly. Anything Claude Code can do in the CLI, the SDK can do programmatically.

The Bigger Picture

The Agent SDK is a general-purpose agent runtime — not just a coding tool. The built-in tools, the hooks system, the subagent delegation, the MCP support — it's a full agent platform.

The TUI is just one entry point. You could build:

  • A Slack bot where Claude actually edits your codebase
  • A CI/CD step that auto-fixes lint errors before merging
  • An internal tool where junior devs prompt in plain English and senior devs approve tool calls
  • A research agent with web search and file output

The pattern is always the same: for await (const message of query(...)). Stream it, render it, hook into it.

Explore further:

The terminal isn't going anywhere. Might as well make it yours.