#!/usr/bin/env bash
# Cohesivity quickstart — reconciles Cohesivity delivery for installed coding
# clients and creates an ephemeral project tenant. Safe to re-run (idempotent).
# Source: https://cohesivity.ai/quickstart.sh   Docs: https://cohesivity.ai/llms.txt
# Defensive by design: no 'set -e'; each step is guarded and never aborts the rest.
BASE='https://cohesivity.ai'

NO_PLUGIN=0
DRY_RUN=0
for arg in "$@"; do
  case "$arg" in
    --no-plugin)
      [ "$NO_PLUGIN" -eq 0 ] || { echo 'cohesivity: usage: bash -s -- [--no-plugin] [--dry-run]' >&2; exit 2; }
      NO_PLUGIN=1
      ;;
    --dry-run)
      [ "$DRY_RUN" -eq 0 ] || { echo 'cohesivity: usage: bash -s -- [--no-plugin] [--dry-run]' >&2; exit 2; }
      DRY_RUN=1
      ;;
    *)
      echo 'cohesivity: usage: bash -s -- [--no-plugin] [--dry-run]' >&2
      exit 2
      ;;
  esac
done

# BEGIN GENERATED COHESIVITY ARTIFACT CONSTANTS
PLUGIN_ARCHIVE_URL='https://codeload.github.com/cohesivity-org/cohesivity-plugin/tar.gz/b9d5c233ef611f984fc6585ac5a0349b041395b0'
PLUGIN_ARCHIVE_SIZE='490480'
PLUGIN_ARCHIVE_SHA256='7d88cabc1a59dae6bf3a981a23aee2f566e59b8656307ba3a927e26ade107e78'
STANDALONE_SKILL_URL='https://raw.githubusercontent.com/cohesivity-org/cohesivity-skill/f97e0d2ac8a653b7d54d1bb6e70aee78a8887e60/cohesivity.skill.md'
STANDALONE_SKILL_SIZE='13456'
STANDALONE_SKILL_SHA256='3b0d9cda6167263cb35a4e3b54ed455113318a1b24cb5e341f26843456b0b589'
# END GENERATED COHESIVITY ARTIFACT CONSTANTS

CODEX_DIR="${CODEX_HOME:-$HOME/.codex}"
HERMES_DIR="${HERMES_HOME:-$HOME/.hermes}"
PLUGIN_DATA_ROOT="${XDG_DATA_HOME:-$HOME/.local/share}/cohesivity/plugin-packages"
HAS_CLAUDE=0
HAS_CURSOR=0
HAS_CODEX=0
HAS_GEMINI=0
HAS_ANTIGRAVITY=0
HAS_OPENCLAW=0
HAS_HERMES=0
HAS_OPENCODE=0
command -v claude >/dev/null 2>&1 && HAS_CLAUDE=1
{ command -v cursor >/dev/null 2>&1 || command -v cursor-agent >/dev/null 2>&1 || [ -d "$HOME/.cursor" ]; } && HAS_CURSOR=1
command -v codex >/dev/null 2>&1 && HAS_CODEX=1
command -v gemini >/dev/null 2>&1 && HAS_GEMINI=1
{ command -v agy >/dev/null 2>&1 || [ -d "$HOME/.gemini/antigravity-cli" ]; } && HAS_ANTIGRAVITY=1
command -v openclaw >/dev/null 2>&1 && HAS_OPENCLAW=1
command -v hermes >/dev/null 2>&1 && HAS_HERMES=1
command -v opencode >/dev/null 2>&1 && HAS_OPENCODE=1

if [ "$DRY_RUN" -eq 1 ]; then
  echo "cohesivity/quickstart: dry-run"
  if [ "$NO_PLUGIN" -eq 1 ]; then
    echo "dry-run: would install the verified standalone skill only; no plugin or MCP configuration"
  else
    [ "$HAS_CLAUDE" -eq 1 ] && echo "dry-run: would reconcile Claude with its native plugin marketplace"
    [ "$HAS_CURSOR" -eq 1 ] && echo "dry-run: would atomically reconcile Cursor's portable plugin"
    [ "$HAS_CODEX" -eq 1 ] && echo "dry-run: would reconcile Codex with its native plugin marketplace"
    [ "$HAS_GEMINI" -eq 1 ] && echo "dry-run: would reconcile Gemini's native extension"
    [ "$HAS_ANTIGRAVITY" -eq 1 ] && echo "dry-run: would reconcile Antigravity's native plugin"
    [ "$HAS_OPENCLAW" -eq 1 ] && echo "dry-run: would reconcile OpenClaw's Claude marketplace bundle and remote OAuth MCP"
    [ "$HAS_HERMES" -eq 1 ] && echo "dry-run: would reconcile Hermes's native skill plus local and remote MCP entries"
    [ "$HAS_OPENCODE" -eq 1 ] && echo "dry-run: would reconcile OpenCode's global skill, local six-tool MCP, and remote OAuth MCP entry"
    if [ "$HAS_CLAUDE" -eq 0 ] && [ "$HAS_CURSOR" -eq 0 ] && [ "$HAS_CODEX" -eq 0 ] && [ "$HAS_GEMINI" -eq 0 ] && [ "$HAS_ANTIGRAVITY" -eq 0 ] && [ "$HAS_OPENCLAW" -eq 0 ] && [ "$HAS_HERMES" -eq 0 ] && [ "$HAS_OPENCODE" -eq 0 ]; then
      echo "dry-run: no supported client detected; would install the verified cross-client standalone skill"
    fi
  fi
  if [ -f .cohesivity ] && grep -q 'coh_management_key=' .cohesivity 2>/dev/null; then
    echo "dry-run: would reuse the existing .cohesivity"
  else
    echo "dry-run: would create an ephemeral tenant and gitignore .cohesivity"
  fi
  for af in AGENTS.md CLAUDE.md README.md; do
    [ -f "$af" ] || continue
    grep -q 'BEGIN:cohesivity' "$af" 2>/dev/null || echo "dry-run: would update $af"
  done
  exit 0
fi

# ── Attribution ─────────────────────────────────────────────────────────────
# The harness is the nearest ancestor process that is not generic plumbing.
# Only this process's own lineage is read — never the system process list — and
# only the resulting name is sent. The lists below are closed sets of Unix
# plumbing, interpreters, and generic path segments; they never name a harness,
# so any harness, present or future, identifies itself by its own process or
# script name. Nothing inferable -> "none".
PLUMB=" sh bash zsh fish dash ksh csh tcsh env sudo doas timeout timelimit nice setsid nohup xargs script ssh sshd tmux screen login su init systemd launchd docker containerd containerd-shim runc podman npm npx pnpm yarn bunx ps awk grep sed find curl wget gnome-terminal konsole xterm alacritty kitty wezterm tilix terminator iterm2 terminal warp-terminal "
INTERP=" node bun deno python python2 python3 ruby perl "
GENERIC=" cli index main app run dist build bin lib libexec src out node_modules _npx versions current "
HN=none; p=$PPID; n=0
# The guard is -ge 1, not -gt 1: pid 1 must be EXAMINED, not merely used as
# the stop condition. On an ordinary machine pid 1 is init/systemd and the
# list below rejects it anyway, but under a microVM or container entrypoint
# pid 1 IS the supervising process that spawned this command, so skipping it
# left those environments with no name at all. Pid 1 reports parent 0, so the
# walk still ends one step later.
while [ "${p:-0}" -ge 1 ] && [ "$n" -lt 20 ]; do
  n=$((n + 1))
  c="$(tr '\0' '\n' < "/proc/$p/cmdline" 2>/dev/null || ps -o args= -p "$p" 2>/dev/null | tr ' ' '\n')"
  # A process that rewrites its title (npm does) leaves no NUL separators, so
  # the whole command arrives as one line; take its first field or the name
  # would be the tail of an entire command line.
  a="$(printf '%s\n' "$c" | head -1)"; a="${a%% *}"; a="${a##*/}"; a="${a#-}"
  case "$INTERP" in *" $a "*)
    s="$(printf '%s\n' "$c" | sed -n '2,8p' | grep / | grep -v = | head -1)"
    while [ -n "$s" ]; do b="${s##*/}"; b="${b%.*}"
      case "$GENERIC" in *" $b "*) s="${s%/*}";; *) break;; esac
    done
    [ -n "$s" ] && a="${s##*/}" && a="${a%.*}";;
  esac
  case "$PLUMB" in *" $a "*) ;; *) [ -n "$a" ] && { HN="$a"; break; };; esac
  # stat is "pid (comm) state ppid ...", and comm can contain spaces and
  # parens when a process rewrites its title, so fields must be counted after
  # the LAST ')' — not with a plain field index.
  p="$(sed 's/.*) //' "/proc/$p/stat" 2>/dev/null | awk '{print $2}' || ps -o ppid= -p "$p" 2>/dev/null | tr -d ' ')"
  case "$p" in ''|*[!0-9]*) p=0;; esac
done
HN="$(printf %s "$HN" | tr -cd 'A-Za-z0-9._-' | cut -c1-40)"; [ -z "$HN" ] && HN=none
UA="{quickstart:$HN}"

download_to() {
  if command -v curl >/dev/null 2>&1; then
    curl -fsSL -H "User-Agent: $UA" -o "$2" "$1" 2>/dev/null
  elif command -v wget >/dev/null 2>&1; then
    wget -qO "$2" --header="User-Agent: $UA" "$1" 2>/dev/null
  else
    return 1
  fi
}

file_sha256() {
  if command -v shasum >/dev/null 2>&1; then
    shasum -a 256 "$1" 2>/dev/null | awk '{print $1}'
  elif command -v sha256sum >/dev/null 2>&1; then
    sha256sum "$1" 2>/dev/null | awk '{print $1}'
  elif command -v openssl >/dev/null 2>&1; then
    openssl dgst -sha256 "$1" 2>/dev/null | sed 's/^.*= *//'
  else
    return 1
  fi
}

verify_file() {
  VF_SIZE="$(wc -c < "$1" 2>/dev/null | tr -d '[:space:]')"
  if [ -z "$VF_SIZE" ] || [ "$VF_SIZE" != "$2" ]; then
    echo "cohesivity: artifact size verification failed (expected $2, got ${VF_SIZE:-unknown})" >&2
    return 1
  fi
  VF_SHA="$(file_sha256 "$1")"
  if [ -z "$VF_SHA" ] || [ "$VF_SHA" != "$3" ]; then
    echo "cohesivity: artifact SHA-256 verification failed" >&2
    return 1
  fi
  return 0
}

validate_archive() {
  ARCHIVE_LIST="$(mktemp "${TMPDIR:-/tmp}/cohesivity-archive-list.XXXXXX" 2>/dev/null)" || return 1
  ARCHIVE_TYPES="$(mktemp "${TMPDIR:-/tmp}/cohesivity-archive-types.XXXXXX" 2>/dev/null)" || { rm -f "$ARCHIVE_LIST"; return 1; }
  if ! tar -tzf "$PLUGIN_ARCHIVE" > "$ARCHIVE_LIST" 2>/dev/null; then
    echo "cohesivity: plugin artifact is not a readable gzip tar archive" >&2
    rm -f "$ARCHIVE_LIST" "$ARCHIVE_TYPES"
    return 1
  fi
  ARCHIVE_ROOT=""
  while IFS= read -r entry; do
    case "$entry" in
      ''|/*|..|../*|*/..|*/../*|*\\*)
        echo "cohesivity: plugin artifact contains an unsafe path" >&2
        rm -f "$ARCHIVE_LIST" "$ARCHIVE_TYPES"
        return 1
        ;;
    esac
    clean="${entry#./}"
    first="${clean%%/*}"
    [ -n "$first" ] || { rm -f "$ARCHIVE_LIST" "$ARCHIVE_TYPES"; return 1; }
    if [ -z "$ARCHIVE_ROOT" ]; then ARCHIVE_ROOT="$first";
    elif [ "$ARCHIVE_ROOT" != "$first" ]; then
      echo "cohesivity: plugin artifact contains multiple roots" >&2
      rm -f "$ARCHIVE_LIST" "$ARCHIVE_TYPES"
      return 1
    fi
  done < "$ARCHIVE_LIST"
  if [ -z "$ARCHIVE_ROOT" ] || ! tar -tvzf "$PLUGIN_ARCHIVE" > "$ARCHIVE_TYPES" 2>/dev/null; then
    echo "cohesivity: plugin artifact metadata could not be verified" >&2
    rm -f "$ARCHIVE_LIST" "$ARCHIVE_TYPES"
    return 1
  fi
  while IFS= read -r detail; do
    kind="${detail%${detail#?}}"
    case "$kind" in -|d) ;; *)
      echo "cohesivity: plugin artifact contains links or special files" >&2
      rm -f "$ARCHIVE_LIST" "$ARCHIVE_TYPES"
      return 1
      ;;
    esac
  done < "$ARCHIVE_TYPES"
  rm -f "$ARCHIVE_LIST" "$ARCHIVE_TYPES"
  return 0
}

atomic_install_tree() {
  source="$1"
  dest="$2"
  parent="${dest%/*}"
  mkdir -p "$parent" 2>/dev/null || return 1
  stage="$(mktemp -d "$parent/.cohesivity-stage.XXXXXX" 2>/dev/null)" || return 1
  if ! cp -R "$source/." "$stage/" 2>/dev/null; then rm -rf "$stage"; return 1; fi
  backup="$parent/.cohesivity-backup.$$"
  while [ -e "$backup" ] || [ -L "$backup" ]; do backup="$backup.x"; done
  had_old=0
  if [ -e "$dest" ] || [ -L "$dest" ]; then
    mv "$dest" "$backup" 2>/dev/null || { rm -rf "$stage"; return 1; }
    had_old=1
  fi
  if mv "$stage" "$dest" 2>/dev/null; then
    [ "$had_old" -eq 0 ] || rm -rf "$backup"
    return 0
  fi
  [ "$had_old" -eq 0 ] || mv "$backup" "$dest" 2>/dev/null
  rm -rf "$stage"
  return 1
}

atomic_install_file() {
  source="$1"
  dest="$2"
  parent="${dest%/*}"
  mkdir -p "$parent" 2>/dev/null || return 1
  stage="$(mktemp "$parent/.cohesivity-file.XXXXXX" 2>/dev/null)" || return 1
  if cp "$source" "$stage" 2>/dev/null && chmod 644 "$stage" 2>/dev/null && mv "$stage" "$dest" 2>/dev/null; then return 0; fi
  rm -f "$stage"
  return 1
}

install_skill_copy() {
  if atomic_install_file "$STANDALONE_SKILL" "$1/SKILL.md"; then
    SKILL_TARGETS=$((SKILL_TARGETS + 1))
    return 0
  fi
  return 1
}

PLUGIN_ARCHIVE=""
PLUGIN_EXTRACT=""
STANDALONE_SKILL=""
HERMES_IMPORT=""
cleanup_delivery() {
  [ -z "$PLUGIN_ARCHIVE" ] || rm -f "$PLUGIN_ARCHIVE" 2>/dev/null
  [ -z "$PLUGIN_EXTRACT" ] || rm -rf "$PLUGIN_EXTRACT" 2>/dev/null
  [ -z "$STANDALONE_SKILL" ] || rm -f "$STANDALONE_SKILL" 2>/dev/null
  [ -z "$HERMES_IMPORT" ] || rm -rf "$HERMES_IMPORT" 2>/dev/null
}
trap 'cleanup_delivery' EXIT
trap 'cleanup_delivery; exit 1' HUP INT TERM

prepare_standalone_skill() {
  STANDALONE_SKILL="$(mktemp "${TMPDIR:-/tmp}/cohesivity-skill.XXXXXX" 2>/dev/null)" || return 1
  download_to "$STANDALONE_SKILL_URL" "$STANDALONE_SKILL" || { echo "cohesivity: could not fetch the standalone skill" >&2; return 1; }
  verify_file "$STANDALONE_SKILL" "$STANDALONE_SKILL_SIZE" "$STANDALONE_SKILL_SHA256"
}

prepare_plugin() {
  PLUGIN_ARCHIVE="$(mktemp "${TMPDIR:-/tmp}/cohesivity-plugin.XXXXXX" 2>/dev/null)" || return 1
  download_to "$PLUGIN_ARCHIVE_URL" "$PLUGIN_ARCHIVE" || { echo "cohesivity: could not fetch the pinned plugin artifact" >&2; return 1; }
  verify_file "$PLUGIN_ARCHIVE" "$PLUGIN_ARCHIVE_SIZE" "$PLUGIN_ARCHIVE_SHA256" || return 1
  validate_archive || return 1
  PLUGIN_EXTRACT="$(mktemp -d "${TMPDIR:-/tmp}/cohesivity-plugin-extract.XXXXXX" 2>/dev/null)" || return 1
  tar -xzf "$PLUGIN_ARCHIVE" -C "$PLUGIN_EXTRACT" 2>/dev/null || return 1
  PLUGIN_ROOT="$PLUGIN_EXTRACT/$ARCHIVE_ROOT"
  CLAUDE_PACKAGE="$PLUGIN_ROOT/packages/claude"
  CODEX_MARKETPLACE="$PLUGIN_ROOT/packages/codex"
  GEMINI_PACKAGE="$PLUGIN_ROOT/packages/gemini"
  ANTIGRAVITY_PACKAGE="$PLUGIN_ROOT/packages/antigravity"
  PORTABLE_PACKAGE="$PLUGIN_ROOT"
  [ -f "$CLAUDE_PACKAGE/.claude-plugin/marketplace.json" ] &&
    [ -f "$CODEX_MARKETPLACE/.agents/plugins/marketplace.json" ] &&
    [ -f "$GEMINI_PACKAGE/gemini-extension.json" ] &&
    [ -f "$ANTIGRAVITY_PACKAGE/plugin.json" ] &&
    [ -f "$PORTABLE_PACKAGE/plugin.json" ] &&
    [ -f "$PORTABLE_PACKAGE/skills/cohesivity/SKILL.md" ] &&
    [ -f "$PORTABLE_PACKAGE/mcp/project-bootstrap.mjs" ] || {
      echo "cohesivity: verified plugin artifact has an unsupported package layout" >&2
      return 1
    }
  if find "$PLUGIN_ROOT" ! -type f ! -type d -print 2>/dev/null | grep -q .; then
    echo "cohesivity: extracted plugin artifact contains links or special files" >&2
    return 1
  fi
  return 0
}

install_hermes_native() {
  command -v hermes >/dev/null 2>&1 || return 1
  command -v node >/dev/null 2>&1 || return 1
  HERMES_NODE="$(node -p 'process.execPath' </dev/null 2>/dev/null)" || return 1
  case "$HERMES_NODE" in /*) ;; *) return 1;; esac
  HERMES_SERVER="$HERMES_DIR/mcp/cohesivity/project-bootstrap.mjs"
  atomic_install_tree "$PORTABLE_PACKAGE/skills/cohesivity" "$HERMES_DIR/skills/cohesivity" || return 1
  atomic_install_file "$PORTABLE_PACKAGE/mcp/project-bootstrap.mjs" "$HERMES_SERVER" || return 1
  HERMES_IMPORT="$(mktemp -d "${TMPDIR:-/tmp}/cohesivity-hermes-import.XXXXXX" 2>/dev/null)" || return 1
  mkdir -p "$HERMES_IMPORT/.claude" || return 1
  node -e '
const { writeFileSync } = require("node:fs");
writeFileSync(process.argv[1], JSON.stringify({
  mcpServers: {
    "cohesivity-local": { command: process.argv[2], args: [process.argv[3]] },
    cohesivity: { url: process.argv[4] }
  }
}), { mode: 0o600 });
' "$HERMES_IMPORT/.claude.json" "$HERMES_NODE" "$HERMES_SERVER" "$BASE/mcp/manage" || return 1
  hermes import-agent claude-code --source "$HERMES_IMPORT/.claude" --overwrite --yes </dev/null >/dev/null 2>&1 || return 1
  hermes config set mcp_servers.cohesivity-local.enabled true </dev/null >/dev/null 2>&1 || return 1
  hermes config set mcp_servers.cohesivity.auth oauth </dev/null >/dev/null 2>&1 || return 1
  hermes config set mcp_servers.cohesivity.enabled true </dev/null >/dev/null 2>&1 || return 1
  HERMES_LOCAL_JSON="$(hermes config get mcp_servers.cohesivity-local --json </dev/null 2>/dev/null)" || return 1
  HERMES_REMOTE_JSON="$(hermes config get mcp_servers.cohesivity --json </dev/null 2>/dev/null)" || return 1
  node -e '
const local = JSON.parse(process.argv[1]);
const remote = JSON.parse(process.argv[2]);
const valid = local.command === process.argv[3] &&
  JSON.stringify(local.args) === JSON.stringify([process.argv[4]]) && local.enabled === true &&
  remote.url === process.argv[5] && remote.auth === "oauth" && remote.enabled === true;
process.exit(valid ? 0 : 1);
' "$HERMES_LOCAL_JSON" "$HERMES_REMOTE_JSON" "$HERMES_NODE" "$HERMES_SERVER" "$BASE/mcp/manage" || return 1
  rm -rf "$HERMES_IMPORT" 2>/dev/null
  HERMES_IMPORT=""
  return 0
}

# Machine id: one per machine, stored outside any project (a project's
# .cohesivity is per project; a machine owns many). Sent on genesis so the
# tenants this machine creates can be joined together. The server issues one
# only when we have none; from then on this file is reused and never rewritten.
MID_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/cohesivity"
MID_FILE="$MID_DIR/machine-id"
MID=""
if [ -f "$MID_FILE" ]; then MID="$(tr -d '\r[:space:]' < "$MID_FILE" 2>/dev/null)"; fi

# POST genesis, dumping response headers to $1 so a newly issued machine id can
# be read back. Branch explicitly on whether MID is set rather than splicing the
# flag in with a conditional parameter expansion: unquoted, that word-splits on
# the space inside the header value and sends a corrupted header.
post_genesis() {
  if command -v curl >/dev/null 2>&1; then
    if [ -n "$MID" ]; then
      curl -fsSL -X POST -H "User-Agent: $UA" -H "X-Cohesivity-Machine-Id: $MID" -D "$1" "$BASE/api/genesis" 2>/dev/null
    else
      curl -fsSL -X POST -H "User-Agent: $UA" -D "$1" "$BASE/api/genesis" 2>/dev/null
    fi
  elif command -v wget >/dev/null 2>&1; then
    if [ -n "$MID" ]; then
      wget -qO- --method=POST --header="User-Agent: $UA" --header="X-Cohesivity-Machine-Id: $MID" -S "$BASE/api/genesis" 2>"$1"
    else
      wget -qO- --method=POST --header="User-Agent: $UA" -S "$BASE/api/genesis" 2>"$1"
    fi
  fi
}

echo ""
echo "cohesivity/quickstart: setting up (harness: $HN)"
echo ""

# 1) Delivery: plugin-aware by default; --no-plugin installs only the skill.
DELIVERY_FAILED=0
SKILL_TARGETS=0
if [ "$NO_PLUGIN" -eq 1 ]; then
  if prepare_standalone_skill; then
    [ "$HAS_CLAUDE" -eq 0 ] || install_skill_copy "$HOME/.claude/skills/cohesivity" || DELIVERY_FAILED=1
    [ "$HAS_CURSOR" -eq 0 ] || install_skill_copy "$HOME/.cursor/skills/cohesivity" || DELIVERY_FAILED=1
    [ "$HAS_CODEX" -eq 0 ] || install_skill_copy "$CODEX_DIR/skills/cohesivity" || DELIVERY_FAILED=1
    [ "$HAS_GEMINI" -eq 0 ] || install_skill_copy "$HOME/.gemini/skills/cohesivity" || DELIVERY_FAILED=1
    if [ "$HAS_ANTIGRAVITY" -eq 1 ] || [ "$HAS_OPENCODE" -eq 1 ]; then
      install_skill_copy "$HOME/.agents/skills/cohesivity" || DELIVERY_FAILED=1
    fi
    [ "$HAS_OPENCLAW" -eq 0 ] || install_skill_copy "$HOME/.openclaw/skills/cohesivity" || DELIVERY_FAILED=1
    [ "$HAS_HERMES" -eq 0 ] || install_skill_copy "$HERMES_DIR/skills/cohesivity" || DELIVERY_FAILED=1
    [ "$SKILL_TARGETS" -eq 0 ] && install_skill_copy "$HOME/.agents/skills/cohesivity" || true
    if [ "$SKILL_TARGETS" -gt 0 ]; then echo "cohesivity: standalone skill reconciled in $SKILL_TARGETS client location(s)";
    else DELIVERY_FAILED=1; fi
  else
    DELIVERY_FAILED=1
  fi
else
  CLIENT_COUNT=$((HAS_CLAUDE + HAS_CURSOR + HAS_CODEX + HAS_GEMINI + HAS_ANTIGRAVITY + HAS_OPENCLAW + HAS_HERMES + HAS_OPENCODE))
  if [ "$CLIENT_COUNT" -eq 0 ]; then
    if prepare_standalone_skill && install_skill_copy "$HOME/.agents/skills/cohesivity"; then
      echo "cohesivity: no supported client detected; standalone skill installed in ~/.agents"
    else
      DELIVERY_FAILED=1
    fi
  elif prepare_plugin; then
    if [ "$HAS_CLAUDE" -eq 1 ]; then
      if command -v claude >/dev/null 2>&1 && claude plugin --help >/dev/null 2>&1; then
        CLAUDE_DURABLE="$PLUGIN_DATA_ROOT/claude"
        if atomic_install_tree "$CLAUDE_PACKAGE" "$CLAUDE_DURABLE" && claude plugin marketplace add "$CLAUDE_DURABLE" >/dev/null 2>&1 && claude plugin install cohesivity@cohesivity >/dev/null 2>&1; then
          echo "cohesivity: Claude: native plugin installed"
        else
          echo "cohesivity: Claude plugin delivery failed" >&2; DELIVERY_FAILED=1
        fi
      elif command -v claude >/dev/null 2>&1 && atomic_install_file "$CLAUDE_PACKAGE/skills/cohesivity/SKILL.md" "$HOME/.claude/skills/cohesivity/SKILL.md" && claude mcp add --transport http --scope user cohesivity "$BASE/mcp/manage" >/dev/null 2>&1; then
        echo "cohesivity: Claude: legacy adapter installed the skill and native remote MCP entry"
      else
        echo "cohesivity: Claude plugin delivery failed" >&2; DELIVERY_FAILED=1
      fi
    fi
    if [ "$HAS_CURSOR" -eq 1 ]; then
      if atomic_install_tree "$PORTABLE_PACKAGE" "$HOME/.cursor/plugins/local/cohesivity"; then echo "cohesivity: Cursor: portable plugin installed";
      else echo "cohesivity: Cursor plugin delivery failed" >&2; DELIVERY_FAILED=1; fi
    fi
    if [ "$HAS_CODEX" -eq 1 ]; then
      if command -v codex >/dev/null 2>&1 && codex plugin --help >/dev/null 2>&1; then
        CODEX_DURABLE="$PLUGIN_DATA_ROOT/codex"
        if atomic_install_tree "$CODEX_MARKETPLACE" "$CODEX_DURABLE" && codex plugin marketplace add "$CODEX_DURABLE" >/dev/null 2>&1 && codex plugin add cohesivity@cohesivity >/dev/null 2>&1; then
          echo "cohesivity: Codex: native plugin installed"
        else
          echo "cohesivity: Codex plugin delivery failed" >&2; DELIVERY_FAILED=1
        fi
      elif command -v codex >/dev/null 2>&1 && atomic_install_file "$CODEX_MARKETPLACE/plugins/cohesivity/skills/cohesivity/SKILL.md" "$CODEX_DIR/skills/cohesivity/SKILL.md" && codex mcp add cohesivity --url "$BASE/mcp/manage" >/dev/null 2>&1; then
        echo "cohesivity: Codex: legacy adapter installed the skill and native remote MCP entry"
      else
        echo "cohesivity: Codex plugin delivery failed" >&2; DELIVERY_FAILED=1
      fi
    fi
    if [ "$HAS_GEMINI" -eq 1 ]; then
      if command -v gemini >/dev/null 2>&1 && gemini extensions --help >/dev/null 2>&1; then
        GEMINI_DURABLE="$PLUGIN_DATA_ROOT/gemini"
        if atomic_install_tree "$GEMINI_PACKAGE" "$GEMINI_DURABLE" && {
          if [ -d "$HOME/.gemini/extensions/cohesivity" ]; then GEMINI_CLI_TRUST_WORKSPACE=true gemini extensions update cohesivity >/dev/null 2>&1;
          else GEMINI_CLI_TRUST_WORKSPACE=true gemini extensions install "$GEMINI_DURABLE" --consent >/dev/null 2>&1; fi
        }; then echo "cohesivity: Gemini: native extension installed";
        else echo "cohesivity: Gemini plugin delivery failed" >&2; DELIVERY_FAILED=1; fi
      elif command -v gemini >/dev/null 2>&1 && atomic_install_file "$GEMINI_PACKAGE/skills/cohesivity/SKILL.md" "$HOME/.gemini/skills/cohesivity/SKILL.md" && gemini mcp add --transport http --scope user cohesivity "$BASE/mcp/manage" >/dev/null 2>&1; then
        echo "cohesivity: Gemini: legacy adapter installed the skill and native remote MCP entry"
      else
        echo "cohesivity: Gemini plugin delivery failed" >&2; DELIVERY_FAILED=1
      fi
    fi
    if [ "$HAS_ANTIGRAVITY" -eq 1 ]; then
      ANTIGRAVITY_DURABLE="$PLUGIN_DATA_ROOT/antigravity"
      if command -v agy >/dev/null 2>&1 && atomic_install_tree "$ANTIGRAVITY_PACKAGE" "$ANTIGRAVITY_DURABLE" && agy plugin install "$ANTIGRAVITY_DURABLE" >/dev/null 2>&1; then
        echo "cohesivity: Antigravity: native plugin installed"
      elif [ -d "$HOME/.gemini/antigravity-cli" ] && atomic_install_tree "$ANTIGRAVITY_PACKAGE" "$HOME/.gemini/antigravity-cli/plugins/cohesivity"; then
        echo "cohesivity: Antigravity: installed by verified positive-home fallback"
      else
        echo "cohesivity: Antigravity plugin delivery failed" >&2; DELIVERY_FAILED=1
      fi
    fi
    if [ "$HAS_OPENCLAW" -eq 1 ]; then
      OPENCLAW_DURABLE="$PLUGIN_DATA_ROOT/openclaw"
      OPENCLAW_MCP_CONFIG='{"url":"'"$BASE"'/mcp/manage","transport":"streamable-http","auth":"oauth"}'
      if command -v openclaw >/dev/null 2>&1 && atomic_install_tree "$CLAUDE_PACKAGE" "$OPENCLAW_DURABLE" && openclaw plugins install cohesivity --marketplace "$OPENCLAW_DURABLE" --force >/dev/null 2>&1 && openclaw plugins enable cohesivity >/dev/null 2>&1 && openclaw mcp set cohesivity "$OPENCLAW_MCP_CONFIG" >/dev/null 2>&1; then
        echo "cohesivity: OpenClaw: Claude marketplace bundle and remote OAuth MCP installed"
      else
        echo "cohesivity: OpenClaw plugin delivery failed" >&2; DELIVERY_FAILED=1
      fi
    fi
    if [ "$HAS_HERMES" -eq 1 ]; then
      if install_hermes_native; then
        echo "cohesivity: Hermes: native skill and MCP servers installed"
      else
        echo "cohesivity: Hermes integration delivery failed" >&2; DELIVERY_FAILED=1
      fi
    fi
    if [ "$HAS_OPENCODE" -eq 1 ]; then
      OPENCODE_DURABLE="$PLUGIN_DATA_ROOT/opencode"
      if atomic_install_tree "$PORTABLE_PACKAGE" "$OPENCODE_DURABLE" &&
        atomic_install_file "$OPENCODE_DURABLE/skills/cohesivity/SKILL.md" "$HOME/.agents/skills/cohesivity/SKILL.md" &&
        opencode mcp add cohesivity-local -- node "$OPENCODE_DURABLE/mcp/project-bootstrap.mjs" </dev/null >/dev/null 2>&1 &&
        opencode mcp add cohesivity --url "$BASE/mcp/manage" </dev/null >/dev/null 2>&1; then
        echo "cohesivity: OpenCode: global skill, local six-tool MCP, and remote OAuth MCP entry installed"
      else
        echo "cohesivity: OpenCode integration delivery failed" >&2; DELIVERY_FAILED=1
      fi
    fi
    echo "cohesivity: OAuth/browser login was not started. Restart each updated client, then use its MCP login UI or command when you want claimed-tenant management tools."
    [ "$HAS_CLAUDE" -eq 0 ] || echo "  - Claude: restart or run /reload-plugins; authenticate cohesivity from /mcp when needed."
    [ "$HAS_CURSOR" -eq 0 ] || echo "  - Cursor: restart or run Developer: Reload Window; connect cohesivity from MCP settings when needed."
    [ "$HAS_CODEX" -eq 0 ] || echo "  - Codex: start a new session; run codex mcp login cohesivity when needed."
    [ "$HAS_GEMINI" -eq 0 ] || echo "  - Gemini: restart the CLI; run /mcp auth cohesivity when needed."
    [ "$HAS_ANTIGRAVITY" -eq 0 ] || echo "  - Antigravity: restart agy; authenticate the cohesivity MCP server when prompted."
    [ "$HAS_OPENCLAW" -eq 0 ] || echo "  - OpenClaw: restart the gateway; run openclaw mcp login cohesivity when needed."
    [ "$HAS_HERMES" -eq 0 ] || echo "  - Hermes: restart the client; local bootstrap tools need no login, and hermes mcp login cohesivity starts OAuth through Dynamic Client Registration only when management tools are needed."
    [ "$HAS_OPENCODE" -eq 0 ] || echo "  - OpenCode: restart the client; local bootstrap tools need no login, and opencode mcp auth cohesivity starts OAuth only when management tools are needed."
  else
    DELIVERY_FAILED=1
  fi
fi

# 2) Tenant: reuse a complete regular .cohesivity, else create one only when no
# credential path exists. Never follow or overwrite an incomplete/symlinked path.
if [ -f .cohesivity ] && [ ! -L .cohesivity ] &&
  grep -q '^tenant_id=' .cohesivity 2>/dev/null &&
  grep -q '^coh_management_key=coh_man_' .cohesivity 2>/dev/null &&
  grep -q '^coh_application_key=coh_app_' .cohesivity 2>/dev/null; then
  echo "cohesivity: reusing the existing .cohesivity (no new tenant created)"
elif [ -e .cohesivity ] || [ -L .cohesivity ]; then
  echo "cohesivity: existing .cohesivity is incomplete or unsafe; repair or remove it before retrying." >&2
else
  IGNORE_READY=0
  if [ -f .gitignore ]; then
    if grep -qxF '.cohesivity' .gitignore 2>/dev/null || printf '%s\n' '.cohesivity' >> .gitignore 2>/dev/null; then IGNORE_READY=1; fi
  elif (umask 077 && printf '%s\n' '.cohesivity' > .gitignore) 2>/dev/null; then
    IGNORE_READY=1
  fi
  if [ "$IGNORE_READY" -ne 1 ]; then
    echo "cohesivity: could not establish the .cohesivity ignore rule; tenant creation was not attempted." >&2
  else
    HDRS="$(mktemp 2>/dev/null || echo "/tmp/coh-hdrs.$$")"
    RESP="$(post_genesis "$HDRS")"
    if printf '%s' "$RESP" | grep -q '^tenant_id=[^[:space:]][^[:space:]]*$' &&
      printf '%s' "$RESP" | grep -q '^coh_management_key=coh_man_' &&
      printf '%s' "$RESP" | grep -q '^coh_application_key=coh_app_' &&
      printf '%s' "$RESP" | grep -q '^expires_at=[^[:space:]][^[:space:]]*$' &&
      printf '%s' "$RESP" | grep -Eq '^tenant_lifecycle=(ephemeral|claimed)$' &&
      printf '%s' "$RESP" | grep -Eq '^runtime_profile=v1-[0-9]+$'; then
      CREDENTIAL_TMP=".cohesivity.tmp.$$"
      rm -f "$CREDENTIAL_TMP" 2>/dev/null
      if (umask 077 && printf '%s' "$RESP" > "$CREDENTIAL_TMP") 2>/dev/null &&
        chmod 600 "$CREDENTIAL_TMP" 2>/dev/null && mv "$CREDENTIAL_TMP" .cohesivity 2>/dev/null; then
    # Persist whatever machine id the server issued. The header comes back only
    # on the request that minted one, so its presence IS the signal to store —
    # both when we sent none and when the id we sent no longer verified (secret
    # rotated, file corrupted or truncated). Gating this on "we had none"
    # instead pinned a dead id forever: the server minted a replacement on every
    # single run and this never took it, so every project became its own
    # machine and the machine -> tenant join it exists for silently died.
    NEW_MID="$(grep -i '^[[:space:]]*X-Cohesivity-Machine-Id:' "$HDRS" 2>/dev/null | head -1 | sed 's/^[^:]*:[[:space:]]*//' | tr -d '\r[:space:]')"
    if [ -n "$NEW_MID" ]; then
      mkdir -p "$MID_DIR" 2>/dev/null && printf '%s\n' "$NEW_MID" > "$MID_FILE" 2>/dev/null
    fi
        echo "cohesivity: created an ephemeral tenant -> ./.cohesivity"
      else
        rm -f "$CREDENTIAL_TMP" 2>/dev/null
        echo "cohesivity: tenant credentials could not be installed atomically." >&2
      fi
    else
      echo "cohesivity: no complete tenant credentials were returned (rate limit, network, or origin error)."
      echo "  retry shortly — re-running this quickstart is idempotent."
    fi
    rm -f "$HDRS" 2>/dev/null
  fi
  
fi

# 3) Point an existing project file at this project's backend. Never creates
# one; appends once, so a re-run leaves the file untouched.
#
# Two audiences, two lines. AGENTS.md / CLAUDE.md are read by an agent already
# working here, so they name where the credentials live. README.md is read by
# whoever picks the repo up cold — including an agent with no skill installed —
# so it points at the status endpoint and the docs instead of at a file it has
# no reason to trust yet.
for af in AGENTS.md CLAUDE.md README.md; do
  [ -f "$af" ] || continue
  grep -q 'BEGIN:cohesivity' "$af" 2>/dev/null && continue
  case "$af" in
    README.md) line='If you are another agent who just picked up this project, you can get the status of its backend using the status endpoint, read more at https://cohesivity.ai/backend-for-ai-agents';;
    *) line='This project uses [Cohesivity](https://cohesivity.ai) for its managed backend. Credentials and tenant state live in `.cohesivity`. Live status is at `GET '"$BASE"'/api/status`.';;
  esac
  # "$line" is expanded, never re-parsed: the backticks the agent-file line
  # carries stay literal markdown rather than becoming command substitution.
  { echo ''
    echo '<!-- BEGIN:cohesivity -->'
    echo "$line"
    echo '<!-- END:cohesivity -->'; } >> "$af" 2>/dev/null && echo "cohesivity: updated $af"
done

# 4) Ground THIS session (a freshly written skill may not auto-load right now).
TID=""
if [ -f .cohesivity ]; then TID="$(grep -m1 '^tenant_id=' .cohesivity 2>/dev/null | sed 's/^tenant_id=//')"; fi
echo ""
FINAL_STATUS=0
if [ -z "$TID" ]; then
  # No tenant: .cohesivity was never written, so there are no keys to read and
  # nothing to provision against. Saying "ready" here and printing the key/
  # provision lines anyway contradicts the reason printed just above, and
  # exiting 0 hid the failure from anything that pipes this script into bash.
  echo "cohesivity: setup incomplete - no tenant was created."
  echo "  - No .cohesivity was written, so there are no keys yet and nothing is provisioned."
  echo "  - The reason is printed above. Fix it and re-run; this quickstart is idempotent."
  FINAL_STATUS=1
else
  echo "cohesivity: ready. tenant $TID"
  echo "  - Keys are in .cohesivity (gitignored, do not commit)."
  echo "  - Provision a service: POST $BASE/api/resources/<name>  (Authorization: Bearer <coh_management_key>)"
  echo "  - Per-service docs: $BASE/offerings/<name>   ·   full reference: $BASE/llms.txt"
fi
if [ "$DELIVERY_FAILED" -ne 0 ]; then
  echo "cohesivity: delivery incomplete; tenant bootstrap was still completed where safe" >&2
  FINAL_STATUS=1
fi
exit "$FINAL_STATUS"
