Scripts & Automation
Developer scripts for building, testing, and releasing PraisonAI
The src/praisonai/scripts/ folder contains automation scripts for development, testing, and release workflows.
Script Overview
| Script | Purpose |
|---|---|
install.sh | Frictionless, environment-isolated one-liner installer (uv tool → pipx → venv fallback) |
install.ps1 | One-liner installer for Windows |
bump_and_release.py | Automated version bump and release |
bump_version.py | Version management utility |
check_version_sync.py | Verify version consistency across packages |
release.py | PyPI release automation |
test-install-smoke.sh | Smoke test the installer |
One-Liner Installer
The installer scripts provide a frictionless installation experience:
macOS/Linux:
curl -fsSL https://praison.ai/install.sh | bashWindows PowerShell:
iwr -useb https://praison.ai/install.ps1 | iexFeatures
- OS Detection – Automatically detects macOS, Linux (various distros), Windows, WSL
- Isolation Backend – Auto-selects
uv tool→pipx→ venv fallback; override with--backend - Python Management – Installs Python 3.10+ if not available (venv path only)
- Package Manager Support – brew, apt, dnf, pacman, winget, chocolatey
- PATH Shim – Drops
~/.local/bin/praisonaiso the CLI is available without activating a venv - Idempotent PATH Block – Appends a clearly-marked
# >>> PraisonAI PATH >>>block to shell rc; skip with--no-modify-path - Shell Completions – Offers to install bash/zsh/fish completions via
praisonai completion <shell> - Interactive Onboarding – Prompts for LLM setup and bot configuration after installation
- Dry Run Mode – Preview changes before applying
Environment Variables
| Variable | Default | Description |
|---|---|---|
PRAISONAI_VERSION | latest | Specific version to install |
PRAISONAI_EXTRAS | "" | Comma-separated extras (defaults to all) |
PRAISONAI_BACKEND | auto | Force backend: uv / pipx / venv / system / auto |
PRAISONAI_INSTALL_DIR | ~/.praisonai | Base dir for the venv fallback |
PRAISONAI_NO_MODIFY_PATH | 0 | Skip shell rc PATH modification (1 to enable) |
PRAISONAI_SKIP_VENV | 0 | Skip isolation entirely (1 to enable) |
PRAISONAI_DRY_RUN | 0 | Preview mode |
PRAISONAI_NO_ONBOARD | 0 | Skip interactive onboarding entirely |
Examples
# Basic install (isolated: uv tool -> pipx -> venv)
curl -fsSL https://praison.ai/install.sh | bash
# Force pipx backend
curl -fsSL https://praison.ai/install.sh | bash -s -- --backend pipx
# Install with extras
PRAISONAI_EXTRAS=ui,chat curl -fsSL https://praison.ai/install.sh | bash
# Don't touch shell rc
curl -fsSL https://praison.ai/install.sh | bash -s -- --no-modify-path
# Dry run (preview only)
PRAISONAI_DRY_RUN=1 curl -fsSL https://praison.ai/install.sh | bash
# Non-interactive for CI/CD
curl -fsSL https://praison.ai/install.sh | bash -s -- --no-promptVersion Management
bump_version.py
Updates version across all package files:
cd src/praisonai
python scripts/bump_version.py 2.3.0Updates:
praisonai/version.pypyproject.toml
check_version_sync.py
Verifies all packages have consistent versions:
python src/praisonai/scripts/check_version_sync.pyRelease Workflow
bump_and_release.py
Automated release pipeline:
python src/praisonai/scripts/bump_and_release.py- Bumps version
- Updates changelog
- Creates git tag
- Pushes to GitHub
- Triggers PyPI release
release.py
Manual PyPI release:
python src/praisonai/scripts/release.pySmoke Testing
test-install-smoke.sh
Tests the installer in isolated Docker containers:
cd src/praisonai/scripts
./test-install-smoke.shTests across:
- Ubuntu 22.04
- Debian 12
- Alpine Linux
Docker Test Files
Located in scripts/docker/install-smoke/:
| File | Purpose |
|---|---|
Dockerfile | Test container image |
run.sh | Installation test script |
Adding New Scripts
When adding new scripts:
- Location: Place in
src/praisonai/scripts/ - Permissions: Make executable with
chmod +x script.sh - Documentation: Update this page
- Testing: Add to CI/CD if applicable
# Make script executable
chmod +x src/praisonai/scripts/my-script.sh
# Test locally
./src/praisonai/scripts/my-script.shTypeScript SDK Scripts
The src/praisonai-ts/scripts/ folder holds Node scripts that run as part of the TypeScript SDK’s dual-build pipeline.
| Script | Purpose |
|---|---|
clean (npm script) | Deletes dist/ before each build (prebuild → clean). Uses the Node builtin fs.rmSync instead of a rimraf binary, so it runs before npm install populates devDependencies. |
esm-shim.js | Post-processes the emitted ESM build so files that still use CJS globals (require, __dirname, __filename, module.exports) keep working under Node ESM. See TypeScript SDK Dual Build. |
verify-dist.mjs | Smoke-checks that both published entry points load and export Agent — CJS via require and ESM via import. |
webview-gate.mjs | Fails the build if a Node builtin (fs, crypto, events, …) becomes reachable at import time from a webview/mobile entry point, and if the entry does not parse at FLOOR_TARGET = "chrome58" (the Android 8 WebView floor). Inspects both TypeScript sources and the built dist/esm/… artifacts. |
clean (prebuild)
- Runs before every build via the
prebuildhook (npm run build→prebuild→clean). - Implemented as a Node one-liner:
node -e "require('fs').rmSync('dist',{recursive:true,force:true})". - Needs no installed
devDependencies— it runs even beforenpm installhas populatednode_modules. This letsnpm cisucceed in a fresh worktree when a sibling package (e.g.praisonai-mobile) pullspraisonai-tsin via afile:link and triggers itspreparehook. force: truemakes it idempotent (no error whendist/is absent), andfs.rmSyncis cross-platform (Windows-safe).- Changed from
rimraf distin PR #4849.
esm-shim.js
- Runs after the ESM build (
npm run build:esm→tsc -p tsconfig.esm.json && node scripts/esm-shim.js). - Prepends a
createRequirebanner only to files that genuinely use CJS. - The banner is browser-safe: it uses guarded top-level
await import('module' | 'url' | 'path').catch(() => null), so a bundler defers the imports rather than failing on them. Node behaviour is byte-identical. - In a browser,
requireis stubbed to a function that throws only if a lazy provider path is actually taken — the shim imposes no runtime cost on the webview path. - Fixed in PR #4484; the previous static-import form broke browser bundles of
dist/esm/mobile.js. - Detection uses
stripStringsAndCommentsto blank literal text and comments, but keeps template-literal${...}interpolations intact so a realrequire(...)inside one is still detected. - Regression tests:
src/praisonai-ts/tests/unit/packaging/esm-shim-banner.test.ts.
webview-gate.mjs
- Inspects both the TypeScript sources (
src/mobile.ts,src/agent/simple.ts) and the built artifacts (dist/esm/mobile.js,dist/esm/agent/simple.js) whendist/exists. - On a fresh clone with no
dist/, the gate prints a note and continues with the source-only check. - CI runs
npm run buildbefore the gate, so the built-artifact check runs on every PR — the gate sees exactly what ships.
# The two checks per entry
| Check | esbuild target | Uses metafile? | Fails when |
|---|---|---|---|
loadable in a webview | ["safari16", "chrome108"] | yes | a Node builtin is imported statically from the graph |
bundles for chrome58 | ["chrome58"] | no | esbuild refuses to lower the syntax (in practice: a top-level await anywhere on the graph, dynamically imported or not) |
The chrome58 check is the one to reach for when a merge suddenly turns praisonai/mobile unbuildable on Android 8. The most common cause is that a source file added a require() or a __dirname, which made scripts/esm-shim.js prepend the createRequire banner to the emitted ESM file — and the banner IS a top-level await, so the entry stops parsing at chrome58. The gate reports the file and line; the fix is to convert the require() to a static import (no cycle) or to await import(…) (inside a function, not at module scope).
verify-dist.mjs
- Runs as
npm run verify:dist, wired into the release / publish smoke checks so a brokendist/never ships. - Loads
dist/index.jsvia CommonJSrequire(...)anddist/esm/index.jsvia ESM dynamicimport(...), then asserts that each entry exportsAgent. Exits non-zero if either entry fails to load orAgentis missing. - Cross-platform ESM path handling.
path.join(root, 'dist', 'esm', 'index.js')returns a native path — on Windows that starts with a drive letter (e.g.F:\...\dist\esm\index.js), which Node’s ESM loader would reject as an unsupported URL scheme (ERR_UNSUPPORTED_ESM_URL_SCHEME, protocolf:). The script therefore converts the path withpathToFileURL(...).hrefbefore the dynamicimport(...). The CJSrequire(...)line accepts native paths on every platform and is unchanged. - Fixed in PR #4923 (issue #4922).