Skip to content

Add --script mode to run command for inline metadata scripts#21

Merged
pirate merged 9 commits into
mainfrom
claude/add-shebang-dependencies-0Tijt
Apr 12, 2026
Merged

Add --script mode to run command for inline metadata scripts#21
pirate merged 9 commits into
mainfrom
claude/add-shebang-dependencies-0Tijt

Conversation

@pirate
Copy link
Copy Markdown
Member

@pirate pirate commented Apr 10, 2026

Summary

This PR adds a new --script mode to the abx-pkg run command that enables executing scripts with inline /// script metadata blocks. The feature automatically parses script metadata, resolves declared dependencies, and executes the script with a PATH that includes all resolved binaries.

Key Changes

  • New parse_script_metadata() function: Extracts TOML-formatted metadata from /// script blocks in script files. Supports multiple comment styles (#, //, --, ;, etc.) and handles multi-line TOML structures with proper indentation preservation.

  • --script flag for run command: When enabled, treats the binary name as an interpreter and the first argument as a script file path. Parses the script's metadata, resolves all declared dependencies, and executes the script with an augmented PATH.

  • Metadata-driven dependency resolution: Scripts can declare dependencies as strings or objects with additional options (custom binproviders, min_version). The resolver collects PATH entries from all successfully resolved binaries.

  • Tool configuration support: Scripts can include [tool.abx-pkg] sections in metadata to set defaults for postinstall_scripts, min_release_age, and min_version. CLI flags take precedence over metadata settings.

  • Comprehensive test coverage: Added 16 unit tests for metadata parsing (various comment styles, edge cases, TOML structures) and 7 integration tests for the full run --script workflow (argument passing, error handling, exit code propagation, CLI override behavior).

Implementation Details

  • Metadata parsing scans only the first 50 lines by default to avoid performance issues with large files
  • Metadata blocks must be properly closed with a /// marker; unclosed blocks return None
  • The script path is resolved to absolute before execution to ensure correct working directory behavior
  • Exit codes from executed scripts propagate through abx-pkg unchanged
  • Dry-run mode (--dry-run) resolves dependencies but skips actual script execution

https://claude.ai/code/session_0125eDj24UMFUhMUN8x2zmHB


Open with Devin

Summary by cubic

Adds --script mode to abx-pkg run to execute scripts with inline /// script metadata, auto-resolve dependencies, and set PATH/ENV for the chosen interpreter. Also unifies installer discovery and runtime ENV across providers, and makes version reporting resilient to missing installers.

  • New Features

    • run --script INTERPRETER SCRIPT_PATH [ARGS...] (shebang: #!/usr/bin/env -S abx-pkg run --script node). Implies --install; --dry-run only resolves.
    • Comment‑agnostic parser scans the first 50 lines for a closed /// script TOML block.
    • Builds PATH and ENV from providers; [tool.abx-pkg] values export to env vars (CLI flags still override). README adds examples.
    • playwright/puppeteer: global/managed/hermetic npm resolution.
  • Refactors

    • Unified installer discovery via INSTALLER_BINARY(), guarding abspath lookups and avoiding detect_euid recursion; version report skips missing installer binaries.
    • Providers expose ENV; apply_env() merges vars. Sets common vars like VIRTUAL_ENV, PYTHONPATH, NODE_PATH, HOMEBREW_PREFIX, GEM_HOME, GOPATH, DENO_DIR, PLAYWRIGHT_BROWSERS_PATH, PUPPETEER_CACHE_DIR.
    • Default install roots come from abx_pkg_install_root_default() which reads ABX_PKG_LIB_DIR at runtime; removed MANAGED_PROVIDER_ROOTS.
    • Subprocess output formatter accepts bytes for robust logging. CI: per‑ref concurrency with cancel‑in‑progress and 20‑minute timeouts in tests, release, and deploy-pages.

Written for commit 18eeb66. Summary will update on new commits.

cubic-dev-ai[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

cubic-dev-ai[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

cubic-dev-ai[bot]

This comment was marked as resolved.

cubic-dev-ai[bot]

This comment was marked as resolved.

@cubic-dev-ai
Copy link
Copy Markdown
Contributor

cubic-dev-ai Bot commented Apr 10, 2026

You're iterating quickly on this pull request. To help protect your rate limits, cubic has paused automatic reviews on new pushes for now—when you're ready for another review, comment @cubic-dev-ai review.

devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

@pirate
Copy link
Copy Markdown
Member Author

pirate commented Apr 10, 2026

@cubic-dev-ai review

@cubic-dev-ai
Copy link
Copy Markdown
Contributor

cubic-dev-ai Bot commented Apr 10, 2026

@cubic-dev-ai review

@pirate I have started the AI code review. It will take a few minutes to complete.

cubic-dev-ai[bot]

This comment was marked as resolved.

@pirate pirate force-pushed the claude/add-shebang-dependencies-0Tijt branch 4 times, most recently from 41370ca to 74ae064 Compare April 10, 2026 12:16
devin-ai-integration[bot]

This comment was marked as resolved.

@pirate pirate force-pushed the claude/add-shebang-dependencies-0Tijt branch 5 times, most recently from 1608e20 to e9523c0 Compare April 10, 2026 12:50
devin-ai-integration[bot]

This comment was marked as resolved.

@pirate pirate force-pushed the claude/add-shebang-dependencies-0Tijt branch 5 times, most recently from f5604fd to d41aec6 Compare April 10, 2026 18:13
devin-ai-integration[bot]

This comment was marked as resolved.

@pirate pirate force-pushed the claude/add-shebang-dependencies-0Tijt branch from 40dcd80 to 78aafd7 Compare April 10, 2026 22:26
Comment on lines +373 to +376
try:
return self.INSTALLER_BINARY(no_cache=no_cache).loaded_abspath
except Exception:
return None
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

shouldnt this be in the base method not the override?

@pirate pirate force-pushed the claude/add-shebang-dependencies-0Tijt branch from 78aafd7 to 130e145 Compare April 10, 2026 22:29
Comment on lines 350 to 363
def default_abspath_handler(
self,
bin_name: BinName | HostBinPath,
no_cache: bool = False,
**context,
) -> HostBinPath | None:
if str(bin_name) == self.INSTALLER_BIN:
return self.INSTALLER_BIN_ABSPATH
try:
return self.INSTALLER_BINARY(no_cache=no_cache).loaded_abspath
except Exception:
return None
bin_dir = self.bin_dir
assert bin_dir is not None
link_path = bin_dir / str(bin_name)
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

cant this just be on the base? then we dont need this same override everywhere.

Checking bin_dir for the bin_name seems like the most common pattern

@pirate pirate force-pushed the claude/add-shebang-dependencies-0Tijt branch 3 times, most recently from 8aad844 to 8536a0f Compare April 10, 2026 22:43
devin-ai-integration[bot]

This comment was marked as resolved.

@pirate pirate force-pushed the claude/add-shebang-dependencies-0Tijt branch from 8536a0f to d899150 Compare April 10, 2026 22:55
devin-ai-integration[bot]

This comment was marked as resolved.

@pirate pirate force-pushed the claude/add-shebang-dependencies-0Tijt branch from d899150 to bbe308c Compare April 10, 2026 23:04
devin-ai-integration[bot]

This comment was marked as resolved.

@pirate pirate force-pushed the claude/add-shebang-dependencies-0Tijt branch from bbe308c to d168e0d Compare April 10, 2026 23:17
devin-ai-integration[bot]

This comment was marked as resolved.

- parse_script_metadata(): comment-syntax-agnostic /// script parser
- --script flag on run command with automatic dep resolution
- BinProvider.ENV computed property + apply_env() for runtime env vars
- ENV overrides on all 14 providers
- [tool.abx-pkg] values passed through as env vars verbatim
- Removed MANAGED_PROVIDER_ROOTS — providers resolve install_root
  from ABX_PKG_LIB_DIR via default_factory
- abx_pkg_install_root_default reads env vars fresh (not cached)
- Playwright/puppeteer: 3-mode npm resolution (global/managed/hermetic)

https://claude.ai/code/session_0125eDj24UMFUhMUN8x2zmHB
@pirate pirate force-pushed the claude/add-shebang-dependencies-0Tijt branch from d168e0d to 48996d7 Compare April 10, 2026 23:31
devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

@pirate pirate force-pushed the claude/add-shebang-dependencies-0Tijt branch from d5c5c17 to 64f8e5c Compare April 12, 2026 05:45
devin-ai-integration[bot]

This comment was marked as resolved.

Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

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

Devin Review found 2 new potential issues.

View 38 additional findings in Devin Review.

Open in Devin Review

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔴 Yarn Berry install drops --force flag when postinstall_scripts=True and no_cache=True

In default_install_handler, the condition for adding --force was changed from if no_cache and "--force" not in cmd to if no_cache and not is_berry and "--force" not in cmd. For Yarn Berry with postinstall_scripts=True, the code never enters the Berry-specific if is_berry and not postinstall_scripts: branch (which is the only other place --force is added for Berry). This means --no-cache no longer forces a fresh install for Yarn Berry when postinstall scripts are enabled, silently serving stale cached packages.

Old vs new behavior trace

Old code path (Berry, postinstall_scripts=True, no_cache=True):

  1. cmd = ["add", ...]
  2. no_cache=True--force added
  3. is_berry and not postinstall_scripts = False → skip
  4. Result: --force present ✅

New code path:

  1. cmd = ["add", ...]
  2. no_cache and not is_berry = False → --force NOT added
  3. is_berry and not postinstall_scripts = False → skip
  4. Result: --force missing ❌

(Refers to line 296)

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines 376 to 382
if not postinstall_scripts:
cmd = [
"up",
*self.yarn_install_args,
*(
["--force"]
if no_cache and "--force" not in self.yarn_install_args
else []
),
"--mode",
"skip-build",
*install_args,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔴 Yarn Berry update handler completely drops --force for no_cache=True

The default_update_handler for Yarn Berry entirely removes the --force flag logic. In the old code, --force was added for Berry when no_cache=True in both the postinstall_scripts=True and postinstall_scripts=False branches. The new code removes the --force insertion for Berry in both branches, so --no-cache on update has no effect for Berry Yarn. The not postinstall_scripts branch also lost its --force injection (abx_pkg/binprovider_yarn.py:383-398).

(Refers to lines 376-383)

Prompt for agents
In binprovider_yarn.py default_update_handler, the Berry branch (is_berry=True) no longer adds --force when no_cache=True. The old code had:

  if is_berry:
      cmd = ["up", *self.yarn_install_args, *install_args]
      if no_cache and "--force" not in cmd:
          cmd.insert(1, "--force")

The new code removes the --force insertion entirely for Berry. Need to restore --force for no_cache=True in the Berry update path. This affects both the postinstall_scripts=True path (line 376, where cmd is built but --force never added) and the postinstall_scripts=False path (lines 378-383, where the cmd is rebuilt without --force).
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

@pirate pirate merged commit 8900987 into main Apr 12, 2026
25 of 93 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants