{"id":47268003,"url":"https://github.com/longcipher/shellflow","last_synced_at":"2026-05-02T10:00:29.077Z","repository":{"id":344506377,"uuid":"1182031299","full_name":"longcipher/shellflow","owner":"longcipher","description":"AI agent native DevOps bash script orchestrator.","archived":false,"fork":false,"pushed_at":"2026-04-27T01:59:59.000Z","size":734,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-04-27T03:36:32.957Z","etag":null,"topics":["agent-native","agent-skills","ansible","bash","devops","ssh"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/longcipher.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-03-15T00:14:32.000Z","updated_at":"2026-04-27T01:59:30.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/longcipher/shellflow","commit_stats":null,"previous_names":["longcipher/shellflow"],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/longcipher/shellflow","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/longcipher%2Fshellflow","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/longcipher%2Fshellflow/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/longcipher%2Fshellflow/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/longcipher%2Fshellflow/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/longcipher","download_url":"https://codeload.github.com/longcipher/shellflow/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/longcipher%2Fshellflow/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32530176,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-02T01:12:54.858Z","status":"online","status_checked_at":"2026-05-02T02:00:05.923Z","response_time":132,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["agent-native","agent-skills","ansible","bash","devops","ssh"],"created_at":"2026-03-15T07:27:57.800Z","updated_at":"2026-05-02T10:00:29.061Z","avatar_url":"https://github.com/longcipher.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ShellFlow\n\n\u003e AI agent native DevOps bash script orchestrator.\n\n[![DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/longcipher/shellflow)\n[![Context7](https://img.shields.io/badge/Website-context7.com-blue)](https://context7.com/longcipher/shellflow)\n[![Python 3.12+](https://img.shields.io/badge/python-3.12%2B-blue.svg)](https://www.python.org/downloads/)\n[![License: Apache-2.0](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE)\n[![PyPI](https://img.shields.io/pypi/v/shellflow.svg)](https://pypi.org/project/shellflow/)\n\n![shellflow](https://socialify.git.ci/longcipher/shellflow/image?font=Source+Code+Pro\u0026language=1\u0026name=1\u0026owner=1\u0026pattern=Circuit+Board\u0026theme=Auto)\n\nShellFlow is a minimal shell script orchestrator for mixed local and remote execution. You write one shell script, mark execution boundaries with comments, and ShellFlow runs each block in order while resolving remote targets from your SSH configuration.\n\n![shellflow-run](assets/shellflow-run.png)\n\n## What It Does\n\n- Split a shell script into `@LOCAL` and `@REMOTE` execution blocks.\n- Run blocks sequentially by default, or run annotated groups with `--mode parallel`.\n- Freeze uppercase prelude assignments once so values such as `BUILD_ID=$(date +%s)` stay consistent across local and remote blocks.\n- Declare script parameters with `# @option` and pass them as CLI flags or agent schema values.\n- Run focused parts of a playbook with `# @TASK` and `shellflow run --task`.\n- Reuse command snippets with `# @MACRO` and `# @HELPER`.\n- Add local lifecycle hooks for setup, cleanup, success, and failure handling.\n- Pass the previous block output forward as `SHELLFLOW_LAST_OUTPUT`.\n- Export named scalar values from a block into later block environments.\n- Emit either a final JSON report or streaming JSON Lines events for agents.\n- Support bounded `@TIMEOUT` and `@RETRY` directives without embedding workflow logic.\n- Provide non-interactive, dry-run, audit-log, doctor, and agent-run modes for automated execution.\n- Resolve remote targets from inline `@SERVER` definitions, `~/.ssh/config`, or a custom SSH config path.\n\n## Quick Start\n\n```bash\nuv tool install shellflow\n\nshellflow run playbooks/hello.sh\n```\n\n## Installation\n\n### User installation (from PyPI)\n\n```bash\nuv tool install shellflow\nshellflow --version\n```\n\n### Install Skill\n\n```bash\nnpx skills add longcipher/shellflow\n```\n\nThis installs the agent skill from this repository for writing and reviewing Shellflow playbooks.\n\nTo upgrade to the latest version:\n\n```bash\nuv tool upgrade shellflow\n```\n\n### Development checkout\n\n```bash\ngit clone https://github.com/longcipher/shellflow.git\ncd shellflow\nuv sync --all-groups # uv sync --refresh --reinstall --no-cache\n```\n\n### Install as a local tool (from source)\n\n```bash\nuv tool install --force .\nshellflow --version\n```\n\n### Install into the active environment (from source)\n\n```bash\nuv pip install -e .\nshellflow --version\n```\n\n## Playbook Format\n\nShellflow playbooks are ordinary shell scripts plus comment markers. Marker names are shown uppercase here and should be written that way for readability; the parser accepts marker names case-insensitively.\n\n### Block markers\n\n- `# @LOCAL`\n- `# @REMOTE \u003cssh-host\u003e`\n\n`\u003cssh-host\u003e` must match an inline `@SERVER` definition or a `Host` entry in your SSH config. Shellflow then connects using the configured `host`, `HostName`, `User`, `Port`, and identity key values.\n\n### Block directives\n\nBlock directives must appear immediately after the `# @LOCAL` or `# @REMOTE \u003cssh-host\u003e` marker, before the first command in that block.\n\n- `# @TIMEOUT \u003cseconds\u003e`\n- `# @RETRY \u003ccount\u003e`\n- `# @EXPORT NAME=stdout|stderr|output|exit_code`\n- `# @SHELL \u003cshell\u003e` - specify `bash`, `zsh`, or `sh`.\n- `# @PARALLEL [group]` - mark this block for grouped parallel execution.\n\n`@PARALLEL` may appear immediately before a block marker or as a block directive. It applies only to that one block. Consecutive parallel blocks are grouped together when you run with `--mode parallel`.\n\nExample:\n\n```bash\n#!/bin/bash\nset -euo pipefail\n\n# @option release-name=\n# @option branch=main\n\n# @LOCAL\n# @EXPORT VERSION=stdout\necho \"$RELEASE_NAME-$BRANCH\"\n\n# @REMOTE sui\nuname -a\n\n# @LOCAL\necho \"remote output: $SHELLFLOW_LAST_OUTPUT\"\necho \"version = $VERSION\"\n```\n\n### Dynamic options\n\nDeclare script parameters near the top of the file:\n\n```bash\n# @option staging\n# @option branch=main\n# @option release-name=\n```\n\n- `# @option staging` is boolean. Passing `--staging` sets `STAGING=1`.\n- `# @option branch=main` has a default. Passing `--branch develop` sets `BRANCH=develop`.\n- `# @option release-name=` is required. Pass `--release-name v1` or set `RELEASE_NAME` in the environment.\n- Option names become uppercase environment variables with dashes converted to underscores.\n\nRun it:\n\n```bash\nshellflow run deploy.sh --branch develop --release-name v2026.05.01 --staging\n```\n\n### Preamble freeze\n\nLines before the first block marker are the shared prelude. Uppercase assignments in the prelude are evaluated once locally and then exported into every block with a frozen value:\n\n```bash\nBUILD_ID=$(date +%s)\n\n# @LOCAL\necho \"$BUILD_ID\"\n\n# @REMOTE sui\necho \"$BUILD_ID\"\n```\n\nBoth blocks receive the same `BUILD_ID`. Non-assignment prelude lines, such as `set -euo pipefail` and helper functions, are still prepended to each block.\n\nKeep the prelude declarative. Avoid one-time side effects such as `cd`, `rm`, or deployment commands before the first marker.\n\n### Tasks and macros\n\nUse `# @TASK \u003cname\u003e` to label blocks and `--task` to run only that task:\n\n```bash\n# @TASK build\n# @LOCAL\necho \"build\"\n\n# @TASK deploy\n# @REMOTE sui\necho \"deploy\"\n```\n\n```bash\nshellflow run deploy.sh --task build\n```\n\nUse a single-line macro to define a task flow:\n\n```bash\n# @MACRO release build deploy smoke-test\n\n# @TASK build\n# @LOCAL\necho \"build\"\n\n# @TASK deploy\n# @REMOTE sui\necho \"deploy\"\n\n# @TASK smoke-test\n# @LOCAL\necho \"smoke\"\n```\n\n```bash\nshellflow run deploy.sh --task release\n```\n\nMacros can also expand command snippets inside a block:\n\n```bash\n# @MACRO print_env\n#   env | sort\n# @ENDMACRO\n\n# @LOCAL\nprint_env\n```\n\n### Helpers\n\nHelpers are reusable command snippets. They are expanded when a block contains only the helper name on a line:\n\n```bash\n# @HELPER backup_db\n#   pg_dump \"$DATABASE_URL\" \u003e backup.sql\n# @ENDHELPER\n\n# @LOCAL\nbackup_db\n```\n\n### Lifecycle hooks\n\nHooks run locally and share Shellflow's execution context:\n\n- `PRE` - once before all main blocks.\n- `BEFORE` - before each main block.\n- `AFTER` - after each main block.\n- `SUCCESS` - after all main blocks succeed.\n- `ERROR` - after a hook or main block fails.\n- `FINISHED` - at the end, whether the run succeeds or fails.\n\n`POST` is accepted as an alias for `AFTER`; `FINALLY` is accepted as an alias for `FINISHED`.\n\n```bash\n# @HOOK PRE\n#   echo \"prepare\"\n# @ENDHOOK\n\n# @HOOK ERROR\n#   echo \"rollback or collect diagnostics\"\n# @ENDHOOK\n\n# @HOOK FINISHED\n#   echo \"cleanup\"\n# @ENDHOOK\n```\n\n### Parallel groups\n\nMark each block that should join the parallel group:\n\n```bash\n# @PARALLEL web\n# @REMOTE web-1\nsystemctl restart nginx\n\n# @PARALLEL web\n# @REMOTE web-2\nsystemctl restart nginx\n\n# @LOCAL\necho \"runs after the parallel group\"\n```\n\nRun with:\n\n```bash\nshellflow run restart.sh --mode parallel\n```\n\nWithout `--mode parallel`, blocks run sequentially even if annotated.\n\n### Remote shells and tracing\n\nUsing `@SHELL` for remote servers with non-bash default shells:\n\nShellflow starts remote shells in login mode. For remote `zsh` and `bash` blocks, Shellflow also bootstraps `~/.zshrc` or `~/.bashrc` quietly before running your commands so tools initialized there, such as `mise`, remain available in non-interactive automation even if the rc file exits non-zero.\n\n```bash\n#!/bin/bash\n\n# @REMOTE zsh-server\n# @SHELL zsh\n# zsh-specific commands work here\nreload\ncompdef\n\n# @REMOTE bash-server\n# Default bash shell is used\nls -la\n```\n\nRemote verbose tracing uses the shell's `DEBUG` trap and executes the block as one native script. That preserves multi-line Bash and zsh constructs such as `if/else/fi`, `for` loops, and function definitions.\n\n## SSH Configuration\n\nYou can define remote hosts inline:\n\n```bash\n# @SERVER sui\n#   host: 192.168.1.100\n#   user: deploy\n#   port: 22\n#   key: ~/.ssh/id_ed25519\n\n# @REMOTE sui\nhostname\n```\n\nInline server definitions are useful for portable playbooks. The `host` field is required; `user`, `port`, and `key` are optional.\n\nExample `~/.ssh/config` entry:\n\n```sshconfig\nHost sui\n    HostName 192.168.1.100\n    User deploy\n    Port 22\n    IdentityFile ~/.ssh/id_ed25519\n```\n\nWith that config, this block is valid:\n\n```bash\n# @REMOTE sui\nhostname\n```\n\nThis is intentional:\n\n- Shellflow accepts configured SSH host aliases, not arbitrary comma-separated or free-form targets.\n- Unknown remote targets fail early with a clear error before spawning `ssh`.\n- You can override the default config path with `--ssh-config`.\n\n## Execution Model\n\nEach block runs in a fresh shell.\n\n- Shell options from the prelude are copied into every block.\n- Shell state like `cd`, shell variables, aliases, and `export` commands does not persist across blocks.\n- Explicit context values are passed forward through environment variables.\n\nExample:\n\n```bash\n# @LOCAL\necho \"build-123\"\n\n# @LOCAL\necho \"last output = $SHELLFLOW_LAST_OUTPUT\"\n```\n\nNamed exports are additive to `SHELLFLOW_LAST_OUTPUT`:\n\n```bash\n# @LOCAL\n# @EXPORT VERSION=stdout\necho \"2026.03.15\"\n\n# @REMOTE sui\necho \"deploying $VERSION\"\necho \"last output = $SHELLFLOW_LAST_OUTPUT\"\n```\n\nLines before the first marker are treated as a shared prelude and prepended to every executable block:\n\n```bash\n#!/bin/bash\nset -euo pipefail\n\n# @LOCAL\necho \"prelude is active\"\n\n# @REMOTE sui\necho \"prelude is also active here\"\n```\n\nUppercase assignments in the prelude are special: Shellflow evaluates them once locally, freezes the values, and exports them into every block. That keeps release IDs, timestamps, and option-derived values stable across local and remote execution.\n\n## Agent-Native Usage\n\nShellflow is designed to be the execution substrate for an outer agent, not an embedded planner.\n\n- Use `--json` when you want one final machine-readable run report.\n- Use `--jsonl` when you want ordered event records while the script runs.\n- Use `--no-input` for CI or agent runs where interactive prompts must fail deterministically.\n- Use `--dry-run` to preview planned execution without running commands.\n- Use `--audit-log \u003cpath\u003e` to mirror the structured event stream into a redacted JSONL file.\n- Use `agent-run --json-input` when an agent already has the script body and option values in memory.\n\nRecommended agent flow:\n\n1. Generate or select a plain shell script with `@LOCAL` and `@REMOTE` markers.\n2. Read `# @option` declarations and provide required values.\n3. Add bounded directives only where needed: `@TIMEOUT`, `@RETRY`, and `@EXPORT`.\n4. Run with `--json` or `--jsonl`.\n5. Let the outer agent decide whether to retry, branch, or stop based on Shellflow's structured result.\n\nAgent-run input:\n\n```bash\nshellflow agent-run --json-input '{\n  \"script\": \"# @option release-name=\\n# @LOCAL\\necho \\\"$RELEASE_NAME\\\"\\n\",\n  \"options\": {\"release-name\": \"v2026.05.01\"},\n  \"dry_run\": false\n}'\n```\n\nShellflow intentionally does not provide:\n\n- Conditional directives such as `@IF stdout_contains=...`\n- A workflow DSL or embedded ReAct loop\n- Heuristic destructive-command detection\n- Multi-host comma expansion inside one `@REMOTE` marker\n\nThose decisions belong in the outer agent or automation layer.\n\n### Agent-Native Reporting\n\nShellflow's structured modes are designed for LLM agent consumption:\n\n- **Stable run and block identifiers**: JSON and JSONL output include `run_id`, one-based block indexes, and stable `block-N` identifiers.\n\n- **Separated stdout and stderr**: Block reports keep stdout, stderr, combined output, exit code, failure kind, retries, timeouts, and exported values explicit.\n\n- **Command-level remote tracing**: Remote verbose execution uses shell `DEBUG` traps to report the command about to run without breaking multi-line shell syntax.\n\n- **Audit-safe exports**: Audit logs redact exported values whose names look secret-like, such as `TOKEN`, `SECRET`, or `PASSWORD`.\n\n- **Bounded verbose output**: `--output-lines` limits verbose per-command log tails while preserving full block output in structured results.\n\n## CLI\n\n```text\nshellflow run \u003cscript\u003e\nshellflow run \u003cscript\u003e --verbose\nshellflow run \u003cscript\u003e --output-lines 50\nshellflow run \u003cscript\u003e --json\nshellflow run \u003cscript\u003e --jsonl\nshellflow run \u003cscript\u003e --no-input\nshellflow run \u003cscript\u003e --dry-run\nshellflow run \u003cscript\u003e --mode parallel\nshellflow run \u003cscript\u003e --task \u003ctask-or-macro\u003e\nshellflow run \u003cscript\u003e --audit-log ./audit.jsonl --jsonl\nshellflow run \u003cscript\u003e --ssh-config ./ssh_config\nshellflow run \u003cscript\u003e --release-name v1 --branch main\nshellflow agent-run --json-input '{\"script\":\"# @LOCAL\\necho hi\\n\"}'\nshellflow doctor [script]\nshellflow --version\n```\n\nExamples:\n\n```bash\nshellflow run playbooks/hello.sh\nshellflow run playbooks/hello.sh -v\nshellflow run playbooks/hello.sh --json\nshellflow run playbooks/hello.sh --jsonl --no-input\nshellflow run playbooks/hello.sh --dry-run --jsonl\nshellflow run playbooks/hello.sh --audit-log ./audit.jsonl --jsonl\nshellflow run playbooks/hello.sh --ssh-config ~/.ssh/config.work\nshellflow run playbooks/deploy.sh --task release --mode parallel --json\nshellflow doctor playbooks/deploy.sh --ssh-config ~/.ssh/config.work\n```\n\nRun `shellflow run --help`, `shellflow agent-run --help`, or `shellflow doctor --help` for the exact command options supported by the installed version.\n\n## Development\n\nUseful commands:\n\n```bash\njust sync\njust test\njust bdd\njust test-all\njust typecheck\njust build\njust publish\n```\n\nDirect verification commands:\n\n```bash\nuv run pytest -q\nuv run behave features\nuv run ruff check .\nuv run ty check src tests\nuv build\n```\n\n## Release Process\n\nShellflow supports both local publishing and GitHub Actions release publishing.\n\n### Local publish\n\n```bash\njust publish\n```\n\n`uv publish` uses standard `uv` authentication mechanisms such as `UV_PUBLISH_TOKEN`, or PyPI trusted publishing when supported by the environment.\n\n### GitHub Actions publish on tag push\n\nThe repository includes:\n\n- `.github/workflows/ci.yml` for lint, type-check, test, and build verification.\n- `.github/workflows/release.yml` for publishing to PyPI when a tag like `v0.1.0` is pushed.\n\nRecommended release flow:\n\n```bash\ngit tag v0.1.0\ngit push origin v0.1.0\n```\n\nTo use trusted publishing with PyPI:\n\n1. Create a `pypi` environment in GitHub repository settings.\n2. Add this repository as a trusted publisher in the PyPI project settings.\n3. Push a `v*` tag.\n\nThe release workflow then runs verification, builds distributions with `uv build`, and uploads them with `uv publish`.\n\n## Project Layout\n\n```text\nshellflow/\n├── src/shellflow.py\n├── src/advanced_modes.py\n├── src/config.py\n├── src/doctor.py\n├── src/helpers.py\n├── src/hooks.py\n├── src/macros.py\n├── src/variables.py\n├── tests/\n├── features/\n├── playbooks/\n├── pyproject.toml\n├── Justfile\n└── README.md\n```\n\n## License\n\nApache-2.0\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flongcipher%2Fshellflow","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flongcipher%2Fshellflow","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flongcipher%2Fshellflow/lists"}