@hasna/skills 0.1.45 → 0.1.47

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -170,7 +170,8 @@ var SKILL_ALIASES = {
170
170
  "pdf-reader": "read-pdf",
171
171
  "generate-image": "image",
172
172
  "image-generator": "image",
173
- "create-blog-article": "blog-article"
173
+ "create-blog-article": "blog-article",
174
+ "skill-diff": "diff-viewer"
174
175
  };
175
176
  function normalizeSkillSlug(name) {
176
177
  return name.trim();
@@ -199,7 +200,7 @@ var PREMIUM_SKILLS = [
199
200
  { slug: "brand-kit", displayName: "Brand Kit", tier: "premium", costCents: 400, providers: ["hosted"], description: "Hosted brand kit with logo usage, palette, typography, brand voice, sample applications, Markdown guide, PDF guide, and SVG assets" },
200
201
  { slug: "generate-book-cover", displayName: "Book Cover", tier: "premium", costCents: 20, providers: ["gpt-image-2"], description: "Professional book cover design from title and genre" },
201
202
  { slug: "remove-background", displayName: "Remove Background", tier: "premium", costCents: 10, providers: ["gemini-3-pro"], description: "AI-powered background removal from images" },
202
- { slug: "transcript", displayName: "Transcript", tier: "premium", costCents: 10, providers: ["whisper"], description: "Audio/video transcription with timestamps" },
203
+ { slug: "transcript", displayName: "Transcript", tier: "premium", costCents: 10, providers: ["openai", "elevenlabs", "deepgram", "hosted"], description: "Audio/video transcription with timestamps, diarization, and URL support" },
203
204
  { slug: "webcrawling", displayName: "Web Crawling", tier: "premium", costCents: 5, providers: ["firecrawl"], description: "Structured web page crawling and extraction" },
204
205
  { slug: "browse", displayName: "Browse", tier: "premium", costCents: 5, providers: ["browser"], description: "Web browsing and page interaction" },
205
206
  { slug: "read-pdf", displayName: "Read PDF", tier: "premium", costCents: 5, providers: ["cerebras"], description: "Hosted PDF extraction and structured content analysis" },
@@ -1320,12 +1321,47 @@ function ensurePortableSkillFiles(skillPath, manifest) {
1320
1321
  writeFileSync2(join3(skillPath, "skill.json"), renderSkillJson(next));
1321
1322
  if (!existsSync3(join3(skillPath, "AGENTS.md")))
1322
1323
  writeFileSync2(join3(skillPath, "AGENTS.md"), renderAgentsMd(next));
1323
- if (!existsSync3(join3(skillPath, "package.json")))
1324
- writeFileSync2(join3(skillPath, "package.json"), renderPackageJson(next));
1324
+ ensurePackageJson(skillPath, next);
1325
1325
  if (!existsSync3(join3(skillPath, "tsconfig.json")))
1326
1326
  writeFileSync2(join3(skillPath, "tsconfig.json"), renderTsconfig());
1327
1327
  return readPortableSkillManifest(skillPath, next.name);
1328
1328
  }
1329
+ function ensurePackageJson(skillPath, manifest) {
1330
+ const pkgPath = join3(skillPath, "package.json");
1331
+ const first = manifest.commands[0] ?? { name: manifest.name, entry: "src/index.ts" };
1332
+ const commandName = normalizePortableSkillName(first.name || manifest.name);
1333
+ const entry = (first.entry ?? "src/index.ts").replace(/^\.\//, "");
1334
+ if (!existsSync3(pkgPath)) {
1335
+ writeFileSync2(pkgPath, renderPackageJson(manifest));
1336
+ return;
1337
+ }
1338
+ const existing = readJsonObject(pkgPath);
1339
+ const bin = {};
1340
+ if (isRecord(existing.bin)) {
1341
+ for (const [name, value] of Object.entries(existing.bin)) {
1342
+ if (typeof value === "string" && value.trim())
1343
+ bin[normalizePortableSkillName(name)] = value.replace(/^\.\//, "");
1344
+ }
1345
+ } else {
1346
+ const binEntry = stringValue(existing.bin);
1347
+ if (binEntry)
1348
+ bin[manifest.name] = binEntry.replace(/^\.\//, "");
1349
+ }
1350
+ bin[commandName] = entry;
1351
+ const scripts = isRecord(existing.scripts) ? { ...existing.scripts } : {};
1352
+ if (!stringValue(scripts.dev))
1353
+ scripts.dev = `bun run ${entry}`;
1354
+ writeFileSync2(pkgPath, `${JSON.stringify({
1355
+ ...existing,
1356
+ name: manifest.name,
1357
+ version: manifest.version,
1358
+ description: manifest.description,
1359
+ type: stringValue(existing.type) ?? "module",
1360
+ bin,
1361
+ scripts
1362
+ }, null, 2)}
1363
+ `);
1364
+ }
1329
1365
  function copySkillDirectory(source, destination) {
1330
1366
  mkdirSync2(destination, { recursive: true });
1331
1367
  cpSync(source, destination, {
@@ -2771,9 +2807,9 @@ var MEDIA_PROCESSING_SKILLS = [
2771
2807
  {
2772
2808
  name: "transcript",
2773
2809
  displayName: "Transcript",
2774
- description: "Generate transcripts from audio and video files with timestamps",
2810
+ description: "Transcribe audio, video, and media URLs with OpenAI GPT-4o, ElevenLabs Scribe v2, DeepGram, or hosted runtime",
2775
2811
  category: "Media Processing",
2776
- tags: ["transcript", "audio", "video", "speech-to-text"]
2812
+ tags: ["transcript", "audio", "video", "speech-to-text", "diarization", "youtube"]
2777
2813
  },
2778
2814
  {
2779
2815
  name: "video-cut-suggester",
@@ -15447,7 +15483,7 @@ function finalize(ctx, schema) {
15447
15483
  result.$schema = "http://json-schema.org/draft-07/schema#";
15448
15484
  } else if (ctx.target === "draft-04") {
15449
15485
  result.$schema = "http://json-schema.org/draft-04/schema#";
15450
- } else if (ctx.target === "openapi-3.0") {}
15486
+ } else if (ctx.target === "openapi-3.0") {} else {}
15451
15487
  if (ctx.external?.uri) {
15452
15488
  const id = ctx.external.registry.get(schema)?.id;
15453
15489
  if (!id)
@@ -15695,7 +15731,7 @@ var literalProcessor = (schema, ctx, json, _params) => {
15695
15731
  if (val === undefined) {
15696
15732
  if (ctx.unrepresentable === "throw") {
15697
15733
  throw new Error("Literal `undefined` cannot be represented in JSON Schema");
15698
- }
15734
+ } else {}
15699
15735
  } else if (typeof val === "bigint") {
15700
15736
  if (ctx.unrepresentable === "throw") {
15701
15737
  throw new Error("BigInt literals cannot be represented in JSON Schema");
@@ -18776,7 +18812,7 @@ import { dirname as dirname4, relative as relative3 } from "path";
18776
18812
  // package.json
18777
18813
  var package_default = {
18778
18814
  name: "@hasna/skills",
18779
- version: "0.1.45",
18815
+ version: "0.1.47",
18780
18816
  description: "Skills library for AI coding agents",
18781
18817
  type: "module",
18782
18818
  bin: {
@@ -18845,7 +18881,7 @@ var package_default = {
18845
18881
  typescript: "^5"
18846
18882
  },
18847
18883
  dependencies: {
18848
- "@hasna/events": "^0.1.3",
18884
+ "@hasna/events": "^0.1.7",
18849
18885
  "@modelcontextprotocol/sdk": "^1.26.0",
18850
18886
  chalk: "^5.3.0",
18851
18887
  commander: "^12.1.0",
@@ -19029,18 +19065,29 @@ var runOutputSchema = objectSchema({
19029
19065
  exitCode: { type: "number", description: "Process exit code for local runs." },
19030
19066
  skill: stringSchema("Canonical skill slug."),
19031
19067
  remote: { type: "boolean", description: "Whether the skill was submitted to the hosted runtime." },
19032
- stdout: stringSchema("Captured stdout for local runs."),
19033
- stderr: stringSchema("Captured stderr for local runs."),
19068
+ stdoutPreview: objectSchema({
19069
+ text: stringSchema("Truncated stdout preview."),
19070
+ length: { type: "number" },
19071
+ truncated: { type: "boolean" }
19072
+ }, [], "Default compact stdout preview."),
19073
+ stderrPreview: objectSchema({
19074
+ text: stringSchema("Truncated stderr preview."),
19075
+ length: { type: "number" },
19076
+ truncated: { type: "boolean" }
19077
+ }, [], "Default compact stderr preview."),
19078
+ stdout: stringSchema("Captured stdout for local runs when detail:true is requested."),
19079
+ stderr: stringSchema("Captured stderr for local runs when detail:true is requested."),
19034
19080
  id: stringSchema("Remote run id when submitted remotely."),
19035
19081
  localRunId: stringSchema("Local run metadata id."),
19036
19082
  status: stringSchema("Run lifecycle status."),
19037
19083
  pricing: pricingSchema,
19038
- remoteRun: objectSchema({}, [], "Normalized hosted remote run contract.", true),
19039
- run: objectSchema({}, [], "Local run metadata.", true),
19084
+ remoteRun: objectSchema({}, [], "Compact hosted remote run summary by default; full contract when detail:true is requested.", true),
19085
+ run: objectSchema({}, [], "Compact local run metadata by default; full metadata when detail:true is requested.", true),
19040
19086
  nextActions: objectSchema({
19041
19087
  poll: stringSchema("Command to poll run status."),
19042
19088
  download: stringSchema("Command to download artifacts.")
19043
- })
19089
+ }),
19090
+ detailHint: stringSchema("How to request the complete payload.")
19044
19091
  }, [], "Skill run result.");
19045
19092
  var toolContracts = [
19046
19093
  {
@@ -19088,7 +19135,7 @@ var toolContracts = [
19088
19135
  {
19089
19136
  name: "list_skills",
19090
19137
  title: "List Skills",
19091
- description: "List skills from the basic or full registry profile.",
19138
+ description: "List skills from the basic or full registry profile. Returns a compact paged envelope by default.",
19092
19139
  params: ["category?", "profile?", "detail?", "limit?", "offset?"],
19093
19140
  category: "discovery",
19094
19141
  sideEffects: "none",
@@ -19104,7 +19151,11 @@ var toolContracts = [
19104
19151
  skills: arraySchema(skillSummarySchema),
19105
19152
  total: { type: "number" },
19106
19153
  offset: { type: "number" },
19107
- limit: { type: "number" }
19154
+ limit: { type: "number" },
19155
+ nextOffset: { type: "number" },
19156
+ hasMore: { type: "boolean" },
19157
+ nextArguments: objectSchema({}, [], "Arguments for the next page.", true),
19158
+ detailHint: stringSchema("How to request fuller skill objects.")
19108
19159
  })
19109
19160
  },
19110
19161
  {
@@ -19125,7 +19176,7 @@ var toolContracts = [
19125
19176
  {
19126
19177
  name: "search_skills",
19127
19178
  title: "Search Skills",
19128
- description: "Search skills by name, description, or tags.",
19179
+ description: "Search skills by name, description, or tags. Returns a compact paged envelope by default.",
19129
19180
  params: ["query", "profile?", "detail?", "limit?", "offset?"],
19130
19181
  category: "discovery",
19131
19182
  sideEffects: "none",
@@ -19137,7 +19188,16 @@ var toolContracts = [
19137
19188
  limit: { type: "number", minimum: 0 },
19138
19189
  offset: { type: "number", minimum: 0 }
19139
19190
  }, ["query"]),
19140
- outputSchema: objectSchema({ skills: arraySchema(skillSummarySchema) })
19191
+ outputSchema: objectSchema({
19192
+ skills: arraySchema(skillSummarySchema),
19193
+ total: { type: "number" },
19194
+ offset: { type: "number" },
19195
+ limit: { type: "number" },
19196
+ nextOffset: { type: "number" },
19197
+ hasMore: { type: "boolean" },
19198
+ nextArguments: objectSchema({}, [], "Arguments for the next page.", true),
19199
+ detailHint: stringSchema("How to request fuller skill objects.")
19200
+ })
19141
19201
  },
19142
19202
  {
19143
19203
  name: "get_skill_info",
@@ -19254,8 +19314,8 @@ var toolContracts = [
19254
19314
  {
19255
19315
  name: "run_skill",
19256
19316
  title: "Run Skill",
19257
- description: "Run a skill locally or through a configured remote runner.",
19258
- params: ["name", "input?", "args?", "approved?"],
19317
+ description: "Run a skill locally or through a configured remote runner. Returns compact stdout/stderr previews and run summaries by default; pass detail:true for full records.",
19318
+ params: ["name", "input?", "args?", "approved?", "detail?"],
19259
19319
  category: "execution",
19260
19320
  sideEffects: "local-process-or-remote-run",
19261
19321
  stable: true,
@@ -19263,28 +19323,33 @@ var toolContracts = [
19263
19323
  name: skillNameInput,
19264
19324
  input: runInputSchema,
19265
19325
  args: runArgsSchema,
19266
- approved: paidRunApprovalSchema
19326
+ approved: paidRunApprovalSchema,
19327
+ detail: { type: "boolean", default: false, description: "Return full stdout/stderr, remote run, and local run metadata." }
19267
19328
  }, ["name"]),
19268
19329
  outputSchema: runOutputSchema
19269
19330
  },
19270
19331
  {
19271
19332
  name: "get_run_status",
19272
19333
  title: "Get Run Status",
19273
- description: "Fetch remote run status and next actions.",
19274
- params: ["run_id"],
19334
+ description: "Fetch remote run status and next actions. Returns a compact status summary by default; pass detail:true for the complete remote run payload.",
19335
+ params: ["run_id", "detail?"],
19275
19336
  category: "execution",
19276
19337
  sideEffects: "none",
19277
19338
  stable: true,
19278
- inputSchema: objectSchema({ run_id: stringSchema("Remote or local run id.") }, ["run_id"]),
19339
+ inputSchema: objectSchema({
19340
+ run_id: stringSchema("Remote or local run id."),
19341
+ detail: { type: "boolean", default: false, description: "Return the complete remote run payload." }
19342
+ }, ["run_id"]),
19279
19343
  outputSchema: objectSchema({
19280
19344
  contractVersion: { type: "number", description: "Remote run payload contract version." },
19281
19345
  runId: stringSchema("Remote run id."),
19282
19346
  localRunId: stringSchema("Local run id."),
19283
- run: objectSchema({}, [], "Normalized remote run status.", true),
19347
+ run: objectSchema({}, [], "Compact remote run status by default; full status when detail:true is requested.", true),
19284
19348
  nextActions: objectSchema({
19285
19349
  poll: stringSchema("Command to poll run status."),
19286
19350
  download: stringSchema("Command to download artifacts.")
19287
- })
19351
+ }),
19352
+ detailHint: stringSchema("How to request the complete payload.")
19288
19353
  })
19289
19354
  },
19290
19355
  {
@@ -19379,13 +19444,25 @@ var toolContracts = [
19379
19444
  {
19380
19445
  name: "list_schedules",
19381
19446
  title: "List Schedules",
19382
- description: "List scheduled skill runs.",
19383
- params: [],
19447
+ description: "List scheduled skill runs as a compact paged envelope.",
19448
+ params: ["limit?", "offset?"],
19384
19449
  category: "scheduling",
19385
19450
  sideEffects: "none",
19386
19451
  stable: true,
19387
- inputSchema: objectSchema(),
19388
- outputSchema: arraySchema(objectSchema({}, [], "Schedule record.", true))
19452
+ inputSchema: objectSchema({
19453
+ limit: { type: "number", minimum: 0 },
19454
+ offset: { type: "number", minimum: 0 }
19455
+ }),
19456
+ outputSchema: objectSchema({
19457
+ schedules: arraySchema(objectSchema({}, [], "Compact schedule record.", true)),
19458
+ total: { type: "number" },
19459
+ offset: { type: "number" },
19460
+ limit: { type: "number" },
19461
+ nextOffset: { type: "number" },
19462
+ hasMore: { type: "boolean" },
19463
+ nextArguments: objectSchema({}, [], "Arguments for the next page.", true),
19464
+ detailHint: stringSchema("How to request complete schedule details.")
19465
+ })
19389
19466
  },
19390
19467
  {
19391
19468
  name: "remove_schedule",
@@ -0,0 +1,32 @@
1
+ export declare const DEFAULT_LIST_LIMIT = 30;
2
+ export declare const DEFAULT_SEARCH_LIMIT = 20;
3
+ export declare const DEFAULT_TAG_LIMIT = 80;
4
+ export declare const DEFAULT_MCP_LIMIT = 25;
5
+ export declare const MAX_PAGE_LIMIT = 200;
6
+ export declare const DEFAULT_PREVIEW_CHARS = 600;
7
+ export interface Page<T> {
8
+ items: T[];
9
+ total: number;
10
+ offset: number;
11
+ limit: number;
12
+ hasMore: boolean;
13
+ nextOffset: number | null;
14
+ }
15
+ export declare function truncateText(value: unknown, maxChars?: number): string;
16
+ export declare function previewText(value: unknown, maxChars?: number): {
17
+ text: string;
18
+ length: number;
19
+ truncated: boolean;
20
+ };
21
+ export declare function parsePageLimit(value: string | number | undefined, fallback: number, options?: {
22
+ max?: number;
23
+ allowAll?: boolean;
24
+ }): number;
25
+ export declare function parsePageOffset(value: string | number | undefined, fallback?: number): number;
26
+ export declare function paginate<T>(items: T[], options: {
27
+ limit: number;
28
+ offset?: number;
29
+ }): Page<T>;
30
+ export declare function showingLabel(total: number, shown: number, offset: number): string;
31
+ export declare function compactRunRecord(run: any): Record<string, unknown>;
32
+ export declare function compactRemoteRun(run: any): Record<string, unknown>;
@@ -11,6 +11,7 @@ export declare const SKILL_ALIASES: {
11
11
  readonly "generate-image": "image";
12
12
  readonly "image-generator": "image";
13
13
  readonly "create-blog-article": "blog-article";
14
+ readonly "skill-diff": "diff-viewer";
14
15
  };
15
16
  export type SkillAlias = keyof typeof SKILL_ALIASES;
16
17
  export declare function normalizeSkillSlug(name: string): string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/skills",
3
- "version": "0.1.45",
3
+ "version": "0.1.47",
4
4
  "description": "Skills library for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {
@@ -69,7 +69,7 @@
69
69
  "typescript": "^5"
70
70
  },
71
71
  "dependencies": {
72
- "@hasna/events": "^0.1.3",
72
+ "@hasna/events": "^0.1.7",
73
73
  "@modelcontextprotocol/sdk": "^1.26.0",
74
74
  "chalk": "^5.3.0",
75
75
  "commander": "^12.1.0",
@@ -1,100 +1,80 @@
1
1
  ---
2
2
  name: transcript
3
- description: Transcribe audio and video files using ElevenLabs Scribe, OpenAI Whisper, or Google Gemini. Supports automatic chunking for large files, speaker diarization, timestamps, and multiple output formats (text, SRT, VTT, JSON).
3
+ description: Transcribe audio, video, YouTube, Vimeo, and generic media URLs with iapp-transcriber or the hosted Skills runtime. Supports OpenAI GPT-4o transcription, OpenAI diarization, ElevenLabs Scribe v2, DeepGram, chunking, source metadata, subtitles, and JSON outputs.
4
4
  ---
5
5
 
6
- # Audio Transcription Skill
6
+ # Transcript
7
7
 
8
- This skill provides high-quality speech-to-text transcription using multiple AI providers. It automatically handles large files through compression and chunking.
8
+ Create transcripts from local audio/video files or media URLs. Use this skill when the user asks to transcribe, caption, diarize, summarize, or package spoken audio/video content.
9
9
 
10
- This CLI is API-backed. Set `SKILLS_API_KEY` when routing through the hosted skills/connectors runtime; provider-specific keys are managed by that runtime.
10
+ ## Choose The Runtime
11
11
 
12
- ## Supported Providers
12
+ - Use the hosted Skills runtime when the user explicitly runs `skills run transcript`, needs remote execution, or has only `SKILLS_API_KEY` configured.
13
+ - Use local `iapp-transcriber` when you are on this machine and need direct access to local files, YouTube/Vimeo/generic `yt-dlp` sources, transcript DB records, MCP tools, comments, exports, or OpenLoops follow-up workflows.
14
+ - The local command is `transcriber` when installed, or `bun run src/cli/index.ts` from `/home/hasna/Workspace/hasnaxyz/internalapp/iapp-transcriber`.
13
15
 
14
- ### ElevenLabs Scribe
15
- - **Accuracy**: 96.7% for English (industry-leading)
16
- - **Max file size**: 3GB / 10 hours
17
- - **Features**: Speaker diarization (up to 32 speakers), word-level timestamps
18
- - **Cost**: $0.40/hour
19
- - **Best for**: Multi-speaker recordings, highest accuracy needs
16
+ ## Hosted Usage
20
17
 
21
- ### OpenAI Whisper
22
- - **Accuracy**: Excellent
23
- - **Max file size**: 25MB (automatic chunking for larger files)
24
- - **Features**: Segment timestamps, language detection
25
- - **Cost**: $0.006/min ($0.003/min with GPT-4o Mini)
26
- - **Best for**: Standard transcription, good balance of cost and quality
18
+ ```bash
19
+ skills run transcript --source ./meeting.mp3 --title "Design review" --provider openai
20
+ skills run transcribe --source https://www.youtube.com/watch?v=... --provider openai --diarize
21
+ ```
27
22
 
28
- ### Google Gemini
29
- - **Accuracy**: Very good
30
- - **Max file size**: 2GB
31
- - **Features**: Multimodal analysis, summarization capabilities
32
- - **Cost**: ~$0.09-0.23/hour (generous free tier available)
33
- - **Best for**: Cost-sensitive projects, multimodal needs
23
+ Poll hosted runs with `skills runs status <run-id>` and download outputs with `skills exports download <run-id>`.
34
24
 
35
- ## Usage
25
+ ## Local Usage
36
26
 
37
- ### Basic Transcription
38
27
  ```bash
39
- bun run src/index.ts transcribe \
40
- --provider openai \
41
- --input ./recording.mp3
28
+ transcriber transcribe ./meeting.mp3 --provider openai --json
29
+ transcriber transcribe https://www.youtube.com/watch?v=... --provider openai --model gpt-4o-transcribe --json
30
+ transcriber transcribe ./meeting.mp3 --provider openai --diarize --json
31
+ transcriber export <transcript-id> --format srt --output captions.srt
42
32
  ```
43
33
 
44
- ### With Speaker Diarization
45
- ```bash
46
- bun run src/index.ts transcribe \
47
- --provider elevenlabs \
48
- --input ./meeting.mp3 \
49
- --diarize \
50
- --timestamps \
51
- --format srt
52
- ```
34
+ Local provider defaults:
53
35
 
54
- ### Export to Subtitles
55
- ```bash
56
- bun run src/index.ts transcribe \
57
- --provider gemini \
58
- --input ./video.mp4 \
59
- --format vtt \
60
- --output ./captions.vtt
61
- ```
36
+ - `openai`: default, uses `gpt-4o-transcribe`; `--diarize` uses `gpt-4o-transcribe-diarize`.
37
+ - `elevenlabs`: uses `scribe_v2`, supports diarization and keyterms.
38
+ - `deepgram`: uses Nova-3, supports diarization.
62
39
 
63
- ### View Provider Info
64
- ```bash
65
- bun run src/index.ts providers
66
- ```
40
+ Local requirements:
67
41
 
68
- ## Output Formats
42
+ - A configured provider credential for the selected local provider.
43
+ - `yt-dlp` for remote media URLs. Set `YTDLP_PATH` if needed.
44
+ - `ffmpeg`/`ffprobe`; the local app bundles npm ffmpeg/ffprobe and also respects `FFMPEG_PATH` and `FFPROBE_PATH`.
69
45
 
70
- | Format | Extension | Description |
71
- |--------|-----------|-------------|
72
- | text | .txt | Plain text transcript |
73
- | srt | .srt | SubRip subtitle format |
74
- | vtt | .vtt | WebVTT subtitle format |
75
- | json | .json | Full structured data with metadata |
46
+ ## Workflow
76
47
 
77
- ## Large File Handling
48
+ 1. Inspect source metadata first for URLs:
78
49
 
79
- The skill automatically handles files larger than provider limits:
50
+ ```bash
51
+ transcriber info <url> --json
52
+ ```
80
53
 
81
- - **Compression**: For OpenAI, files are first compressed using Opus codec
82
- - **Chunking**: Files are split into 10-minute segments with overlap
83
- - **Merging**: Results are intelligently merged to avoid duplicates
54
+ 2. Download audio when the user asks to keep media:
84
55
 
85
- ## Configuration
56
+ ```bash
57
+ transcriber download <url> --format mp3 --json
58
+ ```
86
59
 
87
- ```bash
88
- export SKILLS_API_KEY=your_skill_api_key
89
- ```
60
+ 3. Transcribe with JSON for automation:
90
61
 
91
- ## Dependencies
62
+ ```bash
63
+ transcriber transcribe <path-or-url> --provider openai --json
64
+ ```
92
65
 
93
- For chunking support (OpenAI with large files):
94
- - `ffmpeg` - Audio processing
95
- - `ffprobe` - Duration detection
66
+ 4. Export or post-process:
96
67
 
97
- Install on macOS:
98
- ```bash
99
- brew install ffmpeg
100
- ```
68
+ ```bash
69
+ transcriber get <id> --json
70
+ transcriber export <id> --format txt --output transcript.txt
71
+ transcriber summarize <id>
72
+ ```
73
+
74
+ 5. For repeat work, create OpenLoops command loops around JSON-producing commands, for example `transcriber feed check --json --dry-run`.
75
+
76
+ ## Safety
77
+
78
+ - Only fetch URLs the user is authorized to process.
79
+ - The local app rejects private/local URL hosts by default; set `TRANSCRIBER_ALLOW_PRIVATE_URLS=1` only for trusted internal sources.
80
+ - Prefer `--json` for scripts and OpenLoops so failures include a structured transcript record and nonzero exit code.
@@ -2,7 +2,7 @@
2
2
  "name": "transcript",
3
3
  "version": "1.0.0",
4
4
  "private": true,
5
- "description": "Audio/video transcription skill supporting ElevenLabs, OpenAI Whisper, and Google Gemini with automatic chunking for large files",
5
+ "description": "Audio/video transcription skill backed by iapp-transcriber, OpenAI GPT-4o transcription, ElevenLabs Scribe v2, and hosted Skills runtime",
6
6
  "type": "module",
7
7
  "skills": {
8
8
  "runtime": "hosted",
@@ -1,5 +0,0 @@
1
- {
2
- "env": {
3
- "CLAUDE_CODE_TASK_LIST_ID": "service-apidocs-dev"
4
- }
5
- }
@@ -1,5 +0,0 @@
1
- [install]
2
- peer = false
3
-
4
- [run]
5
- bun = true
@@ -1,5 +0,0 @@
1
- [install]
2
- peer = false
3
-
4
- [run]
5
- bun = true