@steipete/oracle 0.21.1 → 0.21.2

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.
Files changed (39) hide show
  1. package/dist/bin/oracle-cli.js +6 -10
  2. package/dist/src/browser/profileState.js +2 -0
  3. package/package.json +10 -10
  4. package/dist/docs-site/.nojekyll +0 -0
  5. package/dist/docs-site/CNAME +0 -1
  6. package/dist/docs-site/RELEASING.html +0 -403
  7. package/dist/docs-site/advisor.html +0 -317
  8. package/dist/docs-site/agents.html +0 -375
  9. package/dist/docs-site/anthropic.html +0 -368
  10. package/dist/docs-site/bridge.html +0 -421
  11. package/dist/docs-site/browser-mode.html +0 -637
  12. package/dist/docs-site/chromium-forks.html +0 -355
  13. package/dist/docs-site/cli-reference.html +0 -347
  14. package/dist/docs-site/configuration.html +0 -464
  15. package/dist/docs-site/favicon.svg +0 -14
  16. package/dist/docs-site/followup.html +0 -375
  17. package/dist/docs-site/gemini.html +0 -388
  18. package/dist/docs-site/grok.html +0 -325
  19. package/dist/docs-site/index.html +0 -360
  20. package/dist/docs-site/install.html +0 -335
  21. package/dist/docs-site/linux.html +0 -321
  22. package/dist/docs-site/llms.txt +0 -44
  23. package/dist/docs-site/manual-tests.html +0 -621
  24. package/dist/docs-site/mcp.html +0 -412
  25. package/dist/docs-site/multimodel.html +0 -364
  26. package/dist/docs-site/mythical-pro-agents.html +0 -360
  27. package/dist/docs-site/notifier.html +0 -338
  28. package/dist/docs-site/openai-endpoints.html +0 -417
  29. package/dist/docs-site/openrouter.html +0 -344
  30. package/dist/docs-site/quickstart.html +0 -369
  31. package/dist/docs-site/refactor/ux.html +0 -321
  32. package/dist/docs-site/sessions.html +0 -397
  33. package/dist/docs-site/social-card.png +0 -0
  34. package/dist/docs-site/social-card.svg +0 -79
  35. package/dist/docs-site/spec.html +0 -363
  36. package/dist/docs-site/testing.html +0 -323
  37. package/dist/docs-site/tui-debug.html +0 -326
  38. package/dist/docs-site/windows-work.html +0 -348
  39. package/dist/docs-site/windows.html +0 -320
@@ -368,6 +368,12 @@ program
368
368
  .addOption(new Option("--wait").default(undefined))
369
369
  .addOption(new Option("--no-wait").default(undefined).hideHelp())
370
370
  .showHelpAfterError("(use --help for usage)");
371
+ program.on("afterHelp", ({ error }) => {
372
+ if (!error && program.opts().verbose) {
373
+ console.log("");
374
+ printDebugHelp(program.name());
375
+ }
376
+ });
371
377
  program.addHelpText("after", `
372
378
  Examples:
373
379
  # Quick API run with two files
@@ -986,7 +992,6 @@ async function runRootCommand(options) {
986
992
  return;
987
993
  }
988
994
  const userConfig = (await loadUserConfig()).config;
989
- const helpRequested = rawCliArgs.some((arg) => arg === "--help" || arg === "-h");
990
995
  const multiModelProvided = Array.isArray(options.models) && options.models.length > 0;
991
996
  const optionUsesDefault = (name) => {
992
997
  // Commander reports undefined for untouched options, so treat undefined/default the same
@@ -996,15 +1001,6 @@ async function runRootCommand(options) {
996
1001
  if (multiModelProvided && !optionUsesDefault("model") && normalizeModelOption(options.model)) {
997
1002
  throw new Error("--models cannot be combined with --model.");
998
1003
  }
999
- if (helpRequested) {
1000
- if (options.verbose) {
1001
- console.log("");
1002
- printDebugHelp(program.name());
1003
- console.log("");
1004
- }
1005
- program.help({ error: false });
1006
- return;
1007
- }
1008
1004
  const previewMode = resolvePreviewMode(options.dryRun || options.preview);
1009
1005
  const mergedFileInputs = mergePathLikeOptions(options.file, options.include, options.files, options.path, options.paths);
1010
1006
  if (mergedFileInputs.length > 0) {
@@ -248,6 +248,8 @@ async function queryProcessStartTimeMs(pid) {
248
248
  maxBuffer: 1024 * 1024,
249
249
  windowsHide: true,
250
250
  timeout: 5000,
251
+ // Keep ps timestamps parseable regardless of the user's locale.
252
+ env: { ...process.env, LC_ALL: "C" },
251
253
  });
252
254
  const startedAt = Date.parse(String(stdout ?? "").trim());
253
255
  return Number.isFinite(startedAt) ? startedAt : null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@steipete/oracle",
3
- "version": "0.21.1",
3
+ "version": "0.21.2",
4
4
  "description": "CLI wrapper around OpenAI Responses API with GPT-5.6 Sol, GPT-5.6, GPT-5.5 Pro, GPT-5.5, GPT-5.4, GPT-5.2, GPT-5.1, and GPT-5.1 Codex high reasoning modes.",
5
5
  "keywords": [],
6
6
  "homepage": "https://askoracle.sh",
@@ -58,7 +58,7 @@
58
58
  },
59
59
  "dependencies": {
60
60
  "@anthropic-ai/tokenizer": "^0.0.4",
61
- "@google/genai": "^2.22.0",
61
+ "@google/genai": "^2.23.0",
62
62
  "@modelcontextprotocol/server": "^2.0.0",
63
63
  "@steipete/sweet-cookie": "^0.4.3",
64
64
  "chalk": "^6.0.0",
@@ -72,8 +72,8 @@
72
72
  "inquirer": "14.2.2",
73
73
  "json5": "^2.2.3",
74
74
  "kleur": "^4.1.5",
75
- "markdansi": "0.3.3",
76
- "openai": "^7.15.0",
75
+ "markdansi": "0.3.4",
76
+ "openai": "^7.20.0",
77
77
  "osc-progress": "^0.3.3",
78
78
  "qs": "^6.16.0",
79
79
  "shiki": "^4.4.3",
@@ -86,17 +86,17 @@
86
86
  "@modelcontextprotocol/client": "^2.0.0",
87
87
  "@modelcontextprotocol/sdk": "^1.30.0",
88
88
  "@types/chrome-remote-interface": "^0.34.0",
89
- "@types/node": "^26.5.1",
90
- "@vitest/coverage-v8": "5.0.0",
91
- "devtools-protocol": "0.0.1695952",
89
+ "@types/node": "^26.6.2",
90
+ "@vitest/coverage-v8": "5.0.1",
91
+ "devtools-protocol": "0.0.1701330",
92
92
  "es-toolkit": "^1.52.0",
93
93
  "esbuild": "^0.28.2",
94
- "oxfmt": "0.67.0",
94
+ "oxfmt": "0.68.0",
95
95
  "oxlint": "^1.82.0",
96
96
  "puppeteer-core": "^25.10.0",
97
97
  "tsx": "^4.23.13",
98
98
  "typescript": "^7.0.2",
99
- "vitest": "5.0.0"
99
+ "vitest": "5.0.1"
100
100
  },
101
101
  "devEngines": {
102
102
  "runtime": [
@@ -109,5 +109,5 @@
109
109
  "engines": {
110
110
  "node": ">=24"
111
111
  },
112
- "packageManager": "pnpm@11.26.0"
112
+ "packageManager": "pnpm@11.27.0"
113
113
  }
File without changes
@@ -1 +0,0 @@
1
- askoracle.sh
@@ -1,403 +0,0 @@
1
- <!doctype html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="utf-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1">
6
- <title>Release Checklist (npm + Homebrew) — oracle</title>
7
- <meta name="description" content="Release Checklist (npm + Homebrew) — oracle CLI documentation.">
8
- <link rel="canonical" href="https://askoracle.sh/RELEASING.html">
9
- <meta property="og:type" content="website">
10
- <meta property="og:site_name" content="oracle">
11
- <meta property="og:title" content="Release Checklist (npm + Homebrew) — oracle">
12
- <meta property="og:description" content="Release Checklist (npm + Homebrew) — oracle CLI documentation.">
13
- <meta property="og:url" content="https://askoracle.sh/RELEASING.html">
14
- <meta property="og:image" content="https://askoracle.sh/social-card.png">
15
- <meta property="og:image:width" content="1200">
16
- <meta property="og:image:height" content="630">
17
- <meta name="twitter:card" content="summary_large_image">
18
- <meta name="twitter:title" content="Release Checklist (npm + Homebrew) — oracle">
19
- <meta name="twitter:description" content="Release Checklist (npm + Homebrew) — oracle CLI documentation.">
20
- <meta name="twitter:image" content="https://askoracle.sh/social-card.png">
21
- <link rel="icon" href="favicon.svg" type="image/svg+xml">
22
- <link rel="preconnect" href="https://fonts.googleapis.com">
23
- <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
24
- <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
25
- <script>(function(){var s;try{s=localStorage.getItem('theme')}catch(e){}var d=window.matchMedia&&matchMedia('(prefers-color-scheme: dark)').matches;document.documentElement.dataset.theme=s||(d?'dark':'light')})();</script>
26
- <style>
27
- :root{
28
- --ink:#0e0a1f;
29
- --text:#1d1832;
30
- --muted:#6b6582;
31
- --subtle:#9c95b5;
32
- --bg:#fafaff;
33
- --paper:#ffffff;
34
- --accent:#7c3aed;
35
- --accent-soft:rgba(124,58,237,.10);
36
- --accent-strong:#5b21b6;
37
- --accent-2:#0ea5e9;
38
- --accent-glow:#a78bfa;
39
- --line:#e7e3f0;
40
- --line-soft:#f2eff8;
41
- --code-bg:#0c0a1a;
42
- --code-fg:#e9e6f5;
43
- --code-inline-fg:#1c1734;
44
- --pill-border:#dcd5ec;
45
- --shadow-card:0 4px 14px rgba(14,10,31,.08);
46
- --scrollbar:#cbc4dc;
47
- }
48
- :root[data-theme="dark"]{
49
- --ink:#f5f2ff;
50
- --text:#cec7e4;
51
- --muted:#9189a8;
52
- --subtle:#6a6383;
53
- --bg:#0a0815;
54
- --paper:#15102a;
55
- --accent:#a78bfa;
56
- --accent-soft:rgba(167,139,250,.18);
57
- --accent-strong:#c4b5fd;
58
- --accent-2:#38bdf8;
59
- --accent-glow:#c4b5fd;
60
- --line:#272140;
61
- --line-soft:#1c1734;
62
- --code-bg:#06040d;
63
- --code-fg:#e9e6f5;
64
- --code-inline-fg:#e9e6f5;
65
- --pill-border:#2c2549;
66
- --shadow-card:0 4px 18px rgba(0,0,0,.45);
67
- --scrollbar:#3a3358;
68
- }
69
- :root{color-scheme:light}
70
- :root[data-theme="dark"]{color-scheme:dark}
71
- *{box-sizing:border-box}
72
- html{scroll-behavior:smooth;scroll-padding-top:24px}
73
- body{margin:0;background:var(--bg);color:var(--text);font-family:"Inter",ui-sans-serif,system-ui,-apple-system,Segoe UI,sans-serif;line-height:1.65;overflow-x:hidden;-webkit-font-smoothing:antialiased;font-feature-settings:"cv02","cv03","cv04","cv11";transition:background-color .18s,color .18s}
74
- ::selection{background:var(--accent);color:#fff}
75
- a{color:var(--accent);text-decoration:none;transition:color .12s}
76
- a:hover{text-decoration:underline;text-underline-offset:.2em}
77
- .shell{display:grid;grid-template-columns:268px minmax(0,1fr);min-height:100vh}
78
- .sidebar{position:sticky;top:0;height:100vh;overflow:auto;padding:24px 22px;background:var(--paper);border-right:1px solid var(--line);scrollbar-width:thin;scrollbar-color:var(--line) transparent;transition:background-color .18s,border-color .18s}
79
- .sidebar::-webkit-scrollbar{width:6px}
80
- .sidebar::-webkit-scrollbar-thumb{background:var(--line);border-radius:6px}
81
- .sidebar-head{display:flex;align-items:center;gap:10px;margin-bottom:24px}
82
- .brand{display:flex;align-items:center;gap:11px;color:var(--ink);text-decoration:none;flex:1;min-width:0}
83
- .brand:hover{text-decoration:none}
84
- .brand .mark{flex:0 0 30px;width:30px;height:30px;border-radius:50%;background:radial-gradient(circle at 32% 32%,#fff 0,#e0d4ff 22%,#7c3aed 60%,#1e1240 100%);box-shadow:0 0 0 1px rgba(124,58,237,.35),0 6px 18px rgba(124,58,237,.35);position:relative}
85
- .brand .mark::after{content:"";position:absolute;left:50%;top:50%;width:9px;height:9px;border-radius:50%;background:#0c0820;transform:translate(-50%,-50%)}
86
- .brand strong{display:block;font-size:1.05rem;line-height:1.1;font-weight:600;letter-spacing:0;color:var(--ink)}
87
- .brand small{display:block;color:var(--muted);font-size:.74rem;margin-top:3px;font-weight:400}
88
- .theme-toggle{display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto;width:34px;height:34px;border-radius:8px;border:1px solid var(--line);background:var(--paper);color:var(--muted);cursor:pointer;padding:0;transition:border-color .15s,color .15s,background-color .15s,transform .12s}
89
- .theme-toggle:hover{border-color:var(--ink);color:var(--ink)}
90
- .theme-toggle:active{transform:scale(.94)}
91
- .theme-toggle svg{width:16px;height:16px;display:block}
92
- .theme-icon-sun{display:none}
93
- :root[data-theme="dark"] .theme-icon-sun{display:block}
94
- :root[data-theme="dark"] .theme-icon-moon{display:none}
95
- .search{display:block;margin:0 0 22px}
96
- .search span{display:block;color:var(--muted);font-size:.7rem;font-weight:600;text-transform:uppercase;letter-spacing:0;margin-bottom:7px}
97
- .search input{width:100%;border:1px solid var(--line);background:var(--paper);border-radius:8px;padding:9px 12px;font:inherit;font-size:.9rem;color:var(--text);outline:none;transition:border-color .15s,box-shadow .15s,background-color .18s}
98
- .search input:focus{border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-soft)}
99
- nav section{margin:0 0 18px}
100
- nav h2{font-size:.68rem;color:var(--muted);text-transform:uppercase;letter-spacing:0;margin:0 0 6px;font-weight:600}
101
- .nav-link{display:block;color:var(--text);text-decoration:none;border-radius:6px;padding:5px 10px;margin:1px 0;font-size:.9rem;line-height:1.4;transition:background .12s,color .12s}
102
- .nav-link:hover{background:var(--line-soft);color:var(--ink);text-decoration:none}
103
- .nav-link.active{background:var(--accent-soft);color:var(--accent);font-weight:600}
104
- main{min-width:0;padding:32px clamp(20px,4.5vw,56px) 80px;max-width:1180px;margin:0 auto;width:100%}
105
- .hero{display:flex;align-items:flex-end;justify-content:space-between;gap:22px;border-bottom:1px solid var(--line);padding:8px 0 22px;margin-bottom:8px;flex-wrap:wrap}
106
- .hero-text{min-width:0;flex:1 1 320px}
107
- .eyebrow{margin:0 0 8px;color:var(--muted);font-weight:600;text-transform:uppercase;letter-spacing:0;font-size:.7rem}
108
- .hero h1{font-size:2.25rem;line-height:1.1;letter-spacing:0;margin:0;font-weight:700;color:var(--ink)}
109
- .hero-meta{display:flex;gap:8px;flex:0 0 auto;flex-wrap:wrap}
110
- .repo,.edit,.btn-ghost{border:1px solid var(--line);color:var(--text);text-decoration:none;border-radius:7px;padding:6px 11px;font-weight:500;font-size:.83rem;background:var(--paper);transition:border-color .15s,color .15s,background .15s}
111
- .repo:hover,.edit:hover,.btn-ghost:hover{border-color:var(--ink);color:var(--ink);text-decoration:none}
112
- .edit{color:var(--muted)}
113
- .home-hero{position:relative;padding:24px 0 32px;margin-bottom:8px;border-bottom:1px solid var(--line)}
114
- .home-hero>*{position:relative;z-index:1}
115
- .home-hero h1{font-size:3.4rem;line-height:1.04;letter-spacing:0;margin:0 0 .35em;font-weight:700;color:var(--ink);background:linear-gradient(135deg,var(--ink) 0,#7c3aed 60%,#0ea5e9 100%);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent}
116
- :root[data-theme="dark"] .home-hero h1{background:linear-gradient(135deg,#f5f2ff 0,#c4b5fd 50%,#7dd3fc 100%);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent}
117
- .home-hero .lede{font-size:1.18rem;line-height:1.55;color:var(--text);margin:0 0 1.2em;max-width:62ch}
118
- .home-cta{display:flex;flex-wrap:wrap;gap:10px;align-items:center;margin:0 0 18px}
119
- .home-cta .btn{display:inline-flex;align-items:center;gap:7px;border-radius:8px;padding:10px 16px;font-weight:600;font-size:.92rem;text-decoration:none;transition:background .15s,border-color .15s,color .15s,transform .12s}
120
- .home-cta .btn-primary{background:linear-gradient(135deg,var(--accent),var(--accent-strong));color:#fff;border:1px solid var(--accent);box-shadow:0 4px 14px rgba(124,58,237,.35)}
121
- .home-cta .btn-primary:hover{background:var(--accent-strong);border-color:var(--accent-strong);text-decoration:none;transform:translateY(-1px)}
122
- .home-cta .btn-ghost{padding:10px 16px}
123
- .home-install{display:flex;align-items:center;gap:12px;background:var(--code-bg);color:var(--code-fg);border-radius:8px;padding:10px 10px 10px 16px;font:500 .9rem/1.2 "JetBrains Mono","SF Mono",ui-monospace,monospace;max-width:34em;border:1px solid #1f1840}
124
- .home-install .prompt{color:#6f63a3;user-select:none;flex:0 0 auto}
125
- .home-install code{flex:1;background:transparent;border:0;color:var(--code-fg);font:inherit;padding:0;white-space:pre;overflow:hidden;text-overflow:ellipsis}
126
- .home-install .copy{flex:0 0 auto;background:rgba(255,255,255,.08);color:var(--code-fg);border:1px solid rgba(255,255,255,.16);border-radius:6px;padding:5px 11px;font:500 .72rem/1 "Inter",sans-serif;cursor:pointer;transition:background .15s,border-color .15s}
127
- .home-install .copy:hover{background:rgba(255,255,255,.16)}
128
- .home-install .copy.copied{background:var(--accent);border-color:var(--accent)}
129
- .home-services{display:flex;flex-wrap:wrap;gap:6px;margin:6px 0 18px}
130
- .home-services span{display:inline-block;padding:3px 10px;border:1px solid var(--pill-border);border-radius:999px;font-size:.78rem;color:var(--muted);background:var(--paper)}
131
- .home-services span.pill-pro{background:var(--accent-soft);color:var(--accent);border-color:transparent;font-weight:600}
132
- .home-visual{display:block;width:min(100%,620px);height:auto;margin:22px 0 0;border-radius:8px;border:1px solid var(--line);box-shadow:var(--shadow-card);background:var(--paper)}
133
- .doc-grid{display:grid;grid-template-columns:minmax(0,1fr);gap:48px;margin-top:24px}
134
- .doc-grid-home{margin-top:8px}
135
- @media(min-width:1180px){.doc-grid{grid-template-columns:minmax(0,72ch) 200px;justify-content:start}.doc-grid-home{grid-template-columns:minmax(0,76ch);justify-content:start}}
136
- .doc{min-width:0;max-width:72ch;overflow-wrap:break-word}
137
- .doc-home{max-width:76ch}
138
- .doc h1{font-size:2.6rem;line-height:1.08;letter-spacing:0;margin:0 0 .4em;font-weight:700;color:var(--ink)}
139
- body:not(.home) .doc>h1:first-child{display:none}
140
- .doc h2{font-size:1.45rem;line-height:1.2;margin:2em 0 .5em;font-weight:600;letter-spacing:0;color:var(--ink);position:relative}
141
- .doc h3{font-size:1.1rem;margin:1.7em 0 .35em;position:relative;font-weight:600;color:var(--ink);letter-spacing:0}
142
- .doc h4{font-size:.98rem;margin:1.4em 0 .25em;color:var(--ink);position:relative;font-weight:600}
143
- .doc h2:first-child,.doc h3:first-child,.doc h4:first-child{margin-top:.2em}
144
- .doc :is(h2,h3,h4) .anchor{position:absolute;left:-1.05em;top:0;color:var(--subtle);opacity:0;text-decoration:none;font-weight:400;padding-right:.3em;transition:opacity .12s,color .12s}
145
- .doc :is(h2,h3,h4):hover .anchor{opacity:.7}
146
- .doc :is(h2,h3,h4) .anchor:hover{opacity:1;color:var(--accent);text-decoration:none}
147
- .doc p{margin:0 0 1.05em}
148
- .doc ul,.doc ol{padding-left:1.3rem;margin:0 0 1.15em}
149
- .doc li{margin:.25em 0}
150
- .doc li>p{margin:0 0 .4em}
151
- .doc strong{font-weight:600;color:var(--ink)}
152
- .doc em{font-style:italic}
153
- .doc code{font-family:"JetBrains Mono","SF Mono",ui-monospace,monospace;font-size:.84em;background:var(--line-soft);border:1px solid var(--line);border-radius:5px;padding:.08em .35em;color:var(--code-inline-fg)}
154
- .doc pre{position:relative;overflow:auto;background:var(--code-bg);color:var(--code-fg);border-radius:8px;padding:14px 18px;margin:1.3em 0;font-size:.85em;line-height:1.6;scrollbar-width:thin;scrollbar-color:#3a3358 transparent;border:1px solid #221c40}
155
- .doc pre.shiki{background:var(--code-bg)!important;color:var(--code-fg)!important}
156
- .doc pre::-webkit-scrollbar{height:8px;width:8px}
157
- .doc pre::-webkit-scrollbar-thumb{background:#3a3358;border-radius:8px}
158
- .doc pre code{display:block;background:transparent;border:0;color:inherit;padding:0;font-size:1em;white-space:pre}
159
- .doc pre code .line{display:block;min-height:1.6em}
160
- .doc pre .copy{position:absolute;top:8px;right:8px;background:rgba(255,255,255,.06);color:var(--code-fg);border:1px solid rgba(255,255,255,.16);border-radius:6px;padding:3px 9px;font:500 .7rem/1 "Inter",sans-serif;cursor:pointer;opacity:0;transition:opacity .15s,background .15s,border-color .15s}
161
- .doc pre:hover .copy,.doc pre .copy:focus{opacity:1}
162
- .doc pre .copy:hover{background:rgba(255,255,255,.12)}
163
- .doc pre .copy.copied{background:var(--accent);border-color:var(--accent);opacity:1}
164
- .doc blockquote{margin:1.4em 0;padding:10px 16px;border-left:3px solid var(--accent);background:var(--accent-soft);border-radius:0 8px 8px 0;color:var(--text)}
165
- .doc blockquote p:last-child{margin-bottom:0}
166
- .doc table{width:100%;border-collapse:collapse;margin:1.2em 0;font-size:.92em}
167
- .doc th,.doc td{border-bottom:1px solid var(--line);padding:9px 10px;text-align:left;vertical-align:top}
168
- .doc th{font-weight:600;color:var(--ink);background:var(--line-soft);border-bottom:1px solid var(--line)}
169
- .doc hr{border:0;border-top:1px solid var(--line);margin:2.2em 0}
170
- .toc{position:sticky;top:24px;align-self:start;font-size:.84rem;padding-left:14px;border-left:1px solid var(--line);max-height:calc(100vh - 48px);overflow:auto;scrollbar-width:thin;scrollbar-color:var(--line) transparent}
171
- .toc::-webkit-scrollbar{width:5px}
172
- .toc::-webkit-scrollbar-thumb{background:var(--line);border-radius:5px}
173
- .toc h2{font-size:.66rem;color:var(--muted);text-transform:uppercase;letter-spacing:0;margin:0 0 10px;font-weight:600}
174
- .toc a{display:block;color:var(--muted);text-decoration:none;padding:4px 0 4px 10px;line-height:1.35;border-left:2px solid transparent;margin-left:-12px;transition:color .12s,border-color .12s}
175
- .toc a:hover{color:var(--ink);text-decoration:none}
176
- .toc a.active{color:var(--accent);border-left-color:var(--accent);font-weight:500}
177
- .toc-l3{padding-left:22px!important;font-size:.94em}
178
- @media(max-width:1179px){.toc{display:none}}
179
- .page-nav{display:grid;grid-template-columns:1fr 1fr;gap:14px;margin-top:48px;border-top:1px solid var(--line);padding-top:20px}
180
- .page-nav>a{display:block;border:1px solid var(--line);background:var(--paper);border-radius:9px;padding:13px 16px;text-decoration:none;color:var(--text);transition:border-color .15s,transform .15s,box-shadow .15s,background-color .18s}
181
- .page-nav>a:hover{border-color:var(--accent);text-decoration:none;color:var(--ink)}
182
- .page-nav small{display:block;color:var(--muted);font-size:.7rem;text-transform:uppercase;letter-spacing:0;margin-bottom:5px;font-weight:600}
183
- .page-nav span{display:block;font-weight:600;line-height:1.3;color:var(--ink)}
184
- .page-nav-prev{text-align:left}
185
- .page-nav-next{text-align:right;grid-column:2}
186
- .page-nav-prev:only-child{grid-column:1}
187
- .nav-toggle{display:none;position:fixed;top:14px;right:14px;top:calc(14px + env(safe-area-inset-top, 0px));right:calc(14px + env(safe-area-inset-right, 0px));z-index:20;width:40px;height:40px;border-radius:9px;background:var(--paper);border:1px solid var(--line);color:var(--ink);cursor:pointer;padding:10px 9px;flex-direction:column;align-items:stretch;justify-content:space-between;box-shadow:var(--shadow-card)}
188
- .nav-toggle span{display:block;width:100%;height:2px;flex:0 0 2px;background:currentColor;border-radius:2px;transition:transform .2s,opacity .2s}
189
- .nav-toggle[aria-expanded="true"] span:nth-child(1){transform:translateY(8px) rotate(45deg)}
190
- .nav-toggle[aria-expanded="true"] span:nth-child(2){opacity:0}
191
- .nav-toggle[aria-expanded="true"] span:nth-child(3){transform:translateY(-8px) rotate(-45deg)}
192
- @media(max-width:900px){
193
- .shell{display:block}
194
- .sidebar{position:fixed;inset:0 30% 0 0;max-width:320px;height:100vh;z-index:15;transform:translateX(-100%);transition:transform .25s ease,background-color .18s,border-color .18s;box-shadow:0 18px 40px rgba(0,0,0,.18);background:var(--paper);pointer-events:none}
195
- .sidebar.open{transform:translateX(0);pointer-events:auto}
196
- .nav-toggle{display:flex}
197
- main{padding:64px 18px 56px}
198
- .hero{padding-top:6px}
199
- .hero h1{font-size:1.8rem}
200
- .home-hero h1{font-size:2.45rem}
201
- .doc h1{font-size:2.1rem}
202
- .hero-meta{width:100%;justify-content:flex-start}
203
- .home-hero{padding-top:8px}
204
- .home-visual{margin-top:18px}
205
- .doc{padding:0}
206
- .doc-grid{margin-top:18px;gap:24px}
207
- .doc :is(h2,h3,h4) .anchor{display:none}
208
- }
209
- @media(max-width:520px){
210
- main{padding:60px 14px 48px}
211
- .doc pre{margin-left:-14px;margin-right:-14px;border-radius:0;border-left:0;border-right:0}
212
- .home-install{flex-wrap:wrap}
213
- }
214
- </style>
215
- </head>
216
- <body>
217
- <button class="nav-toggle" type="button" aria-label="Toggle navigation" aria-expanded="false">
218
- <span aria-hidden="true"></span><span aria-hidden="true"></span><span aria-hidden="true"></span>
219
- </button>
220
- <div class="shell">
221
- <aside class="sidebar">
222
- <div class="sidebar-head">
223
- <a class="brand" href="./" aria-label="oracle docs home">
224
- <span class="mark" aria-hidden="true"></span>
225
- <span><strong>oracle</strong><small>askoracle.sh</small></span>
226
- </a>
227
- <button class="theme-toggle" type="button" aria-label="Toggle dark mode" aria-pressed="false" data-theme-toggle>
228
- <svg class="theme-icon-moon" viewBox="0 0 20 20" aria-hidden="true"><path d="M14.6 12.1A6.5 6.5 0 0 1 7.4 2.7a6.5 6.5 0 1 0 7.2 9.4z" fill="currentColor"/></svg>
229
- <svg class="theme-icon-sun" viewBox="0 0 20 20" aria-hidden="true"><circle cx="10" cy="10" r="3.4" fill="currentColor"/><g stroke="currentColor" stroke-width="1.6" stroke-linecap="round"><line x1="10" y1="2" x2="10" y2="4"/><line x1="10" y1="16" x2="10" y2="18"/><line x1="2" y1="10" x2="4" y2="10"/><line x1="16" y1="10" x2="18" y2="10"/><line x1="4.2" y1="4.2" x2="5.6" y2="5.6"/><line x1="14.4" y1="14.4" x2="15.8" y2="15.8"/><line x1="4.2" y1="15.8" x2="5.6" y2="14.4"/><line x1="14.4" y1="5.6" x2="15.8" y2="4.2"/></g></svg>
230
- </button>
231
- </div>
232
- <label class="search"><span>Search</span><input id="doc-search" type="search" placeholder="browser, mcp, sessions"></label>
233
- <nav><section><h2>Start</h2><a class="nav-link" href="./">Overview</a><a class="nav-link" href="install.html">Install</a><a class="nav-link" href="quickstart.html">Quickstart</a><a class="nav-link" href="configuration.html">Local configuration (JSON5)</a></section><section><h2>Mythical Pro Agents</h2><a class="nav-link" href="mythical-pro-agents.html">Mythical Pro Agents</a><a class="nav-link" href="openai-endpoints.html">OpenAI-Compatible Endpoints</a><a class="nav-link" href="anthropic.html">Anthropic (Claude) Integration Plan</a><a class="nav-link" href="gemini.html">Gemini Integration</a><a class="nav-link" href="openrouter.html">OpenRouter</a><a class="nav-link" href="grok.html">Grok 4.1 (xAI) Support</a></section><section><h2>Browser Mode</h2><a class="nav-link" href="browser-mode.html">Browser Mode</a><a class="nav-link" href="chromium-forks.html">Chromium-based browsers (Chromium, Edge, Brave variants)</a><a class="nav-link" href="linux.html">Linux Notes</a><a class="nav-link" href="windows.html">Windows compatibility notes</a><a class="nav-link" href="windows-work.html">Windows Work</a><a class="nav-link" href="bridge.html">Bridge (Windows-hosted ChatGPT session → Linux clients)</a></section><section><h2>Agents &amp; MCP</h2><a class="nav-link" href="agents.html">Coding Agents</a><a class="nav-link" href="mcp.html">MCP Server</a></section><section><h2>Workflows</h2><a class="nav-link" href="sessions.html">Sessions</a><a class="nav-link" href="followup.html">Followups &amp; Lineage</a><a class="nav-link" href="multimodel.html">Multi-Model Execution</a></section><section><h2>Reference</h2><a class="nav-link" href="cli-reference.html">CLI Reference</a><a class="nav-link" href="spec.html">Spec</a><a class="nav-link" href="notifier.html">Session completion notifications</a><a class="nav-link" href="tui-debug.html">TUI navigation crash notes (2025-11-19)</a><a class="nav-link" href="manual-tests.html">Manual Test Suite (Browser Mode + Live API)</a><a class="nav-link" href="testing.html">Testing quickstart</a><a class="nav-link active" href="RELEASING.html">Release Checklist (npm + Homebrew)</a></section></nav>
234
- </aside>
235
- <main>
236
- <header class="hero">
237
- <div class="hero-text">
238
- <p class="eyebrow">Reference</p>
239
- <h1>Release Checklist (npm + Homebrew)</h1>
240
- </div>
241
- <div class="hero-meta">
242
- <a class="repo" href="https://github.com/steipete/oracle" rel="noopener">GitHub</a>
243
- <a class="edit" href="https://github.com/steipete/oracle/edit/main/docs/RELEASING.md" rel="noopener">Edit page</a>
244
- </div>
245
- </header>
246
- <div class="doc-grid">
247
- <article class="doc"><h1 id="release-checklist-npm-homebrew">Release Checklist (npm + Homebrew)</h1>
248
- <blockquote><p>For a guarded, phased flow, run <code>./scripts/release.sh &lt;phase&gt;</code> (gates | artifacts | publish | smoke | tag | github-release | all); it stops on the first error so you can resume after fixing issues.</p></blockquote>
249
- <ol>
250
- <li><strong>Version &amp; metadata</strong></li>
251
- </ol>
252
- <ul>
253
- <li>[ ] Update <code>package.json</code> version (e.g., <code>1.0.0</code>).</li>
254
- <li>[ ] Update any mirrored version strings (CLI banner/help, docs metadata) to match.</li>
255
- <li>[ ] Confirm package metadata (name, description, repository, keywords, license, <code>files</code>/<code>.npmignore</code>).</li>
256
- <li>[ ] If dependencies changed, run <code>pnpm install</code> so <code>pnpm-lock.yaml</code> is current.</li>
257
- <li>[ ] Source <code>~/.profile</code> so codesign/notary env vars are available before building the notifier.</li>
258
- </ul>
259
- <ol>
260
- <li><strong>Artifacts</strong></li>
261
- </ol>
262
- <ul>
263
- <li>[ ] Run <code>./scripts/release.sh artifacts</code> (builds <code>dist/</code>, packs npm, and generates checksums).</li>
264
- <li>[ ] Verify <code>bin</code> mapping in <code>package.json</code> points to <code>dist/bin/oracle-cli.js</code>.</li>
265
- </ul>
266
- <ul>
267
- <li>[ ] Keep the generated <code>.release-artifacts/oracle-&lt;version&gt;.tgz{,.sha1,.sha256}</code> for the GitHub release.</li>
268
- <li><code>.release-artifacts/</code> is gitignored; do <strong>not</strong> commit these files.</li>
269
- <li>Set <code>ARTIFACT_DIR</code> to override the artifact directory; use the same directory for <code>github-release</code>.</li>
270
- <li>[ ] Rebuild macOS notifier helper with signing + notarization:</li>
271
- <li><code>cd vendor/oracle-notifier &amp;&amp; ./build-notifier.sh</code> (requires <code>CODESIGN_ID</code> and <code>APP_STORE_CONNECT_*</code>).</li>
272
- <li>Signing inputs (same as Trimmy): <code>CODESIGN_ID=&quot;Developer ID Application: Peter Steinberger (Y5PE65HELJ)&quot;</code> plus notary env vars <code>APP_STORE_CONNECT_API_KEY_P8</code>, <code>APP_STORE_CONNECT_KEY_ID</code>, and <code>APP_STORE_CONNECT_ISSUER_ID</code>.</li>
273
- <li>Sparkle ed25519 private key lives at <code>/Users/steipete/Library/CloudStorage/Dropbox/Backup/Sparkle</code>; export <code>SPARKLE_PRIVATE_KEY_FILE</code> to that path whenever the build script needs to sign an appcast/enclosure.</li>
274
- <li>Verify tickets: <code>xcrun stapler validate vendor/oracle-notifier/OracleNotifier.app</code> and <code>spctl -a -t exec -vv vendor/oracle-notifier/OracleNotifier.app</code>.</li>
275
- </ul>
276
- <ol>
277
- <li><strong>Changelog &amp; docs</strong></li>
278
- </ol>
279
- <ul>
280
- <li>[ ] Update <code>CHANGELOG.md</code> (or release notes) with highlights.</li>
281
- <li>[ ] Keep changelog entries product-facing only; avoid adding release-status/meta lines (e.g., “Published to npm …”)—that belongs in the GitHub release body.</li>
282
- <li>[ ] Verify changelog structure: versions strictly descending, no duplicates or skipped numbers, single heading per version.</li>
283
- <li>[ ] Ensure README reflects current CLI options (globs, <code>--status</code>, heartbeat behavior).</li>
284
- <li>[ ] <strong>Release notes must exactly match the version’s changelog section</strong> (full Added/Changed/Fixed/Tests bullets, no omissions). After creating the GitHub release, compare the body to <code>CHANGELOG.md</code> and fix any mismatch.</li>
285
- </ul>
286
- <ol>
287
- <li><strong>Validation</strong></li>
288
- </ol>
289
- <ul>
290
- <li>[ ] <code>pnpm run check</code> (zero warnings allowed; fail on any lint/type warnings).</li>
291
- <li>[ ] <code>pnpm vitest</code></li>
292
- <li>[ ] <code>pnpm run lint</code></li>
293
- <li>[ ] Optional live smoke (with real <code>OPENAI_API_KEY</code>): <code>ORACLE_LIVE_TEST=1 pnpm vitest run tests/live/openai-live.test.ts</code></li>
294
- <li>[ ] MCP sanity check: with <code>config/mcporter.json</code> pointed at the local stdio server (<code>oracle-local</code>), run <code>mcporter list oracle-local --schema --config config/mcporter.json</code> after building (<code>pnpm build</code>) to ensure tools/resources are discoverable.</li>
295
- </ul>
296
- <ol>
297
- <li><strong>Publish (npm)</strong></li>
298
- </ol>
299
- <ul>
300
- <li>[ ] Ensure git status is clean; commit and push any pending changes.</li>
301
- <li>[ ] Avoid repeated browser auth: create a granular access token with <strong>write</strong> + <strong>Bypass 2FA</strong> at npmjs.com/settings/~/tokens, then export it (e.g., <code>export NPM_TOKEN=...</code> in <code>~/.profile</code>) and set <code>//registry.npmjs.org/:_authToken=${NPM_TOKEN}</code> in <code>~/.npmrc</code>.</li>
302
- <li>[ ] Use the <code>NPM_TOKEN</code> from <code>~/.profile</code> (our “NPM out token”). If <code>npm publish</code> opens browser auth, the token wasn’t loaded—rerun with <code>source ~/.profile</code>.</li>
303
- <li>[ ] Confirm auth: <code>npm whoami</code>.</li>
304
- <li>[ ] Decide tag before publish:</li>
305
- <li>If npm <code>latest</code> is ahead (e.g., <code>npm view @steipete/oracle version</code> shows a higher major), publish with <code>--tag legacy</code>.</li>
306
- <li>If this should become latest, publish with <code>--tag latest</code> (or publish then <code>npm dist-tag add @steipete/oracle@X.Y.Z latest</code>).</li>
307
- <li>[ ] <code>npm publish --access public --tag &lt;legacy|latest&gt;</code> (2FA OTP required even with token).</li>
308
- <li>[ ] If promoting later: <code>npm dist-tag add @steipete/oracle@X.Y.Z latest --otp &lt;code&gt;</code> (OTP required).</li>
309
- <li>[ ] <code>npm view @steipete/oracle version</code> (and optionally <code>npm view @steipete/oracle time</code>) to confirm the registry shows the new version.</li>
310
- <li>[ ] Verify positional prompt still works: <code>npx -y @steipete/oracle &quot;Test prompt&quot; --dry-run</code>.</li>
311
- </ul>
312
- <ol>
313
- <li><strong>Homebrew (tap)</strong></li>
314
- </ol>
315
- <ul>
316
- <li>[ ] The <code>Update Homebrew Tap</code> workflow preflights the tarball and both checksum assets after the GitHub release is published: it verifies their hashes and the public tarball URL before dispatching <code>steipete/homebrew-tap</code>.</li>
317
- <li>[ ] Missing assets or failed verification stop the job before dispatch. Run <code>./scripts/release.sh github-release</code>, then re-run <code>.github/workflows/update-homebrew-tap.yml</code> via <code>workflow_dispatch</code> with the release tag (<code>tag=vX.Y.Z</code>). For an older release, do not rebuild: download the published npm tarball (<code>npm view @steipete/oracle@X.Y.Z dist.tarball</code>), verify it against <code>dist.integrity</code>, place it in <code>ARTIFACT_DIR</code> as <code>oracle-X.Y.Z.tgz</code> with <code>.sha1</code>/<code>.sha256</code> files, and run the phase with <code>VERSION=X.Y.Z</code>.</li>
318
- <li>[ ] Confirm the tap workflow updated <code>Formula/oracle.rb</code> to the GitHub release asset and committed the SHA256.</li>
319
- <li>[ ] Verify install:</li>
320
- <li><code>brew uninstall oracle || true</code></li>
321
- <li><code>brew tap steipete/tap || true</code></li>
322
- <li><code>brew install steipete/tap/oracle</code></li>
323
- <li><code>oracle --version</code></li>
324
- <li><code>brew uninstall oracle</code></li>
325
- </ul>
326
- <ol>
327
- <li><strong>Post-publish</strong></li>
328
- </ol>
329
- <ul>
330
- <li>[ ] Run <code>./scripts/release.sh tag</code> so <code>vX.Y.Z</code> exists on origin (always tag each release).</li>
331
- <li>[ ] Run <code>./scripts/release.sh github-release</code>: create a draft with title <code>X.Y.Z</code> and the full version&#39;s changelog section (without its heading), upload the tarball and both checksums, verify the downloads, publish, and re-verify the public tarball URL. Publishing triggers the Homebrew tap workflow, which also waits for that URL to become available.</li>
332
- <li>Existing releases keep their notes; identical assets are skipped, and conflicting assets fail without overwriting.</li>
333
- <li>[ ] Confirm the GitHub release body exactly matches the <code>CHANGELOG.md</code> section for <code>X.Y.Z</code> (full bullet list). If not, update with <code>gh release edit vX.Y.Z --notes-file &lt;file&gt;</code>.</li>
334
- <li>[ ] Confirm npm shows the new version: <code>npm view @steipete/oracle version</code> and <code>npx -y @steipete/oracle@X.Y.Z --version</code>.</li>
335
- <li>[ ] Promote desired dist-tag (e.g., <code>npm dist-tag add @steipete/oracle@X.Y.Z latest</code>).</li>
336
- <li>[ ] From a clean temp directory (no package.json/node_modules), run <code>npx @steipete/oracle@X.Y.Z &quot;Smoke from empty dir&quot; --dry-run</code> to confirm the package installs/executes via npx.</li>
337
- <li>[ ] After verification, remove the generated tarball/checksum assets (<code>trash .release-artifacts</code>, or the overridden <code>ARTIFACT_DIR</code>).</li>
338
- <li>[ ] Announce / share release notes.</li>
339
- </ul><nav class="page-nav" aria-label="Pager"><a class="page-nav-prev" href="testing.html"><small>Previous</small><span>Testing quickstart</span></a></nav></article>
340
-
341
- </div>
342
- </main>
343
- </div>
344
- <script>
345
- const themeRoot=document.documentElement;
346
- function applyTheme(mode){themeRoot.dataset.theme=mode;document.querySelectorAll('[data-theme-toggle]').forEach(b=>b.setAttribute('aria-pressed',mode==='dark'?'true':'false'))}
347
- function storedTheme(){try{return localStorage.getItem('theme')}catch(e){return null}}
348
- function persistTheme(mode){try{localStorage.setItem('theme',mode)}catch(e){}}
349
- applyTheme(themeRoot.dataset.theme==='dark'?'dark':'light');
350
- document.querySelectorAll('[data-theme-toggle]').forEach(btn=>{btn.addEventListener('click',()=>{const next=themeRoot.dataset.theme==='dark'?'light':'dark';applyTheme(next);persistTheme(next)})});
351
- const systemDark=window.matchMedia&&matchMedia('(prefers-color-scheme: dark)');
352
- function onSystemChange(e){if(storedTheme())return;applyTheme(e.matches?'dark':'light')}
353
- if(systemDark){if(systemDark.addEventListener)systemDark.addEventListener('change',onSystemChange);else if(systemDark.addListener)systemDark.addListener(onSystemChange)}
354
- const sidebar=document.querySelector('.sidebar');
355
- const toggle=document.querySelector('.nav-toggle');
356
- const mobileNav=window.matchMedia('(max-width: 900px)');
357
- const sidebarFocusable='a[href],button,input,select,textarea,[tabindex]';
358
- function setSidebarFocusable(enabled){
359
- sidebar?.querySelectorAll(sidebarFocusable).forEach((el)=>{
360
- if(enabled){
361
- if(el.dataset.sidebarTabindex!==undefined){
362
- if(el.dataset.sidebarTabindex)el.setAttribute('tabindex',el.dataset.sidebarTabindex);
363
- else el.removeAttribute('tabindex');
364
- delete el.dataset.sidebarTabindex;
365
- }
366
- }else if(el.dataset.sidebarTabindex===undefined){
367
- el.dataset.sidebarTabindex=el.getAttribute('tabindex')??'';
368
- el.setAttribute('tabindex','-1');
369
- }
370
- });
371
- }
372
- function setSidebarOpen(open){
373
- if(!sidebar||!toggle)return;
374
- sidebar.classList.toggle('open',open);
375
- toggle.setAttribute('aria-expanded',open?'true':'false');
376
- if(mobileNav.matches){
377
- sidebar.inert=!open;
378
- if(open)sidebar.removeAttribute('aria-hidden');
379
- else sidebar.setAttribute('aria-hidden','true');
380
- setSidebarFocusable(open);
381
- }else{
382
- sidebar.inert=false;
383
- sidebar.removeAttribute('aria-hidden');
384
- setSidebarFocusable(true);
385
- }
386
- }
387
- setSidebarOpen(false);
388
- toggle?.addEventListener('click',()=>setSidebarOpen(!sidebar?.classList.contains('open')));
389
- document.addEventListener('click',(e)=>{if(!sidebar?.classList.contains('open'))return;if(sidebar.contains(e.target)||toggle?.contains(e.target))return;setSidebarOpen(false)});
390
- document.addEventListener('keydown',(e)=>{if(e.key==='Escape')setSidebarOpen(false)});
391
- const syncSidebarForViewport=()=>setSidebarOpen(sidebar?.classList.contains('open')??false);
392
- if(mobileNav.addEventListener)mobileNav.addEventListener('change',syncSidebarForViewport);
393
- else mobileNav.addListener?.(syncSidebarForViewport);
394
- const input=document.getElementById('doc-search');
395
- input?.addEventListener('input',()=>{const q=input.value.trim().toLowerCase();document.querySelectorAll('nav section').forEach(sec=>{let any=false;sec.querySelectorAll('.nav-link').forEach(a=>{const m=!q||a.textContent.toLowerCase().includes(q);a.style.display=m?'block':'none';if(m)any=true});sec.style.display=any?'block':'none'})});
396
- function attachCopy(target,getText){const btn=document.createElement('button');btn.type='button';btn.className='copy';btn.textContent='Copy';btn.addEventListener('click',async()=>{try{await navigator.clipboard.writeText(getText());btn.textContent='Copied';btn.classList.add('copied');setTimeout(()=>{btn.textContent='Copy';btn.classList.remove('copied')},1400)}catch{btn.textContent='Failed';setTimeout(()=>{btn.textContent='Copy'},1400)}});target.appendChild(btn)}
397
- document.querySelectorAll('.doc pre').forEach(pre=>attachCopy(pre,()=>pre.querySelector('code')?.textContent??''));
398
- document.querySelectorAll('.home-install').forEach(el=>attachCopy(el,()=>el.querySelector('code')?.textContent??''));
399
- const tocLinks=document.querySelectorAll('.toc a');
400
- if(tocLinks.length){const map=new Map();tocLinks.forEach(a=>{const id=a.getAttribute('href').slice(1);const el=document.getElementById(id);if(el)map.set(el,a)});const setActive=l=>{tocLinks.forEach(x=>x.classList.remove('active'));l.classList.add('active')};const obs=new IntersectionObserver(entries=>{const visible=entries.filter(e=>e.isIntersecting).sort((a,b)=>a.boundingClientRect.top-b.boundingClientRect.top);if(visible.length){const link=map.get(visible[0].target);if(link)setActive(link)}},{rootMargin:'-15% 0px -65% 0px',threshold:0});map.forEach((_,el)=>obs.observe(el))}
401
- </script>
402
- </body>
403
- </html>