Last active
September 6, 2026 01:51
-
-
Save Kcrong/3dd66eaeda6838e4e9e8650059b75908 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| # | |
| # AI-DLC V2 Kiro CLI Installer | |
| # ============================ | |
| # | |
| # This script is intentionally documented for review before execution. | |
| # | |
| # Safety contract | |
| # --------------- | |
| # - Installs into the current working directory only. It accepts no arguments. | |
| # - Reads the release from the official public repository below. | |
| # - Does not run sudo, install packages, or directly read credential files. | |
| # - Does not modify global ~/.kiro settings. | |
| # - Clones the fixed release into a temporary directory and checks out only dist/kiro. | |
| # - Scans every destination file before changing the project. | |
| # - Lists every overlap and requires explicit confirmation through /dev/tty. | |
| # - Refusal exits before creating, modifying, or deleting any project file. | |
| # - Approval copies every release file individually; no directory is overwritten as a unit. | |
| # - Unrelated and stale project files are never deleted. | |
| # - The temporary clone is the only directory automatically deleted. | |
| # - Doctor is requested through the configured Kiro CLI aidlc agent in no-interactive mode. | |
| # - The doctor request may invoke a configured model, consume credits, and use provider networking. | |
| # - Installation succeeds only when Kiro CLI exits successfully and reports N passed, 0 failed. | |
| # | |
| # Overwrite limitations | |
| # --------------------- | |
| # - One confirmation covers the complete displayed overlap list. | |
| # - Approved files are replaced without backups. Use source control if rollback is required. | |
| # - A forced termination after approval may leave a partial installation; rerun to repair it. | |
| # - A terminal is mandatory when overlaps exist. Non-interactive overwrites fail closed. | |
| # | |
| # Fail on command errors, undeclared variables, and failures inside pipelines. | |
| set -Eeuo pipefail | |
| IFS=$'\n\t' | |
| # User input cannot redirect the installer to another repository or release. | |
| readonly REPO_URL="https://github.com/awslabs/aidlc-workflows.git" | |
| # Latest official GitHub release verified on 2026-09-06. | |
| # This fixed tag makes a future curl | bash one-liner reproducible. | |
| readonly RELEASE_TAG="v2.7.0" | |
| tmp_dir="" | |
| log() { printf '==> %s\n' "$*"; } | |
| warn() { printf 'WARNING: %s\n' "$*" >&2; } | |
| die() { printf 'ERROR: %s\n' "$*" >&2; exit 1; } | |
| # tmp_dir receives only the path returned by mktemp below. | |
| cleanup() { [[ -z "$tmp_dir" || ! -d "$tmp_dir" ]] || find "$tmp_dir" -depth -delete; } | |
| trap cleanup EXIT | |
| # This is a single-purpose one-liner installer. Reject all arguments instead of maintaining | |
| # path, ref, usage, and help branches that could diverge from the reviewed defaults. | |
| (($# == 0)) || die "this installer does not accept arguments" | |
| # Check prerequisites without installing anything automatically. | |
| # bun is required by the installed AI-DLC hooks and tools, but this installer does not invoke | |
| # a TypeScript utility directly for doctor; it sends the doctor prompt through Kiro CLI. | |
| for tool in git bun kiro-cli cp dirname find mktemp uname; do | |
| command -v "$tool" >/dev/null 2>&1 || die "required command not found: $tool" | |
| done | |
| os="$(uname -s)" | |
| [[ "$os" == "Linux" || "$os" == "Darwin" ]] || die "supported operating systems: macOS and Linux" | |
| # Check only the local Kiro CLI version here. The doctor step later invokes the aidlc agent. | |
| kiro_version="$(kiro-cli --version 2>&1)" || die "kiro-cli --version failed" | |
| [[ "$kiro_version" =~ ([0-9]+)\.([0-9]+) ]] || die "unable to parse Kiro CLI version" | |
| (( BASH_REMATCH[1] > 2 || (BASH_REMATCH[1] == 2 && BASH_REMATCH[2] >= 6) )) \ | |
| || die "Kiro CLI 2.6 or newer is required" | |
| # Resolve the existing current directory. No project directory is created by the installer. | |
| project="$(pwd -P)" | |
| [[ "$project" != *$'\n'* && "$project" != *$'\r'* ]] \ | |
| || die "current directory contains a control character" | |
| # Reject symlinks in managed destinations so a copy cannot escape the project boundary. | |
| for path in "$project/.kiro" "$project/aidlc" "$project/AGENTS.md" "$project/.gitignore"; do | |
| [[ ! -L "$path" ]] || die "refusing to install through symlink: $path" | |
| done | |
| for dir in "$project/.kiro" "$project/aidlc"; do | |
| [[ ! -d "$dir" || -z "$(find "$dir" -type l -print -quit)" ]] \ | |
| || die "managed tree contains a symlink: $dir" | |
| done | |
| # Keep V1 rules untouched and warn after installation if they were present. | |
| v1_rules_present=false | |
| if [[ -d "$project/.kiro/steering/aws-aidlc-rules" \ | |
| || -d "$project/.kiro/aws-aidlc-rule-details" ]]; then | |
| v1_rules_present=true | |
| fi | |
| # Prefer a session-scoped scratch directory, then TMPDIR, then the Unix fallback. | |
| temp_root="${KIROCREW_SCRATCH:-${TMPDIR:-/tmp}}" | |
| [[ -d "$temp_root" && -w "$temp_root" ]] || die "temporary directory is not writable: $temp_root" | |
| tmp_dir="$(mktemp -d "$temp_root/aidlc-v2-install.XXXXXX")" | |
| source_dir="$tmp_dir/source" | |
| # Clone exactly the fixed release tag. Sparse checkout materializes only dist/kiro. | |
| GIT_TERMINAL_PROMPT=0 git clone --quiet --branch "$RELEASE_TAG" --single-branch \ | |
| --depth=1 --filter=blob:none --sparse --no-checkout "$REPO_URL" "$source_dir" | |
| git -C "$source_dir" sparse-checkout set dist/kiro | |
| git -C "$source_dir" checkout --quiet --detach "$RELEASE_TAG" | |
| # Verify that the checkout is exactly the reviewed release tag. | |
| resolved_tag="$(git -C "$source_dir" describe --tags --exact-match HEAD)" | |
| [[ "$resolved_tag" == "$RELEASE_TAG" ]] || die "resolved release tag does not match: $resolved_tag" | |
| resolved_sha="$(git -C "$source_dir" rev-parse HEAD)" | |
| distribution="$source_dir/dist/kiro" | |
| # Fail before touching the project if the release layout is incomplete or contains symlinks. | |
| for path in .kiro aidlc AGENTS.md .gitignore; do | |
| [[ -e "$distribution/$path" ]] || die "release distribution is missing: $path" | |
| done | |
| [[ -z "$(find "$distribution" -type l -print -quit)" ]] || die "release distribution contains a symlink" | |
| # Build a complete file-level plan. No project file is changed in this phase. | |
| declare -a source_files=() | |
| declare -a target_files=() | |
| declare -a overlap_indexes=() | |
| while IFS= read -r -d '' source_file; do | |
| relative_path="${source_file#"$distribution/"}" | |
| target_file="$project/$relative_path" | |
| index="${#source_files[@]}" | |
| source_files[$index]="$source_file" | |
| target_files[$index]="$target_file" | |
| if [[ -e "$target_file" ]]; then | |
| [[ -f "$target_file" ]] || die "destination exists but is not a regular file: $relative_path" | |
| overlap_indexes[${#overlap_indexes[@]}]="$index" | |
| fi | |
| done < <(find "$distribution" -type f -print0) | |
| ((${#source_files[@]} > 0)) || die "release distribution contains no files" | |
| log "Release: $RELEASE_TAG" | |
| log "Files to install: ${#source_files[@]}" | |
| log "Overlapping files: ${#overlap_indexes[@]}" | |
| # Show every destructive target before requesting one batch confirmation. | |
| # /dev/tty keeps the prompt usable when the script itself arrives through stdin. | |
| if ((${#overlap_indexes[@]} > 0)); then | |
| [[ -r /dev/tty && -w /dev/tty ]] \ | |
| || die "overlapping files require an interactive terminal for confirmation" | |
| { | |
| printf '\nThe following existing files would be overwritten:\n' | |
| for index in "${overlap_indexes[@]}"; do | |
| printf ' %s\n' "${target_files[$index]#"$project/"}" | |
| done | |
| printf '\nOverwrite all listed files and continue? [y/N] ' | |
| } >/dev/tty | |
| answer="" | |
| IFS= read -r answer </dev/tty || die "unable to read overwrite confirmation" | |
| case "$answer" in | |
| y|Y|yes|Yes|YES) log "Overwrite approved for ${#overlap_indexes[@]} file(s)" ;; | |
| *) die "installation cancelled; no project files were changed" ;; | |
| esac | |
| fi | |
| # Copy each release file separately. Existing files reached this point only after approval. | |
| for index in "${!source_files[@]}"; do | |
| source_file="${source_files[$index]}" | |
| target_file="${target_files[$index]}" | |
| mkdir -p "$(dirname "$target_file")" | |
| cp -p "$source_file" "$target_file" | |
| done | |
| [[ "$v1_rules_present" == false ]] \ | |
| || warn "legacy V1 rule directories were retained for manual review" | |
| # Ask the aidlc agent to route --doctor through the normal Kiro CLI workflow. | |
| # The `--` separator is required; without it, Kiro CLI parses --doctor as its own unknown option. | |
| # Capture stdout so exit status 0 alone is insufficient: the output must also contain a clean | |
| # doctor summary. Stderr remains visible for hook and model progress reporting. | |
| log "Running AI-DLC doctor through Kiro CLI" | |
| doctor_output="$( | |
| cd "$project" | |
| kiro-cli chat --no-interactive --agent aidlc -- '--doctor' | |
| )" || die "Kiro CLI doctor prompt failed" | |
| printf '%s\n' "$doctor_output" | |
| [[ "$doctor_output" =~ [0-9]+[[:space:]]passed,[[:space:]]0[[:space:]]failed ]] \ | |
| || die "AI-DLC doctor did not report a clean result" | |
| # Print only reproducibility data, not credentials, environment dumps, or project paths. | |
| printf '\nAI-DLC V2 installation complete.\n' | |
| printf 'Release: %s\nSource commit: %s\n' "$resolved_tag" "$resolved_sha" |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
curl -sL https://gist.githubusercontent.com/Kcrong/3dd66eaeda6838e4e9e8650059b75908/raw | bash