Skip to content

refactor(plugin/{codex,claude-code}): extract installer wrapper to checked-in file#2026

Merged
ZaynJarvis merged 4 commits into
volcengine:mainfrom
t0saki:refactor/plugin-wrappers-rc
May 13, 2026
Merged

refactor(plugin/{codex,claude-code}): extract installer wrapper to checked-in file#2026
ZaynJarvis merged 4 commits into
volcengine:mainfrom
t0saki:refactor/plugin-wrappers-rc

Conversation

@t0saki
Copy link
Copy Markdown
Collaborator

@t0saki t0saki commented May 13, 2026

Summary

Refactor the shell-rc wrappers shipped by both the claude-code and codex memory plugin installers. Same shape applied to both plugins:

  • Move the wrapper function body out of the installer's heredoc / inline-rc-block, into a checked-in standalone file at examples/<plugin>/setup-helper/wrapper.sh.
  • The user's shell rc gets a single one-line source hook pointing directly at the wrapper file in the cloned plugin checkout — no $HOME-copy step.

Before / after

Before, installers had ~16–60 lines of shell function body inlined in the user's ~/.zshrc / ~/.bashrc, written via read -r -d '' BODY <<'WRAPPER' heredoc inside install.sh, with awk strip-and-append on every upgrade. Wrapper diffs showed up as heredoc-content changes inside the installer.

After, in both plugins:

  • setup-helper/wrapper.sh is a real, syntax-highlighted, diffable source file.
  • User's rc OV-plugin block: ~16–60 lines → 3 lines (# >>> marker, [ -f ... ] && . "...", # <<< marker).
  • No copy step. Updates ride for free on the installer's existing git fetch + reset --hard.
  • Installer size: codex install.sh ~420 → ~340 lines; claude install.sh shed ~16 lines too.
  • The marker-replacement logic only triggers the legacy-cleanup pass once — when upgrading from a pre-split installer that inlined the full wrapper.
  • Footgun gone: the previous "if END marker is missing the awk strip drops everything from BEGIN marker to EOF" edge case can't happen anymore — the marker block content is now a stable one-liner that doesn't need to be rewritten on every install.

Why combined

Same shape, same pattern, identical motivation — easier to review as one PR than two. Originally split into #2024 (claude) and #2025 (codex); folding them into a single PR here. Both predecessor PRs are being closed in favor of this one.

Behavior preserved

Wrapper bodies are byte-for-byte the same as what shipped before — same ovcli.conf parsing, same env injection, same identity headers. Only where the wrapper code lives changes.

For codex specifically (the more involved wrapper): the .mcp.json cache rewriting (URL + bearer_token_env_var sync) and the empty-api-key handling — both already in main via #2023 — are preserved verbatim, just sitting in wrapper.sh instead of being embedded in install.sh.

Test plan

  • bash -n / zsh -n pass on all four files (two install.sh, two wrapper.sh)
  • Running each installer over a previous-version install (with the inline wrapper block) strips the legacy block and replaces it with the 3-line source hook
  • source ~/.zshrc && type claude and type codex both show their respective wrappers loaded from the standalone files
  • Wrapper behavior unchanged:
    • claude invocation still injects OPENVIKING_URL / OPENVIKING_API_KEY from ovcli.conf
    • codex invocation still re-renders cache .mcp.json url + bearer_token_env_var and skips empty env vars
  • Uninstall: rm ~/.openviking/openviking-repo no-ops both source hooks (no error, functions just aren't defined)

Closes #2024.
Closes #2025.

t0saki added 4 commits May 13, 2026 21:50
The installer-emitted codex() wrapper had grown to ~60 lines of shell
function body inlined as a marker-delimited block inside the user's
~/.zshrc / ~/.bashrc. Every upgrade required the awk-strip-and-append
dance, which had a known edge case (rc with begin-marker but no
end-marker) we'd already had to harden against, and the inline noise
was hostile to anyone reading their own rc.

This commit switches to the standard pyenv / nvm / fnm pattern:

- Wrapper body lives in its own file at ~/.openviking/codex-plugin.rc.sh
  (path overridable via OPENVIKING_CODEX_WRAPPER_RC). Full overwrite on
  every install — no marker logic inside the wrapper file itself.

- The user's shell rc gets a single one-line source hook, still wrapped
  in marker comments for cleanup-on-uninstall:

    # >>> openviking-codex-plugin >>>
    [ -f "$HOME/.openviking/codex-plugin.rc.sh" ] && . "..."
    # <<< openviking-codex-plugin <<<

  Since the content of this block never changes across installs, the
  marker-replacement logic only triggers the legacy-cleanup path once
  when upgrading from a pre-rc-split install that inlined the full
  wrapper.

User-visible improvements:

- ~/.zshrc OV-plugin block: ~70 lines → 3 lines.
- `cat ~/.openviking/codex-plugin.rc.sh` shows the wrapper directly.
- Uninstall is just `rm ~/.openviking/codex-plugin.rc.sh` + delete the
  3-line block — no awk required.
- Upgrades touch the rc file at most once (to install the source hook);
  subsequent installs only rewrite the wrapper file.

Verified end-to-end: stale install with the old inline wrapper got the
3-line source hook substituted in place; `source ~/.zshrc && type codex`
showed the new wrapper loaded from the standalone file.
…ance

Follow-up to the rc-split commit. Instead of embedding the wrapper body
as a heredoc inside install.sh and writing it to a copy under
~/.openviking/, the wrapper now lives as its own checked-in file at
examples/codex-memory-plugin/setup-helper/wrapper.sh. The user's shell
rc sources that file directly from the cloned plugin checkout (the path
the installer already manages via git fetch + reset --hard).

What this buys:

- Wrapper diffs are real diffs — code review sees `+ codex() { ... }`
  rather than `+ heredoc lines inside install.sh that produce
  ~/.openviking/codex-plugin.rc.sh`.
- No copy step in the installer means no installer code path for "did
  the user accidentally edit ~/.openviking/codex-plugin.rc.sh?" or "is
  the copied file in sync with what the installer would produce now?"
- Updates ride for free on `git pull` / the installer's existing
  fetch+reset. No "re-run installer to refresh the wrapper" step.
- Uninstall is just `rm ~/.openviking/openviking-repo` (or just leave it
  — the source hook will silently no-op when the file is gone, since
  it's gated with `[ -f ... ] && .`).

Installer shrinks from ~420 lines (with the inline heredoc) to ~340.
The wrapper is unchanged content-wise; this commit only moves where it
lives.
The installer-emitted claude() wrapper had been inlined as a
marker-delimited block in the user's ~/.zshrc / ~/.bashrc. Every upgrade
required the awk-strip-and-append dance, the inline noise was hostile
to anyone reading their own rc, and there was a known footgun: if the
END marker got hand-deleted from the rc, the next install's awk-strip
would drop everything from the BEGIN marker to EOF.

Switch to the standard pyenv / nvm / fnm pattern, mirroring what the
codex-memory-plugin installer now does (see volcengine#2023):

- Wrapper body lives in its own file at ~/.openviking/claude-plugin.rc.sh
  (path overridable via OPENVIKING_CLAUDE_WRAPPER_RC). Full overwrite on
  every install — no marker logic inside the wrapper file itself.

- The user's shell rc gets a single one-line source hook, still
  marker-wrapped for clean uninstall:

    # >>> openviking claude-code memory plugin >>>
    [ -f "$HOME/.openviking/claude-plugin.rc.sh" ] && . "..."
    # <<< openviking claude-code memory plugin <<<

  Content is constant across installs, so the marker-replacement logic
  only triggers the legacy-cleanup path once (when upgrading from a
  pre-rc-split install that inlined the full claude() function body).

User-visible improvements:

- ~/.zshrc OV-plugin block: ~16 lines of wrapper body → 3 lines.
- Wrapper body is a real file you can `cat` / `diff` / restore from
  source control; no need to re-run the installer to inspect it.
- Uninstall: `rm ~/.openviking/claude-plugin.rc.sh` + delete the 3-line
  marker block.
- The END-marker corruption footgun is gone, since the marker block
  content is bytestring-stable and the awk-strip only runs when both
  markers are present anyway.

No behavior change to the wrapper itself (still pulls url/api_key from
ovcli.conf via jq).
…per/wrapper.sh

Squash-style follow-up to the previous rc-split commit on this branch:
now that the wrapper lives in its own file conceptually, just check it
in at examples/claude-code-memory-plugin/setup-helper/wrapper.sh and
have the user's shell rc source it directly from the cloned plugin
checkout. No copy step, no heredoc dance in install.sh.

Why this is better than the previous approach (wrapper body embedded as
a heredoc in install.sh, written to a copy in ~/.openviking):

- Wrapper is a real reviewable file. Diffs show `+ claude() { ... }`,
  not "+ heredoc lines that produce the wrapper".
- Updates ride on the installer's existing `git fetch + reset --hard`
  step — no separate "re-run installer to refresh the copy" path.
- One less source of truth (no $HOME copy that can drift from the
  installer's intent).
- Uninstall: `rm ~/.openviking/openviking-repo`; the source hook in the
  rc silently no-ops via `[ -f ... ] && .`.

The previous commit on this branch already shrunk the rc block from
~16 inline lines to 3 (marker + source hook + marker). This commit just
moves the wrapper body from "embedded in installer" to "checked into the
repo at a stable path", with no behavior change to the wrapper itself.
@github-actions
Copy link
Copy Markdown

PR Reviewer Guide 🔍

Here are some key observations to aid the review process:

🎫 Ticket compliance analysis 🔶

2024 - Partially compliant

Compliant requirements:

  • Extract claude() wrapper to checked-in wrapper.sh
  • User's rc gets single source hook instead of inline function
  • Preserve wrapper behavior byte-for-byte

Non-compliant requirements:

  • Remove footgun where missing END marker causes awk to drop everything to EOF

2025 - Fully compliant

Compliant requirements:

  • Extract codex() wrapper to checked-in wrapper.sh
  • User's rc gets single source hook instead of inline function
  • No copy step to ~/.openviking/
  • Preserve wrapper behavior byte-for-byte
⏱️ Estimated effort to review: 2 🔵🔵⚪⚪⚪
🏅 Score: 88
🧪 No relevant tests
🔒 No security concerns identified
✅ No TODO sections
🔀 Multiple PR themes

Sub-PR theme: refactor(plugin/claude-code): extract installer wrapper to checked-in file

Relevant files:

  • examples/claude-code-memory-plugin/setup-helper/install.sh
  • examples/claude-code-memory-plugin/setup-helper/wrapper.sh

Sub-PR theme: refactor(plugin/codex): extract installer wrapper to checked-in file

Relevant files:

  • examples/codex-memory-plugin/setup-helper/install.sh
  • examples/codex-memory-plugin/setup-helper/wrapper.sh

⚡ Recommended focus areas for review

Missing Safety Check

The awk strip does not verify presence of the END marker before proceeding, which can delete everything from BEGIN marker to EOF if END is accidentally missing. This is inconsistent with the codex installer, which has a safety check.

if grep -qF "$MARKER_BEGIN" "$RC"; then
  info "Replacing openviking source hook in $RC"
  # Strip existing block (whether it's the new one-liner or an old
  # inline-wrapper block from a previous version).
  awk -v b="$MARKER_BEGIN" -v e="$MARKER_END" '
    $0 == b {skip=1; next}
    $0 == e {skip=0; next}
    !skip
  ' "$RC" > "$RC.tmp" && mv "$RC.tmp" "$RC"
Outdated Comment

The header comment incorrectly states the installer copies the wrapper to ~/.openviking/codex-plugin.rc.sh; the new behavior is to source directly from the cloned repo checkout.

# ${OPENVIKING_CODEX_WRAPPER_RC:-~/.openviking/codex-plugin.rc.sh}. The
# installer copies this file verbatim — re-run the installer to update.

@github-actions
Copy link
Copy Markdown

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
General
Fix wrapper comment to match install behavior

Correct the header comment to match the actual installation behavior. The installer
now sources this wrapper directly from the plugin checkout instead of copying it to
a separate rc file, so updates land via git updates without re-running the
installer.

examples/codex-memory-plugin/setup-helper/wrapper.sh [3-5]

-# Installed by examples/codex-memory-plugin/setup-helper/install.sh to
-# ${OPENVIKING_CODEX_WRAPPER_RC:-~/.openviking/codex-plugin.rc.sh}. The
-# installer copies this file verbatim — re-run the installer to update.
+# Sourced from the user's shell rc via a `[ -f ... ] && . ...` hook that
+# the installer writes once. Updates land for free via the installer's
+# `git fetch + reset --hard` of the plugin checkout — no need to re-run
+# the installer just to refresh this wrapper.
Suggestion importance[1-10]: 6

__

Why: The comment in wrapper.sh incorrectly states the installer copies the file to a separate rc path, when the PR actually sources the wrapper directly from the plugin checkout. This fix prevents user confusion about how updates are applied.

Low

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors both the codex and claude-code memory plugin installers so the shell wrapper functions live in checked-in wrapper.sh files, while users’ shell rc files only contain a stable marker block that sources those wrappers from the cloned OpenViking repo checkout.

Changes:

  • Extract the previously inlined shell wrapper bodies into examples/<plugin>/setup-helper/wrapper.sh.
  • Update both installers to write a minimal 3-line marker block that sources the wrapper from the repo checkout (no $HOME copy).
  • Adjust rc marker replacement logic to clean up legacy inline-wrapper blocks during upgrades.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

File Description
examples/codex-memory-plugin/setup-helper/wrapper.sh Adds standalone codex() wrapper implementation (moved out of installer heredoc).
examples/codex-memory-plugin/setup-helper/install.sh Switches rc installation to a stable source hook pointing at the checked-in wrapper file.
examples/claude-code-memory-plugin/setup-helper/wrapper.sh Adds standalone claude() wrapper implementation (moved out of installer inline block).
examples/claude-code-memory-plugin/setup-helper/install.sh Switches rc installation to a stable source hook pointing at the checked-in wrapper file.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 202 to 212
touch "$RC"
if grep -qF "$MARKER_BEGIN" "$RC"; then
info "Existing wrapper detected in $RC — replacing in place"
info "Replacing openviking source hook in $RC"
# Strip existing block (whether it's the new one-liner or an old
# inline-wrapper block from a previous version).
awk -v b="$MARKER_BEGIN" -v e="$MARKER_END" '
$0 == b {skip=1; next}
$0 == e {skip=0; next}
!skip
' "$RC" > "$RC.tmp" && mv "$RC.tmp" "$RC"
else
Comment on lines +3 to +5
# Installed by examples/codex-memory-plugin/setup-helper/install.sh to
# ${OPENVIKING_CODEX_WRAPPER_RC:-~/.openviking/codex-plugin.rc.sh}. The
# installer copies this file verbatim — re-run the installer to update.
@ZaynJarvis ZaynJarvis merged commit 527d68d into volcengine:main May 13, 2026
8 of 9 checks passed
@github-project-automation github-project-automation Bot moved this from Backlog to Done in OpenViking project May 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants