24 Commits
Author SHA1 Message Date
JATMNandGitHub 1e56d4e7b2 feat(providers): add focused LLMTR hybrid gateway (#2150)
* feat: add LLMTR hybrid gateway

* feat: support LLMTR_API_KEY

* fix: allow LLMTR provider env files

* fix: protect LLMTR credential routing

* fix: protect LLMTR profile credentials

* fix: complete LLMTR env lifecycle

* fix: select LLMTR model before client setup

* fix: address LLMTR review findings

* fix: route LLMTR auxiliary models correctly

* fix: complete LLMTR credential boundaries

* fix: clear persisted LLMTR startup keys

* fix: normalize LLMTR generic credentials

* fix: scope LLMTR credential support

* fix: align LLMTR credential boundaries

* fix: close LLMTR credential boundaries

* fix: clear stale LLMTR auth state

* fix: clear persisted LLMTR credentials

* fix: complete LLMTR setup contracts

* fix: close LLMTR lifecycle gaps

* fix(providers): close LLMTR credential boundaries

* fix(providers): preserve saved LLMTR profile keys
2026-08-24 10:16:04 +08:00
6e3590303b feat(partners): add Concentrate and Exa to partner roster (#2141)
Adds Concentrate (concentrate.ai) and Exa (exa.ai) to the README
partners table and the web landing page, with light/dark logo variants
self-hosted under docs/assets/ and web/public/partners/.

Co-authored-by: OpenClaude <openclaude@gitlawb.com>
2026-08-19 14:13:09 +08:00
BogdanandGitHub 09eba26d30 feat(cost): support exact custom model pricing (#2131)
* feat(cost): support exact custom model pricing

* fix(cost): address custom pricing review feedback
2026-08-16 15:55:02 +08:00
575b407275 feat(partners): add ApiSmart, refresh Novita AI logo (#2121)
- Add ApiSmart (https://www.apismart.ai) to the README partners table
  and the web partner strip, with a dark-theme logo variant (near-black
  wordmark recolored to white, white matte removed).
- Replace the Novita AI PNG logo with the new SVG wordmark plus a
  generated dark variant, wired through the same prefers-color-scheme
  <picture> pattern (README) and logoDark field (web).

Co-authored-by: OpenClaude <openclaude@gitlawb.com>
2026-08-13 11:11:43 +08:00
JATMNandGitHub 7cae4089d6 feat(xai): add Grok 4.6/4.5 to catalog, xAI provider, and gateways (#2117)
* feat(xai): add Grok 4.6/4.5 and hybrid catalog discovery

xAI's current flagship is Grok 4.6; keep shared capability flags so gateways can reference the new models, and let /v1/models surface later Grok IDs without another catalog bump.

* fix(xai): authenticate hybrid discovery for OAuth and keep gateway aliases aligned

OAuth xAI sessions had no /v1/models credential, so hybrid refresh failed; also drop curated alias IDs from discovery and map grok-build-latest on Atlas/Hicap to Grok 4.5.

* fix(xai): align OAuth hybrid discovery cache with runtime metadata

OAuth-only xAI sessions hashed the access token into discovery writes, but
runtime limit lookups only used env credentials, so uncataloged Grok IDs
fell back to default windows. Mirror stored OAuth on cache reads and isolate
discovery tests from the shared config home.

* fix(xai): keep Grok 4.6 PR on catalog and hybrid discovery

Move OAuth /v1/models auth and cache-key alignment out of this branch so the catalog, xAI hybrid vendor, and gateway references stay reviewable on their own.

* fix(xai): read discovered model context length

* fix(xai): preserve OAuth discovery metadata

* fix(xai): tolerate malformed discovery models

* fix(discovery): harden credential cache partitions

* fix(xai): unify discovery OAuth cache handling

* fix(xai): preserve OAuth discovery cache identity

* fix(discovery): use native cache namespace hashing

* fix(xai): keep OAuth discovery nonblocking

* fix(discovery): use opaque cache fingerprints
2026-08-13 10:43:41 +08:00
JATMNandGitHub c40d663b70 fix(web): link release notes to GitHub (#2114)
* fix(web): link release notes to GitHub

* test(web): verify release link safety contract
2026-08-12 08:26:03 +08:00
JATMNandGitHub 5f8e7d101b Revert "fix(release): synchronize web changelog entries (#2088)" (#2113)
This reverts commit 7743cf280e.
2026-08-11 20:23:26 +08:00
JATMNandGitHub ff91642364 feat(integrations): add ApiSmart OpenAI-compatible gateway provider (#2109)
* feat(integrations): add ApiSmart OpenAI-compatible gateway provider

Add a hybrid-catalog ApiSmart gateway with dedicated APISMART_API_KEY/APISMART_MODEL
env wiring, route detection, profile persistence, and regression tests so the
provider works via --provider, env-only setup, and saved profiles.

* fix(apismart): protect dedicated credentials

* fix(apismart): enforce route credential boundaries

* fix(apismart): honor explicit competing route models

* fix(apismart): validate credentials and default profiles

* test(apismart): isolate env-only client tests

* fix(apismart): align routing and validation contracts

* fix(apismart): centralize route capability contracts

* Revert "fix(apismart): centralize route capability contracts"

This reverts commit f8cd975e68.

* fix(apismart): reject template credential placeholders at the shared root

Expand the shared credential usability helpers so dotenv sentinels like
null/undefined cannot win ApiSmart env-only precedence or get mirrored into
OPENAI_API_KEY, and restore focused ApiSmart docs after dropping the
shared routing centralization.

* fix(apismart): reject null base-URL and placeholder profile keys

Treat dotenv `null`/`undefined` OPENAI_BASE_URL sentinels as unset so
--provider apismart can apply defaults, and align profile/validation
credential checks with the shared placeholder contract.

* fix(apismart): match AIMLAPI env-only intent and proxy credential withholding

Use the OpenAI-compatible env-only gate so lingering CLAUDE_CODE_USE_OPENAI still keeps ApiSmart identity, retain route id on retargeted profiles, and withhold ambient credentials on non-canonical relaunches.

* fix(apismart): restore AIMLAPI credential and canonical URL parity

Backfill APISMART_API_KEY on relaunch and keyless canonical profiles, and gate credential forwarding on an exact /v1 inference URL so dedicatedCredentialsOnly auth and ambient keys stay aligned with AIMLAPI.

* fix: simplify apismart gateway integration

* fix: reject credential placeholders consistently

* test: remove obsolete apismart exception coverage

* test: remove stale apismart model fixture

* fix(apismart): restore dedicated provider contract

* fix(apismart): enforce credential boundaries

* fix(apismart): clear inherited auth headers

* test(apismart): strengthen credential boundaries
2026-08-11 19:08:38 +08:00
JATMNandGitHub 7743cf280e fix(release): synchronize web changelog entries (#2088)
* fix(release): sync web changelog entries from release please

* fix(release): provide sync push credentials

* fix(release): gate and finalize web release sync

* fix(release): make web release sync recoverable

* fix(release): target release PR commands explicitly

* fix(release): honor manifest release configuration

* fix(release): recover failed web sync retries

* ci(release): run full sync preflight

* fix(release): validate synchronized PR head

* fix(release): validate bot sync in release job

* fix(release): harden bot-owned web sync

* fix(release): validate exact bot PR head

* fix(release): isolate and bind PR synchronization

* fix(release): isolate validation from write credentials

* fix(release): reject non-regular generated inputs

* fix(release): require a valid forward version bump

* fix(release): scope sync artifacts to run attempts

* fix(release): reuse validated artifacts across retries

* fix(release): resume readiness after a completed push

* fix(release): bind retries to the validated commit

* fix(release): address synchronization review findings

* fix(release): support CRLF changelog recovery

* fix(release): keep validation transitions fail-closed

* fix(release): restore scoped web sync and marker ownership

Cut the multi-job finalize state machine back to a single draft-until-push
sync path, and fix consecutive releases leaving stacked automation markers
by stripping leftover draft ownership when inserting the next version.

* fix(release): keep web sync from blocking npm publish

Move pending Release Please web sync into its own job so a sync failure cannot skip install-verify, npm, or docker after a release tag is already created.

* fix(release): close web-sync trust and policy gaps

Remove hand-curation escape hatches, split read-only validation from
write-only push, discover bot PRs by branch identity, and run the full
local gate suite before marking the release PR ready.

* fix(release): validate gates against synchronized commit

Commit the synced releases.ts in the read-only validate job before
typecheck, security scan, and whitespace checks so those gates inspect
the content that will be marked ready, not the pre-sync HEAD.

* fix(release): harden web-sync trust boundary and draft gating

Run sync from trusted main with only changelog/manifest overlaid from
the bot PR, re-draft after release-please, serialize sync without
canceling in-flight pushes, and require an explicit sync base.

* fix(release): restore overlaid inputs before validate cleanliness gate

Fetching changelog/manifest from the bot PR dirtied tracked files on the
trusted main checkout and made the final git-diff gate fail on every
pending release. Restore those overlays after sync and fetch origin/main
for the security/whitespace checks.

* fix(release): reuse validated sync artifacts on retry

* fix(release): validate release sync inputs and retries

* fix(release): recover web sync state transitions

* fix(release): protect generated release ownership

* fix(release): repair web sync recovery gates

* fix(release): bind sync artifacts to validated base

* fix(release): verify synchronized file mode

* fix(release): paginate bot PR discovery
2026-08-11 18:37:49 +08:00
மனோஜ்குமார் பழனிச்சாமிandGitHub 95eeb0bde3 feat(cli): add --yolo alias for --dangerously-skip-permissions (#2097)
Register the alias on the main command and the ssh stub. Recognize it in
the cc:// and ssh raw-argv scans, and in both skills pre-parse boolean sets
(leading and trailing), so  and
 route correctly. Update the web flags docs.

Includes source-scan + help-text tests proving the alias is wired through.
The SSH/argv refactor remains on the existing feat/yolo-flag branch for a
separate follow-up PR.
2026-08-07 09:47:47 +08:00
JATMNandGitHub 63fda83d55 fix(web): add v0.27.0 changelog entry and clarify release-data ownership (#2075)
* fix(web): add 0.27 release entry

* test(web): cover 0.27 release entry

* fix(web): clarify 0.27 permission-timeout highlight

* docs: ban drive-by edits to web/src/data/releases.ts

Tell agents and contributors that the curated changelog is owned by
the release/web process, and stop verify-dist from instructing unrelated
PRs to patch it when npm publishes ahead of the site.

* test(web): locate curated release by version

* test(web): enforce newest-first release order
2026-08-03 10:54:52 +08:00
56a920196d feat(web): replace favicon/logo with Ember Block O brand mark (#2065)
The site icon was still the 2026-06 terminal-face + git-fork circuit
mark, predating the ember identity the product now leads with (the
ANSI-Shadow startup logo and the orange pixel wordmark in the README).

Replace it with the Ember Block O: the startup screen's figlet "O"
letterform re-plotted as pure SVG rects — five ember gradient bands
(#ffb15f → #be5008, the exact stops from StartupScreen.palettes.ts)
with the wordmark's thin offset outline shadow, on a dark rounded tile.
Reads as a crisp orange O at 16px and matches CLI, README, and site.

- openclaude-logo.svg: new mark (same filename, Head.astro untouched)
- openclaude.png: 512px transparent-corner render (PNG favicon and the
  nav/footer images, which already reference this path)
- og/{default,docs,commands,buddy}.png: all four social cards
  regenerated with the new mark; layout, copy, and grid unchanged

Co-authored-by: OpenClaude <openclaude@gitlawb.com>
2026-07-29 20:45:24 +08:00
c2030bbb2b fix(web): make web/ build standalone — stop importing the repo-root p… (#2061)
* fix(web): make web/ build standalone — stop importing the repo-root package.json

vercel --prod deploys only the web/ directory, so site.ts importing
../../../package.json (and verify-dist.ts reading it) broke every Vercel
build with ts(2307) while local builds passed.

- SITE.version now derives from latestVersion, the newest entry in
  src/data/releases.ts — committed data inside web/, so builds are
  deterministic and need nothing outside the directory
- verify-dist gains a best-effort npm freshness guard: fails the build
  only when registry.npmjs.org reports a newer @gitlawb/openclaude than
  releases.ts; unreachable registry or malformed responses skip the
  check, and site-ahead-of-npm is allowed for release PRs
- verify-dist.test.ts covers the guard via injected fetch (no network)

Co-Authored-By: OpenClaude <openclaude@gitlawb.com>

* fix(web): reject leading-zero semver from the npm registry

Number() would normalize a malformed '01.2.3' to 1.2.3; require strict
semver components so malformed registry values skip the freshness check
instead of being silently coerced.

Co-Authored-By: OpenClaude <openclaude@gitlawb.com>

---------

Co-authored-by: OpenClaude <openclaude@gitlawb.com>
2026-07-29 13:12:35 +08:00
0f76b5490b feat(web): v0.26 refresh — buddy page, changelog, partners, provider … (#2060)
* feat(web): v0.26 refresh — buddy page, changelog, partners, provider catalog

- Single-source the site version from the root package.json (never stale again)
- New /buddy/ page: all 7 hero sprites rendered as animated SVGs generated
  from src/buddy/pixelSprites.ts, attack descriptions, commands, hatch lore,
  plus a dedicated 1200x630 OG image composed from the real sprites
- New /changelog/ page: curated release highlights 0.19 -> 0.26 from a typed
  releases.ts data file
- Landing: buddy teaser section, partners strip (GitLawb, Bankr, Atomic Chat,
  Xiaomi MiMo, Atlas Cloud, AI/ML API, Novita AI) with self-hosted logos,
  community links, refreshed provider strip, node >= 22 fix
- Providers docs rebuilt as grouped catalog (39 providers: subscriptions,
  gateways, vendors, local, custom) incl. xAI OAuth, AI/ML API, Cloudflare
  Workers AI, NVIDIA NIM, Kimi K3, GPT-5.6, Opengateway free models
- Data refresh vs v0.26.0 source: 16 new slash commands, pdf skill, new CLI
  flags + 10 subcommands, modelLimits/providerFallbackChain/agentRouting
  settings, corrected env vars (GEMINI_API_KEY, OPENGATEWAY_API_KEY, ...)
- Nav/footer/docs sidebar link the new pages; JSON-LD breadcrumbs on both

Co-Authored-By: OpenClaude <openclaude@gitlawb.com>

* fix(web): address CodeRabbit review — flag description + dist verification

- Correct --disable-slash-commands description: the flag empties the entire
  slash-command list (REPL.tsx filters all commands), not just skills; the
  upstream help string "Disable all skills" is the misleading one
- Add scripts/verify-dist.ts, wired into `bun run build` (so the existing CI
  web job runs it): asserts SITE.version matches the root package.json in the
  rendered pages, nav exposes /buddy/ and /changelog/, every release renders
  with its GitHub URL, every hero renders with its sprite asset, partner and
  community links render on the landing page, and the sitemap covers the new
  routes

Co-Authored-By: OpenClaude <openclaude@gitlawb.com>

* fix(web): harden verify-dist per review — empty-page guard, rendered-nav check, tests

- page() now records a failure for a present-but-empty file, so '' is only
  ever returned alongside a recorded failure and skipped assertions can no
  longer mask a blank page
- assert the rendered docs sidebar (dist/docs/) links every docsNav route,
  not just the source data array and the landing nav
- extract pure verifyDist(dist) and add 9 fixture-based bun tests covering
  missing/empty pages, lost sidebar links, missing sprites, stale partner
  links, missing release URLs, and sitemap regressions; discovered by the
  root `bun test` run in CI, no workflow changes needed

Co-Authored-By: OpenClaude <openclaude@gitlawb.com>

* test(web): derive the missing-sprite fixture from heroes data

Hard-coding robinhood.svg would make the test throw during fixture mutation
if that hero were renamed, instead of exercising verifyDist().

Co-Authored-By: OpenClaude <openclaude@gitlawb.com>

---------

Co-authored-by: OpenClaude <openclaude@gitlawb.com>
2026-07-29 12:32:47 +08:00
a5b277971d feat(settings): add settings-based subscription override and agy terminal support (#1731)
* feat(settings): add settings-based subscription override and agy terminal support

* feat(provider): rebrand Gemini wizard setup steps to Google AI / Gemini

* fix(settings): restrict subscription override to trusted sources

Addresses jatmn's CodeRabbit review on #1731.

P1 — untrusted settings sources could spoof subscriber state:
  Reads subscriptionType only from policy/flag/user/local settings,
  excluding project and repository settings which can be checked into
  shared repos. Adds getTrustedSubscriptionType() helper used by both
  isClaudeAISubscriber() and getSubscriptionType().

P2 — subscriptionType: "free" did not short-circuit OAuth-detected
  subscriber state. With a valid Claude AI OAuth token and
  subscriptionType: "free" in settings, isClaudeAISubscriber() still
  returned true. Now "free" is authoritative and returns false.

P3 — test isolation: added afterEach(mock.restore()) to auth.test.ts
  so Bun's module mocks cannot leak into subsequent tests.

Also splits the antigravity askpass test into focused cases for
"agy" and "antigravity" substrings.

* fix(settings): restrict subscriptionType override to user settings and return false early for free

* fix(auth): clean up unused import and return type matching in tests

* fix(provider): align Gemini chooser copy with the wizard's actual auth methods

Addresses jatmn's review on #1731. The /provider chooser advertised "Google AI /
Gemini Subscription" and "Use your Google AI Premium plan, …", but the Gemini
setup wizard only offers three auth methods — API key, access token, and local
ADC — with no subscription/Premium sign-in flow. Drop the "Subscription" label
and "Google AI Premium plan" framing so the chooser matches the wizard (and the
"Google AI / Gemini" wording used elsewhere in the file). No OAuth/subscription
sign-in is planned: using Google AI/Gemini subscriptions via third-party tools
violates Google's Terms of Service.

* fix(pr1731): resolve review follow-ups

* fix(pr1731): close review follow-ups

* fix(pr1731): close antigravity and gemini follow-ups

---------

Co-authored-by: jatmn <the@jat.mn>
2026-07-07 22:02:36 +08:00
e2bbb0295a feat: smart auto-routing (per-turn simple-vs-strong model selection) (#1734)
* feat(smart-routing): add smartRouting settings schema and reader

* feat(smart-routing): resolve role keys to a SmartRoutingConfig

* feat(smart-routing): wire per-user-turn routing into the query loop

Classify once per user turn (transition===undefined), pin the decision in a
loop-local, and apply the model-only route before the blocking-limit math.
Enforce the org allowlist by calling isModelAllowed directly (coerce disallowed
to strong; disable for the session if strong is also disallowed). Strip thinking
history on a model change only under the provider gate (preserve-reasoning
providers are left untouched). Export stripThinkingBlocksIfProviderAllows.

* feat(smart-routing): add routed-error fallback to the strong model

A simple-routed turn whose model call hits a retryable error retries once on
the strong model, reusing the existing attemptWithFallback retry loop. Aborts
and 4xx client errors propagate. Adds a session routing tally (simple/strong
counts and simple->strong escalations) for the observability surface.

* feat(smart-routing): add /smartroute command and env defaults

/smartroute shows status and sets/toggles the simple and strong roles from
agentModels keys, warning when the simple model is not first-party-cheaper than
the strong one. OPENCLAUDE_SMART_ROUTING(_SIMPLE/_STRONG) provide startup
defaults; an explicit settings block overrides env.

* feat(smart-routing): show routing summary in /cost

Appends a session routing summary (turns simple/strong, simple->strong
escalations) to /cost, with an estimated-savings line gated on first-party
pricing and annotated unavailable for unknown third-party pricing. Per-turn
cost is already attributed to the routed model via the existing per-model
breakdown.

* fix(smart-routing): re-pin to strong after a routed-error fallback

Without this, a turn's later continuation passes re-applied the pinned simple
model after a fallback, re-triggering the same failure each pass. Re-pinning to
strong keeps the rest of the turn on the recovered model.

* fix(review): provider-swap guard, tally reset, notice-storm, env docs

- Add the KTD6 provider-swap guard: drop the per-turn routing pin when a
  mid-turn provider-fallback swap changes the active provider, so the old
  provider's model id is not replayed at the new endpoint (adversarial P1).
- Reset the routing tally in resetCostState() so /cost does not show stale
  cross-session counts.
- Don't emit the disabled-for-session notice on every turn when no sessionId
  is available (suppress instead of storm).
- Document OPENCLAUDE_SMART_ROUTING* in the openaiShim env-var header.
- Add tests: provider-swap-safe pin, undefined-session silence, /smartroute
  strong arm and no-value guard.

* docs(smart-routing): document /smartroute, settings, and env vars

Register /smartroute in the web command catalog, add the smartRouting setting
and OPENCLAUDE_SMART_ROUTING* env vars to the configuration reference, add a
docs/smart-routing.md usage guide, and link it from the README.

* fix(review): clear tally on /login, extract+test swap predicate, cap disabled set

- /login used the raw bootstrap resetCostState, leaking the routing tally
  across an account switch; switch it to the cost-tracker wrapper.
- Extract the provider-swap drop check as a pure, tested
  shouldDropPinForProviderSwap() and use it in the query loop.
- Cap the disabledSessions set so a long-lived host can't grow it unbounded.
- Document the 404/429 retry-by-design rationale; add tests for it.
- Clarify the routedFallbackUsed per-turn scope and the apply-after-guard
  comment; document cross-provider role rejection and the re-enable path.

* test(smart-routing): make allowlist tests robust to cross-file module mocks

The decideTurnModel allowlist tests spied the global settings singleton, which
let another file's leaked mock.module of modelAllowlist (agent.test.ts) flip
isModelAllowed out from under them in the full suite. Spy isModelAllowed
directly and restore it in afterEach so the tests are deterministic regardless
of suite ordering.

* fix(smart-routing): address CodeRabbit review and green CI

- index.test.ts: pin the allowlist in the three happy-path decideTurnModel
  tests so they no longer inherit a leaked cross-file isModelAllowed mock
  (the CI test failure)
- smartroute/index.test.ts: narrow the LocalCommandResult union via an
  expectText helper instead of reading .value off the union (the CI
  typecheck failure)
- conversationRecovery.ts: route deserialize's thinking-strip gate through
  stripThinkingBlocksIfProviderAllows, removing the duplicated provider
  detection
- conversationRecovery.test.ts: replace the two as-any fixtures with a
  shared typed factory

* fix(smart-routing): scope cost claims to first-party reference pricing

Smart routing's savings estimate and "simple isn't cheaper" warning were
derived from the static first-party MODEL_COSTS table via getKnownInputCost,
with no knowledge of the active provider, gateway, or account pricing. For a
multi-provider user whose model ids happen to exist in that table but bill
differently, the /cost summary and /smartroute warning stated a savings figure
as if it reflected what they are actually charged.

Narrow the copy instead of inventing provider-aware pricing the code cannot
verify: the /cost line, the /smartroute warning, and docs/smart-routing.md now
label the numbers as first-party reference pricing and note the active provider
may bill differently. Tests assert the qualifier on every reworded branch so it
cannot silently regress. No routing logic changed.

* fix(smart-routing): clarify simple role wording

* Fix smart routing review findings

* fix(smart-routing): honor env roles and non-text turns

* test(smart-routing): cover non-text skip path

---------

Co-authored-by: jatmn <the@jat.mn>
2026-07-07 10:48:52 +08:00
77c0a0d780 feat(ux): honest feedback pass — visible retries, statusline truncation marker, hint grace period (#1862)
* feat(ux): honest feedback pass — visible retries, statusline truncation marker, hint grace period

Three fixes with one principle: never look frozen, never silently hide state.

- SystemAPIErrorMessage: retries were fully hidden until attempt 4, so
  transient rate limits / overloads were indistinguishable from a hang.
  Attempts 1-3 now render a compact dim line ("Rate limited — retrying
  in 4s… (attempt 2/10)") with a live countdown; the full error block
  is unchanged at attempt >= 4. The transcript already keeps only the
  last api_error message and hides it on the next non-error message,
  so early visibility adds no stacking. New briefAPIErrorReason()
  classifies 429/529/5xx/connection failures, including the
  OpenAI-compat shim's plain-text transport errors that carry no cause
  chain. Component rewritten from react-compiler output to plain React.

- BuiltinStatusLine: fitSegments dropped rate-limit -> cost -> context
  silently on narrow terminals. Segments now degrade to short forms
  first (ctx 37% -> 37%, $1.23 -> $1), and anything still dropped is
  marked with a trailing dim "…" so hidden data is visible as hidden.
  The marker is best-effort: at extreme widths the bare model name
  beats showing nothing.

- PromptInputFooter: "? for shortcuts" was suppressed whenever a status
  line rendered — the default state since the builtin statusline
  shipped, killing the hint's discoverability path entirely. New users
  (numStartups <= 10) keep the hint alongside the status line;
  established users get the quieter footer.

- docs: BASH_MAX_OUTPUT_LENGTH env var documented on the website env
  reference (default 30000, cap 150000).

Verified live in the TUI (tmux + mock OpenAI endpoint): compact retry
line from attempt 1 against a dead endpoint, full block at attempt 4,
Esc interrupts cleanly; statusline at 100/32/24 cols shows full /
degraded / "test-model · 2% · …"; hint present at numStartups=2,
suppressed at 50.

Co-Authored-By: OpenClaude <openclaude@gitlawb.com>

* fix(review): address CodeRabbit feedback — custom statusline yields immediately, timeout test, docs wording

- shouldSuppressShortcutsHint: a custom status line is explicit user
  configuration, so it now always wins over the discoverability grace
  period; only the builtin status line grants new users the hint.
  Test added to lock the semantics.
- Test the ETIMEDOUT -> "Request timed out" branch. Note: CodeRabbit's
  suggested test shape (plain object with a cause) would not exercise
  the branch — extractConnectionErrorDetails only walks Error
  instances — so the error itself carries the code.
- Docs: soften "full output saved" to reflect the persisted-file cap.

Co-Authored-By: OpenClaude <openclaude@gitlawb.com>

---------

Co-authored-by: OpenClaude <openclaude@gitlawb.com>
2026-07-05 19:31:14 +08:00
BogdanandGitHub 5b1db554fd feat(lsp): expose captured diagnostics (#1813) 2026-07-02 08:12:36 +08:00
BogdanandGitHub 8023356841 feat(session): harden fork-session branching (#1801)
* feat(session): harden fork-session branching

Add explicit fork-session branching metadata, preserve fork-owned transcript state, and seed retained content replacement records for forked resumes.

Document --fork-session behavior and cover forked resume transcript/materialization behavior with focused tests.

* fix(session): respect print persistence for fork seeding
2026-06-28 06:17:29 +08:00
2aad6fc93e feat(config): add OPENCLAUDE_CONFIG_DIR override (#1683)
* feat(config): add OPENCLAUDE_CONFIG_DIR env var as preferred alias for CLAUDE_CONFIG_DIR (#454)

The legacy CLAUDE_CONFIG_DIR name was the only way to point openclaude
at a non-default config home, which leaked Anthropic branding for a
fork that has otherwise rebranded to OpenClaude. Add OPENCLAUDE_CONFIG_DIR
as the preferred name. CLAUDE_CONFIG_DIR continues to work for
backward compatibility; when both are set with different values,
OPENCLAUDE_CONFIG_DIR wins and a one-time warning is logged.

- src/utils/envUtils.ts: introduce resolveConfigDirEnv() that picks
  OPENCLAUDE_CONFIG_DIR over CLAUDE_CONFIG_DIR and emits a conflict
  warning. Memoize cache key now tracks both env vars so changing
  either invalidates the cached result.
- src/utils/env.ts: getGlobalClaudeFile() previously read
  CLAUDE_CONFIG_DIR directly, missing the new alias. Route through
  resolveConfigDirEnv() so the global config file path follows the
  same precedence.
- src/utils/secureStorage/macOsKeychainHelpers.ts: the "is default
  dir" check used by keychain service-name scoping now considers
  both env vars.
- src/utils/swarm/spawnUtils.ts: forward OPENCLAUDE_CONFIG_DIR to
  teammate processes alongside the legacy var.
- src/utils/openclaudePaths.test.ts: +6 unit tests covering the new
  alias, fallthrough, conflict warning, and resolveConfigDirEnv()
  in isolation.
- .env.example: document both env vars and the precedence rule.

Verified locally on Linux: with only OPENCLAUDE_CONFIG_DIR set, with
only CLAUDE_CONFIG_DIR set (legacy still works), with both set
matching (silent), with both set conflicting (warn once + OPENCLAUDE
wins), with neither set (default ~/.openclaude). Memo cache
invalidates across 4 sequential env transitions. Built dist/cli.mjs
honors the new var and emits the conflict warning to the user.

* Fix config-dir warning and docs review findings

Only mark the config-dir conflict warning as emitted when a warning callback actually receives it, add coverage for warn-once and silent callers, and update web configuration docs for OPENCLAUDE_CONFIG_DIR precedence.

# Conflicts:
#	web/src/data/configuration.ts

* Align configuration docs with openclaude paths

Update the configuration page settings-file table to point default users at .openclaude settings and keybindings paths, matching the new config home behavior.

* Align keybindings docs with openclaude config home

Update the keybindings page, keybindings docs data, and skill index to point default users at ~/.openclaude/keybindings.json.

* Align skill and hook labels with openclaude paths

Update bundled config/keybindings skill prompts, public skills docs, hook/trust labels, and the user memory selector to use the active OpenClaude config home paths.

# Conflicts:
#	src/components/TrustDialog/utils.ts
#	src/components/hooks/SelectEventMode.tsx
#	src/skills/bundled/updateConfig.ts
#	src/utils/hooks/hooksSettings.ts

* Resolve config-home paths dynamically in skill prompts

Use runtime settings/keybindings path helpers for bundled skill prompts and the restricted-hooks banner so custom OPENCLAUDE_CONFIG_DIR values are reflected in user-facing guidance.

* Update active command prompts for openclaude paths

Point statusline, setup/onboarding prompts, plugin messages, and the external user-memory warning at the active OpenClaude settings and memory paths.

# Conflicts:
#	src/commands/auto-fix.ts
#	src/commands/onboard-github/onboard-github.tsx
#	src/commands/plugin/ManagePlugins.tsx
#	src/commands/statusline.tsx

* Fix remaining config path review findings

* Cover dynamic config paths in UI and storage tests

* Fix config path smoke failures after rebase

* Fix remaining config path review findings

---------

Co-authored-by: gnanam1990 <gnanasekaran.sekareee@gmail.com>
2026-06-18 08:57:22 +08:00
BogdanandGitHub 544b857876 fix(settings): correct stale settings path references (#1666)
* fix(settings): correct OpenClaude settings paths

* fix(settings): address review path clarity

* fix(sandbox): protect OpenClaude settings in changed cwd
2026-06-17 11:44:03 +08:00
d08593de92 feat(web): rebuild landing as Astro static site with gitlawb theme and full docs (#1606)
* feat(web): rebuild landing as Astro static site with gitlawb theme and full docs

Replaces the Vite+React SPA in web/ with a fully static Astro 6 site:

- gitlawb-aligned design system: dark-default monochrome surface tokens,
  Geist Mono, hairline grids, [light]/[dark] toggle — keeping the orange
  #ff7a1a openclaude accent (#e85d00 in light mode for AA contrast)
- 9-page docs section: installation, quickstart, providers, slash
  commands (all 69 user-facing commands with argument hints), CLI
  reference (every non-hidden flag), configuration, keybindings, skills —
  rendered from typed data files seeded from the CLI source
- SEO: per-page canonicals/OG/Twitter, JSON-LD (SoftwareApplication,
  TechArticle, BreadcrumbList), @astrojs/sitemap, robots.txt, and
  generated 1200x630 OG cards, all on https://openclaude.gitlawb.com
- zero framework JS: theme toggle, copy buttons, mobile nav, and TOC
  highlighting are small vanilla scripts
- CI-compatible: same typecheck/build script names, bun.lock regenerated

Co-Authored-By: OpenClaude <openclaude@gitlawb.com>

* feat(web): redesign logo as gitlawb-aligned circuit mark

White terminal face (hollow node eyes, >_ prompt mouth) on a black
square with an orange git-fork trace descending to two commit nodes —
same stroke language as the gitlawb mark. Adds the SVG source as the
favicon and regenerates all three OG cards with the new logo.

Co-Authored-By: OpenClaude <openclaude@gitlawb.com>

* fix(web): address review feedback on copy button a11y and css lint

- CopyCommand: generic aria-label (component is reusable, not
  install-specific) and a visually-hidden role="status" live region so
  screen readers announce the copied state
- global.css: lowercase text-rendering keyword, blank line before
  color-scheme, kebab-case fade-up keyframe name

Co-Authored-By: OpenClaude <openclaude@gitlawb.com>

---------

Co-authored-by: OpenClaude <openclaude@gitlawb.com>
2026-06-12 23:54:24 +08:00
chioarubandGitHub f3d41c6161 fix(release): verify npm latest tag and document @latest install (#1378)
* fix(release): verify npm latest tag and document @latest install

* fix(auto-updater): use @latest for global installs
2026-06-01 06:08:17 +08:00
4eb486ef83 Feat/web landing refresh (#958)
* feat(web): openclaude landing — runs anywhere, uses anything

A new marketing site for openclaude under web/, plus the minimal root
infrastructure to build, ignore, and gate it without affecting the
published npm package.

Landing page (web/)
- Vite + React 19 with monospace gitlawb typography (sf mono / fira code).
- Hero: pill, two-line wordmark "runs anywhere. / uses anything.",
  copy-to-clipboard install command, github cta.
- Six feature rows in hermes-style "title — sentence" format on hairline
  dividers (any model, real tools, profiles per repo, streaming,
  gateway routing, editor + server modes).
- Install block: same copyable command + three numbered steps.
- One-line footer with brand, version, gitlawb link, and license.
- Light theme is the default with a no-flash bootstrap script and a
  ☀ / ☾ toggle persisted to localStorage.
- New orange terminal-face logo at 36px in the nav.
- Body wash: dual orange radial gradients for warmth on both themes.

Root infra
- web/ excluded from npm publish via .npmignore (belt-and-suspenders
  alongside the existing files whitelist).
- web/ excluded from docker context (.dockerignore).
- web:dev / web:build / web:preview / web:typecheck scripts in
  package.json that delegate via --cwd web (no root deps added).
- web typecheck + build added to the pr-checks workflow.
- web/dist/ and web/*.tsbuildinfo ignored.

Co-Authored-By: OpenClaude <openclaude@gitlawb.com>

* added vercel in .gitignore

---------

Co-authored-by: OpenClaude <openclaude@gitlawb.com>
2026-04-30 18:22:01 +08:00