otter-axi 0.1.0 → 1.1.0

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/README.md CHANGED
@@ -17,10 +17,13 @@ any agent session or shell, with refresh handled silently.
17
17
  ## Install & authenticate
18
18
 
19
19
  ```sh
20
- npx -y otter-axi auth login # one-time browser approval
20
+ npm install -g otter-axi # install the CLI on your PATH
21
+ otter-axi auth login # one-time browser approval
21
22
  otter-axi doctor # config → credentials → MCP reachable
22
23
  ```
23
24
 
25
+ Or run any command ad hoc without installing: `npx -y otter-axi <command>`.
26
+
24
27
  Tokens are stored in `~/.config/otter-axi/config.json` (mode `0600`) and refreshed
25
28
  automatically; they are never printed. Read-only scopes: `profile:read`, `conversations:read`.
26
29
 
@@ -44,14 +47,17 @@ Flags: `-q/--query`, `--after`/`--before` (ISO or relative `7d`/`2w`/`3m`/`1y`),
44
47
  ```sh
45
48
  otter-axi fetch <id> # metadata + preview
46
49
  otter-axi fetch <id> --full # verbatim transcript to stdout (for piping)
47
- otter-axi fetch <id> --text-out t.txt # verbatim transcript to a file
48
- otter-axi fetch <id> --json-out t.json # parsed segments [{start,speaker,text}]
49
- otter-axi fetch <id> --csv-out t.csv # parsed segments as CSV (--tsv-out for TSV)
50
+ otter-axi fetch <id> --json-out # parsed segments auto-path in the OS temp dir
51
+ otter-axi fetch <id> --json-out=t.json # …or an explicit path
52
+ otter-axi fetch <id> --csv-out # CSV (--tsv-out / --text-out likewise)
50
53
  ```
51
54
 
52
55
  The segment formats (`--json-out`/`--csv-out`/`--tsv-out`) parse the `[H:MM:SS] Speaker N: …`
53
56
  transcript into `{start, speaker, text}` rows — otter-axi owns one tested, lossless parser so
54
- agents don't re-derive it. Verbatim text stays the default; the parse never drops content.
57
+ agents don't re-derive it. Per the [AXI side-channel-file convention](https://github.com/kunchenguid/axi/issues/32),
58
+ the path is optional (bare → `<os-tmpdir>/otter-axi/<ts>-<id>.<ext>` — transient scratch the OS
59
+ cleans up), and writing a file is additive: stdout keeps the preview and adds `wrote:`/`columns:`
60
+ and a `jq` hint.
55
61
 
56
62
  ## Commands
57
63
 
@@ -1,5 +1,19 @@
1
1
  import type { StructuredOutput } from "../output.js";
2
- export declare const FETCH_HELP = "usage: otter-axi fetch <id|url> [output-mode]\nargs:\n <id|url> conversation slug or an https://otter.ai/u/<id> URL\noutput modes (at most one; default is a preview):\n --full print the entire verbatim transcript to stdout (for piping)\n --text-out <path> write the verbatim transcript text to a file (alias: --out)\n --json-out <path> write parsed segments [{start,speaker,text}] as JSON\n --csv-out <path> write parsed segments as CSV (start,speaker,text)\n --tsv-out <path> write parsed segments as TSV\nnotes:\n otter-axi owns the transcript parse; segment formats are lossless on content.";
2
+ export declare const FETCH_HELP = "usage: otter-axi fetch <id|url> [output-mode]\nargs:\n <id|url> conversation slug or an https://otter.ai/u/<id> URL\noutput modes (at most one; default is a preview):\n --full print the entire verbatim transcript to stdout (for piping)\n --text-out[=path] write the verbatim transcript text to a file (alias: --out)\n --json-out[=path] write parsed segments [{start,speaker,text}] as JSON\n --csv-out[=path] write parsed segments as CSV (start,speaker,text)\n --tsv-out[=path] write parsed segments as TSV\nnotes:\n Path is optional: bare flag auto-writes ~/.config/otter-axi/exports/<ts>-<id>.<ext>;\n use --json-out=path for an explicit location. Writing a file is additive \u2014 stdout keeps\n the preview and adds wrote/columns/jq help. otter-axi owns the lossless transcript parse.";
3
+ type OutFormat = "text" | "json" | "csv" | "tsv";
3
4
  /** Normalize a conversation slug or otter.ai URL to a bare id. */
4
5
  export declare function normalizeConversationId(input: string): string;
6
+ /**
7
+ * Explicit path (expanded), or an auto path in the OS temp dir keyed by timestamp + id.
8
+ * An auto-generated export is ephemeral scratch, so it goes in `os.tmpdir()` (OS-pruned) —
9
+ * never under `~/.config`, which nothing prunes. `os.tmpdir()` → `/tmp` on Linux, `$TMPDIR` on macOS.
10
+ */
11
+ export declare function resolveExportPath(explicit: string | undefined, format: OutFormat, id: string, now?: Date): string;
12
+ /**
13
+ * Write an export file. Auto-generated files (no explicit path) land in a world-readable temp
14
+ * dir and may hold a sensitive transcript → owner-only `0600`. Explicit paths are the caller's
15
+ * responsibility and use the default umask.
16
+ */
17
+ export declare function writeExport(path: string, body: string, auto: boolean): void;
5
18
  export declare function fetchCommand(args: string[]): Promise<StructuredOutput | string>;
19
+ export {};
@@ -1,4 +1,6 @@
1
- import { writeFileSync } from "node:fs";
1
+ import { mkdirSync, writeFileSync } from "node:fs";
2
+ import { homedir, tmpdir } from "node:os";
3
+ import { dirname, isAbsolute, join, resolve } from "node:path";
2
4
  import { Buffer } from "node:buffer";
3
5
  import { AxiError } from "axi-sdk-js";
4
6
  import { hasFlag, parseArgs, strFlag } from "../flags.js";
@@ -7,36 +9,66 @@ import { truncateCell } from "../output.js";
7
9
  import { parseTranscript, segmentsToCsv, segmentsToTsv, } from "../transcript.js";
8
10
  export const FETCH_HELP = `usage: otter-axi fetch <id|url> [output-mode]
9
11
  args:
10
- <id|url> conversation slug or an https://otter.ai/u/<id> URL
12
+ <id|url> conversation slug or an https://otter.ai/u/<id> URL
11
13
  output modes (at most one; default is a preview):
12
- --full print the entire verbatim transcript to stdout (for piping)
13
- --text-out <path> write the verbatim transcript text to a file (alias: --out)
14
- --json-out <path> write parsed segments [{start,speaker,text}] as JSON
15
- --csv-out <path> write parsed segments as CSV (start,speaker,text)
16
- --tsv-out <path> write parsed segments as TSV
14
+ --full print the entire verbatim transcript to stdout (for piping)
15
+ --text-out[=path] write the verbatim transcript text to a file (alias: --out)
16
+ --json-out[=path] write parsed segments [{start,speaker,text}] as JSON
17
+ --csv-out[=path] write parsed segments as CSV (start,speaker,text)
18
+ --tsv-out[=path] write parsed segments as TSV
17
19
  notes:
18
- otter-axi owns the transcript parse; segment formats are lossless on content.`;
19
- const VALUED = ["out", "text-out", "json-out", "csv-out", "tsv-out"];
20
+ Path is optional: bare flag auto-writes ~/.config/otter-axi/exports/<ts>-<id>.<ext>;
21
+ use --json-out=path for an explicit location. Writing a file is additive — stdout keeps
22
+ the preview and adds wrote/columns/jq help. otter-axi owns the lossless transcript parse.`;
20
23
  const PREVIEW_CHARS = 1200;
24
+ const EXT = { text: "txt", json: "json", csv: "csv", tsv: "tsv" };
25
+ // Flags that select a file-export format. NOT in `valued`, so a bare flag is boolean
26
+ // (→ auto-path) and an explicit path uses `--json-out=path` (avoids eating the <id> positional).
27
+ const OUT_FLAGS = [
28
+ { flag: "json-out", format: "json" },
29
+ { flag: "csv-out", format: "csv" },
30
+ { flag: "tsv-out", format: "tsv" },
31
+ { flag: "text-out", format: "text" },
32
+ { flag: "out", format: "text" }, // back-compat alias
33
+ ];
21
34
  /** Normalize a conversation slug or otter.ai URL to a bare id. */
22
35
  export function normalizeConversationId(input) {
23
36
  const trimmed = input.trim();
24
37
  const match = trimmed.match(/otter\.ai\/u\/([^/?#]+)/i);
25
38
  return match ? match[1] : trimmed;
26
39
  }
27
- function outPath(parsed, flag) {
28
- if (!hasFlag(parsed, flag))
29
- return undefined;
30
- const p = strFlag(parsed, flag);
31
- if (!p) {
32
- throw new AxiError(`--${flag} needs a file path`, "VALIDATION_ERROR", [
33
- `Run \`otter-axi fetch <id> --${flag} <path>\``,
34
- ]);
40
+ function expandPath(p) {
41
+ const e = p.startsWith("~/") ? join(homedir(), p.slice(2)) : p;
42
+ return isAbsolute(e) ? e : resolve(e);
43
+ }
44
+ /**
45
+ * Explicit path (expanded), or an auto path in the OS temp dir keyed by timestamp + id.
46
+ * An auto-generated export is ephemeral scratch, so it goes in `os.tmpdir()` (OS-pruned) —
47
+ * never under `~/.config`, which nothing prunes. `os.tmpdir()` → `/tmp` on Linux, `$TMPDIR` on macOS.
48
+ */
49
+ export function resolveExportPath(explicit, format, id, now = new Date()) {
50
+ if (explicit)
51
+ return expandPath(explicit);
52
+ const stamp = now.toISOString().replace(/[:.]/g, "-");
53
+ return join(tmpdir(), "otter-axi", `${stamp}-${id}.${EXT[format]}`);
54
+ }
55
+ /**
56
+ * Write an export file. Auto-generated files (no explicit path) land in a world-readable temp
57
+ * dir and may hold a sensitive transcript → owner-only `0600`. Explicit paths are the caller's
58
+ * responsibility and use the default umask.
59
+ */
60
+ export function writeExport(path, body, auto) {
61
+ mkdirSync(dirname(path), { recursive: true });
62
+ writeFileSync(path, body, auto ? { mode: 0o600 } : undefined);
63
+ }
64
+ function jqHelp(format, path) {
65
+ if (format === "json") {
66
+ return `Run \`jq -r '.[] | "[\\(.start)] \\(.speaker): \\(.text)"' ${path}\` to process the segments`;
35
67
  }
36
- return p;
68
+ return undefined;
37
69
  }
38
70
  export async function fetchCommand(args) {
39
- const parsed = parseArgs(args, { valued: VALUED });
71
+ const parsed = parseArgs(args);
40
72
  const raw = parsed.positionals[0];
41
73
  if (!raw) {
42
74
  throw new AxiError("Missing conversation id or URL", "VALIDATION_ERROR", [
@@ -45,14 +77,10 @@ export async function fetchCommand(args) {
45
77
  ]);
46
78
  }
47
79
  const id = normalizeConversationId(raw);
48
- const textPath = outPath(parsed, "text-out") ?? outPath(parsed, "out");
49
- const jsonPath = outPath(parsed, "json-out");
50
- const csvPath = outPath(parsed, "csv-out");
51
- const tsvPath = outPath(parsed, "tsv-out");
80
+ const present = OUT_FLAGS.filter((m) => hasFlag(parsed, m.flag));
52
81
  const full = hasFlag(parsed, "full");
53
- const modeCount = [textPath, jsonPath, csvPath, tsvPath].filter((p) => p !== undefined).length +
54
- (full ? 1 : 0);
55
- if (modeCount > 1) {
82
+ const distinctFormats = new Set(present.map((m) => m.format));
83
+ if (distinctFormats.size + (full ? 1 : 0) > 1) {
56
84
  throw new AxiError("Choose a single output mode", "VALIDATION_ERROR", [
57
85
  "Use one of --full | --text-out | --json-out | --csv-out | --tsv-out",
58
86
  ]);
@@ -69,7 +97,10 @@ export async function fetchCommand(args) {
69
97
  ]);
70
98
  }
71
99
  const text = t.text ?? "";
72
- const meta = {
100
+ // Raw transcript to stdout for piping — return a string so the SDK passes it through as-is.
101
+ if (full)
102
+ return text;
103
+ const base = {
73
104
  id: t.id ?? id,
74
105
  title: t.title ?? "",
75
106
  url: t.url ?? `https://otter.ai/u/${t.id ?? id}`,
@@ -79,54 +110,44 @@ export async function fetchCommand(args) {
79
110
  action_items: Array.isArray(t.metadata?.action_items)
80
111
  ? t.metadata.action_items.length
81
112
  : 0,
113
+ chars: text.length,
114
+ preview: truncateCell(text, PREVIEW_CHARS),
82
115
  };
83
- // Verbatim text → file (byte-exact, no parsing).
84
- if (textPath) {
85
- writeFileSync(textPath, text);
86
- return { ...meta, format: "text", saved: textPath, bytes: Buffer.byteLength(text) };
87
- }
88
- // Parsed segment formats → file.
89
- if (jsonPath || csvPath || tsvPath) {
90
- const segments = parseTranscript(text);
91
- const speakers = [...new Set(segments.map((s) => s.speaker).filter(Boolean))];
92
- let body;
93
- let path;
94
- let format;
95
- if (jsonPath) {
96
- body = `${JSON.stringify(segments, null, 2)}\n`;
97
- path = jsonPath;
98
- format = "json";
99
- }
100
- else if (csvPath) {
101
- body = segmentsToCsv(segments);
102
- path = csvPath;
103
- format = "csv";
104
- }
105
- else {
106
- body = segmentsToTsv(segments);
107
- path = tsvPath;
108
- format = "tsv";
109
- }
110
- writeFileSync(path, body);
116
+ if (present.length === 0) {
111
117
  return {
112
- ...meta,
113
- format,
114
- saved: path,
115
- bytes: Buffer.byteLength(body),
116
- segments: segments.length,
117
- speakers,
118
+ ...base,
119
+ help: [
120
+ "Export with --json-out / --csv-out / --tsv-out / --text-out (add =path for an explicit location)",
121
+ "--full prints the whole verbatim transcript to stdout",
122
+ ],
118
123
  };
119
124
  }
120
- // Raw transcript to stdout for piping return a string so the SDK passes it through as-is.
121
- if (full)
122
- return text;
123
- return {
124
- ...meta,
125
- chars: text.length,
126
- preview: truncateCell(text, PREVIEW_CHARS),
127
- help: [
128
- "Pass --text-out/--json-out/--csv-out/--tsv-out <path> to export, or --full to print all",
129
- ],
130
- };
125
+ // File export additive: keep the preview, write the file, add wrote/columns/jq help.
126
+ const format = present[0].format;
127
+ const explicit = present.map((m) => strFlag(parsed, m.flag)).find((v) => v !== undefined);
128
+ const path = resolveExportPath(explicit, format, id);
129
+ let body;
130
+ const extra = {};
131
+ if (format === "text") {
132
+ body = text;
133
+ }
134
+ else {
135
+ const segments = parseTranscript(text);
136
+ body =
137
+ format === "json"
138
+ ? `${JSON.stringify(segments, null, 2)}\n`
139
+ : format === "csv"
140
+ ? segmentsToCsv(segments)
141
+ : segmentsToTsv(segments);
142
+ extra.segments = segments.length;
143
+ extra.columns = "start, speaker, text";
144
+ }
145
+ // Auto-generated (no explicit path) → owner-only 0600 (sensitive transcript in a temp dir).
146
+ writeExport(path, body, explicit === undefined);
147
+ const help = [];
148
+ const jq = jqHelp(format, path);
149
+ if (jq)
150
+ help.push(jq);
151
+ return { ...base, wrote: path, bytes: Buffer.byteLength(body), ...extra, ...(help.length ? { help } : {}) };
131
152
  }
132
153
  //# sourceMappingURL=fetch.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"fetch.js","sourceRoot":"","sources":["../../../src/commands/fetch.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"fetch.js","sourceRoot":"","sources":["../../../src/commands/fetch.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "otter-axi",
3
- "version": "0.1.0",
3
+ "version": "1.1.0",
4
4
  "type": "module",
5
5
  "description": "Find and pull Otter.ai meeting transcripts from the terminal with token-efficient output.",
6
6
  "bin": {
@@ -37,6 +37,14 @@
37
37
  "vitest": "^4.1.9"
38
38
  },
39
39
  "author": "Jarvus Innovations",
40
+ "repository": {
41
+ "type": "git",
42
+ "url": "git+https://github.com/JarvusInnovations/otter-axi.git"
43
+ },
44
+ "homepage": "https://github.com/JarvusInnovations/otter-axi#readme",
45
+ "bugs": {
46
+ "url": "https://github.com/JarvusInnovations/otter-axi/issues"
47
+ },
40
48
  "keywords": [
41
49
  "otter",
42
50
  "otter.ai",
@@ -51,14 +51,16 @@ Tokens live in `~/.config/otter-axi/config.json` (mode 0600) and are never print
51
51
  ```sh
52
52
  otter-axi fetch <id> # metadata header + preview
53
53
  otter-axi fetch <id> --full # verbatim transcript to stdout (pipe it)
54
- otter-axi fetch <id> --text-out t.txt # verbatim transcript to a file
55
- otter-axi fetch <id> --json-out t.json # parsed segments [{start,speaker,text}]
56
- otter-axi fetch <id> --csv-out t.csv # parsed segments as CSV (--tsv-out for TSV)
54
+ otter-axi fetch <id> --json-out # parsed segments auto-path under exports/
55
+ otter-axi fetch <id> --json-out=t.json # …or an explicit path (note the = form)
56
+ otter-axi fetch <id> --csv-out # CSV (--tsv-out / --text-out likewise)
57
57
  ```
58
58
 
59
59
  Transcripts are `[H:MM:SS] Speaker N: …`. Default/`--full`/`--text-out` are verbatim; the
60
60
  `--json-out`/`--csv-out`/`--tsv-out` modes parse into `{start,speaker,text}` segments via
61
- otter-axi's own lossless parser (so you don't re-derive it). At most one output mode per call.
61
+ otter-axi's own lossless parser (so you don't re-derive it). Path is optional (bare
62
+ auto-path in the OS temp dir `<os-tmpdir>/otter-axi/`; `=path` for explicit); writing is additive —
63
+ stdout keeps the preview and adds `wrote:`/`columns:` + a `jq` hint. One output mode per call.
62
64
 
63
65
  ## Notes
64
66