> ## Documentation Index
> Fetch the complete documentation index at: https://praison.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# 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:**

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
curl -fsSL https://praison.ai/install.sh | bash
```

**Windows PowerShell:**

```powershell theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
iwr -useb https://praison.ai/install.ps1 | iex
```

### Features

* **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/praisonai` so 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

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
# 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-prompt
```

***

## Version Management

### bump\_version.py

Updates version across all package files:

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
cd src/praisonai
python scripts/bump_version.py 2.3.0
```

Updates:

* `praisonai/version.py`
* `pyproject.toml`

### check\_version\_sync.py

Verifies all packages have consistent versions:

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
python src/praisonai/scripts/check_version_sync.py
```

***

## Release Workflow

### bump\_and\_release.py

Automated release pipeline:

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
python src/praisonai/scripts/bump_and_release.py
```

1. Bumps version
2. Updates changelog
3. Creates git tag
4. Pushes to GitHub
5. Triggers PyPI release

### release.py

Manual PyPI release:

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
python src/praisonai/scripts/release.py
```

***

## Smoke Testing

### test-install-smoke.sh

Tests the installer in isolated Docker containers:

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
cd src/praisonai/scripts
./test-install-smoke.sh
```

Tests 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:

1. **Location**: Place in `src/praisonai/scripts/`
2. **Permissions**: Make executable with `chmod +x script.sh`
3. **Documentation**: Update this page
4. **Testing**: Add to CI/CD if applicable

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
# Make script executable
chmod +x src/praisonai/scripts/my-script.sh

# Test locally
./src/praisonai/scripts/my-script.sh
```

***

## TypeScript 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](/docs/developers/typescript-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 `prebuild` hook (`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 before `npm install` has populated `node_modules`. This lets `npm ci` succeed in a fresh worktree when a sibling package (e.g. `praisonai-mobile`) pulls `praisonai-ts` in via a `file:` link and triggers its `prepare` hook.
* `force: true` makes it idempotent (no error when `dist/` is absent), and `fs.rmSync` is cross-platform (Windows-safe).
* Changed from `rimraf dist` in [PR #4849](https://github.com/MervinPraison/PraisonAI/pull/4849).

<Note>
  `src/praisonai-ts/package-lock.json` is committed (since [PR #4884](https://github.com/MervinPraison/PraisonAI/pull/4884)) so that `npm install` in CI reproduces the exact dependency tree the mobile bundle gate measures. `pnpm-lock.yaml` is also kept for local pnpm workflows.
</Note>

#### esm-shim.js

* Runs after the ESM build (`npm run build:esm` → `tsc -p tsconfig.esm.json && node scripts/esm-shim.js`).
* Prepends a `createRequire` banner 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, `require` is 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](https://github.com/MervinPraison/PraisonAI/pull/4484); the previous static-import form broke browser bundles of `dist/esm/mobile.js`.
* Detection uses `stripStringsAndComments` to blank literal text and comments, but keeps template-literal `${...}` interpolations intact so a real `require(...)` 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`) when `dist/` exists.
* On a fresh clone with no `dist/`, the gate prints a note and continues with the source-only check.
* CI runs `npm run build` before 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 broken `dist/` never ships.
* Loads `dist/index.js` via CommonJS `require(...)` and `dist/esm/index.js` via ESM dynamic `import(...)`, then asserts that each entry exports `Agent`. Exits non-zero if either entry fails to load or `Agent` is 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`, protocol `f:`). The script therefore converts the path with `pathToFileURL(...).href` before the dynamic `import(...)`. The CJS `require(...)` line accepts native paths on every platform and is unchanged.
* Fixed in [PR #4923](https://github.com/MervinPraison/PraisonAI/pull/4923) (issue [#4922](https://github.com/MervinPraison/PraisonAI/issues/4922)).

<Note>
  Rule of thumb when extending this script: for any new ESM entry, wrap the joined path with `pathToFileURL(...).href` before `await import(...)`. For CJS entries, a plain `require(join(...))` continues to work.
</Note>

***

## Related

<CardGroup cols={2}>
  <Card title="Local Development" icon="code" href="/docs/developers/local-development">
    Setting up dev environment
  </Card>

  <Card title="Testing" icon="flask" href="/docs/developers/testing">
    Running tests
  </Card>

  <Card icon="package" href="/docs/developers/typescript-dual-build">
    ESM/CJS build and the createRequire banner
  </Card>
</CardGroup>
