text-summarizer
Summarise a chunk of text down to roughly `length` words using the agent's configured LLM provider. Input shape `{ text: string, length?: number }` on stdin, JSON; output shape `{ summary: string }` on stdout, JSON. Minimal: ~50 lines, no streaming, no retries — a deliberate base
Install
npx skills add https://github.com/ChronoAIProject/Ornn/tree/develop/examples/text-summarizer
claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install chronoaiproject-ornn@llmmart
git clone https://github.com/ChronoAIProject/Ornn.git
The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole chronoaiproject/ornn collection as a plugin from our marketplace. Git is the plain clone.
README
text-summarizer
Summarise input text using Claude. ~50 lines of TypeScript; pure stdin/stdout JSON.
Run: ANTHROPIC_API_KEY=sk-ant-... echo '{"text":"..."}' | bun run src/index.ts
Adapt: swap Anthropic SDK for another vendor; or wrap the call in retry/streaming. The I/O contract ({ text, length? } → { summary }) is intentionally fixed so the skill stays composable.
See SKILL.md for the full agent-facing contract.
Skill manifest
text-summarizer
A minimum-viable LLM skill — the smallest amount of code that takes structured input, calls an LLM, and emits structured output.
Contract
Input (stdin, JSON):
{ "text": "...long input...", "length": 60 }
text(string, required) — what to summarise.length(number, optional, default 60) — target word count for the summary.
Output (stdout, JSON):
{ "summary": "..." }
Errors — written to stderr as { "error": "...message..." } and exit code 1.
Required environment
| Var | Purpose |
|---|---|
ANTHROPIC_API_KEY |
Talks to Claude. Swap the SDK call to point at OpenAI / Gemini / your own backend; nothing else changes. |
Run locally
cd examples/text-summarizer
bun install
ANTHROPIC_API_KEY=sk-ant-... echo '{"text":"...","length":40}' | bun run src/index.ts
Adapt this
- Different model vendor — replace
Anthropicwith the SDK of your choice; the I/O shape stays. - Stream output — emit one JSON line per token instead of one final blob.
- Sanitise input — the current code passes
textto the model verbatim; for untrusted callers, strip control characters and cap length before the API call.
Files (ornn)
-
src
-
index.ts 1.9 KB
/** * text-summarizer example skill. * * Reads `{ text, length? }` from stdin (single JSON blob), asks Claude * for a summary of roughly `length` words, writes `{ summary }` to * stdout. On any failure: `{ error }` on stderr + exit code 1. * * Intentionally minimal — no retries, no streaming, no input * sanitisation. See SKILL.md "Adapt this" for production hardening. */ import Anthropic from "@anthropic-ai/sdk"; interface Input { text: string; length?: number; } async function readStdin(): Promise<string> { const chunks: Buffer[] = []; for await (const chunk of process.stdin) chunks.push(chunk as Buffer); return Buffer.concat(chunks).toString("utf8"); } async function main(): Promise<void> { const raw = (await readStdin()).trim(); if (!raw) { throw new Error("expected JSON `{ text, length? }` on stdin"); } const input = JSON.parse(raw) as Input; if (typeof input.text !== "string" || input.text.length === 0) { throw new Error("`text` is required and must be a non-empty string"); } const length = typeof input.length === "number" && input.length > 0 ? input.length : 60; const client = new Anthropic(); const message = await client.messages.create({ model: "claude-opus-4-7", max_tokens: Math.max(256, length * 4), messages: [ { role: "user", content: `Summarise the following text in approximately ${length} words. Reply with only the summary, no preamble.\n\n${input.text}`, }, ], }); const summary = message.content .filter((block): block is Anthropic.TextBlock => block.type === "text") .map((block) => block.text) .join("\n") .trim(); process.stdout.write(JSON.stringify({ summary }) + "\n"); } main().catch((err: unknown) => { const message = err instanceof Error ? err.message : String(err); process.stderr.write(JSON.stringify({ error: message }) + "\n"); process.exit(1); });
-
-
package.json 344 B
{ "name": "@ornn-examples/text-summarizer", "version": "1.0.0", "private": true, "description": "Minimal LLM-backed summarizer skill — example for the Ornn skill format", "type": "module", "main": "src/index.ts", "scripts": { "start": "bun run src/index.ts" }, "dependencies": { "@anthropic-ai/sdk": "^0.30.1" } } -
README.md 442 B
# text-summarizer Summarise input text using Claude. ~50 lines of TypeScript; pure stdin/stdout JSON. **Run:** `ANTHROPIC_API_KEY=sk-ant-... echo '{"text":"..."}' | bun run src/index.ts` **Adapt:** swap `Anthropic` SDK for another vendor; or wrap the call in retry/streaming. The I/O contract (`{ text, length? }` → `{ summary }`) is intentionally fixed so the skill stays composable. See `SKILL.md` for the full agent-facing contract. -
SKILL.md 1.8 KB
--- name: text-summarizer description: Summarise a chunk of text down to roughly `length` words using the agent's configured LLM provider. Input shape `{ text: string, length?: number }` on stdin, JSON; output shape `{ summary: string }` on stdout, JSON. Minimal: ~50 lines, no streaming, no retries — a deliberate baseline so the wiring is visible. For a production summariser, fork this and add retries, prompt-injection sanitisation, length validation, and per-model cost tracking. version: "1.0" license: MIT metadata: category: text tag: - example - llm - summarization - typescript --- # text-summarizer A minimum-viable LLM skill — the smallest amount of code that takes structured input, calls an LLM, and emits structured output. ## Contract **Input** (stdin, JSON): ```json { "text": "...long input...", "length": 60 } ``` - `text` (string, required) — what to summarise. - `length` (number, optional, default 60) — target word count for the summary. **Output** (stdout, JSON): ```json { "summary": "..." } ``` **Errors** — written to stderr as `{ "error": "...message..." }` and exit code `1`. ## Required environment | Var | Purpose | |---|---| | `ANTHROPIC_API_KEY` | Talks to Claude. Swap the SDK call to point at OpenAI / Gemini / your own backend; nothing else changes. | ## Run locally ```bash cd examples/text-summarizer bun install ANTHROPIC_API_KEY=sk-ant-... echo '{"text":"...","length":40}' | bun run src/index.ts ``` ## Adapt this - **Different model vendor** — replace `Anthropic` with the SDK of your choice; the I/O shape stays. - **Stream output** — emit one JSON line per token instead of one final blob. - **Sanitise input** — the current code passes `text` to the model verbatim; for untrusted callers, strip control characters and cap length before the API call.
Comments (0)
Sign in to join the conversation.
Reviews (0)
No reviews yet.
No comments yet.