From 1f98a55f1febe46b4623b6780b25b297a4ac558b Mon Sep 17 00:00:00 2001 From: leeguooooo <9278645+leeguooooo@users.noreply.github.com> Date: Wed, 14 Oct 2026 14:08:15 +0900 Subject: [PATCH] feat: add sflow (Session Flow) to the use-family --- .claude-plugin/marketplace.json | 18 +++++++++++++++++- README.md | 12 ++++++++++-- install-clis.sh | 4 ++-- install-use-family.sh | 8 +++++--- plugins/use-family/.claude-plugin/plugin.json | 5 +++-- plugins/use-family/scripts/doctor.sh | 4 ++-- plugins/use-family/scripts/sync-clis.sh | 6 +++--- plugins/use-family/skills/use-family/SKILL.md | 4 +++- tests/doctor.test.sh | 1 + tests/install-clis.test.sh | 4 ++-- upgrade-use-family.sh | 8 ++++---- 11 files changed, 52 insertions(+), 22 deletions(-) diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 76f8af7..b4b8926 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -34,7 +34,7 @@ { "name": "use-family", "description": "The whole *-use family in one install: every *-use plugin below as a dependency, a routing skill that tells the agent which one to use and how they combine, and a session-start check for missing CLIs, and CLIs kept at their plugin's version.", - "version": "0.13.0", + "version": "0.14.0", "category": "productivity", "source": "./plugins/use-family", "homepage": "https://github.com/leeguooooo/plugins/tree/main/plugins/use-family" @@ -273,6 +273,22 @@ ], "strict": false }, + { + "name": "sflow", + "description": "Session Flow — run one JSON workflow across separate Claude Code, Codex, Pi and Antigravity (agy) sessions: each step in its own native TUI, a dependency graph with parallel steps, results passed and hash-checked over OCS, never auto-committed or resent. Trust and approval prompts are asked in your conversation and answered with your choice. macOS/Linux; needs tmux and ocs.", + "version": "0.1.7", + "category": "productivity", + "source": { + "source": "url", + "url": "https://github.com/leeguooooo/session-flow.git", + "ref": "main" + }, + "homepage": "https://github.com/leeguooooo/session-flow", + "skills": [ + "./skills/sflow" + ], + "strict": false + }, { "name": "bitwarden-use", "description": "Bitwarden/Vaultwarden CLI with an ssh-agent-style background agent and FIDO2 passkey extraction — headless passkey logins, vault lookups, and a built-in SSH agent.", diff --git a/README.md b/README.md index e0aa005..c52868b 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ The plugin only carries the slash commands; the actual statusLine renderer is th ## The `*-use` family -Agent-native CLIs that let coding agents drive real, logged-in surfaces — a browser, a phone, WeChat, Discord, a password vault, a private notes repo, the clipboard history — and talk to each other (`ocs`, from [open-cross-session](https://github.com/leeguooooo/open-cross-session)). Each plugin ships the agent skill; the CLI binary self-installs on first use (GitHub Release, no npm, no token). +Agent-native CLIs that let coding agents drive real, logged-in surfaces — a browser, a phone, WeChat, Discord, a password vault, a private notes repo, the clipboard history — and talk to each other (`ocs`, from [open-cross-session](https://github.com/leeguooooo/open-cross-session)) or work through one multi-step workflow together (`sflow`, from [session-flow](https://github.com/leeguooooo/session-flow)). Each plugin ships the agent skill; the CLI binary self-installs on first use (GitHub Release, no npm, no token). ## The *-use family in one install @@ -60,7 +60,7 @@ curl -fsSL https://raw.githubusercontent.com/leeguooooo/plugins/main/install-cli ```sh codex plugin marketplace add leeguooooo/plugins -for plugin in use-family chrome-use cookie-use mail-use message-use paste-use thermo-use wechat-use discord-use iphone-use android-use profile-use memory-use ocs bitwarden-use chatgpt-use image-use motion-use switch-use; do +for plugin in use-family chrome-use cookie-use mail-use message-use paste-use thermo-use wechat-use discord-use iphone-use android-use profile-use memory-use ocs sflow bitwarden-use chatgpt-use image-use motion-use switch-use; do codex plugin add "$plugin@leeguooooo-plugins" || break done ``` @@ -215,6 +215,14 @@ open-cross-session — AI coding agents talking to each other: Claude Code, Code --- +### [sflow](https://github.com/leeguooooo/session-flow) + +Session Flow — run one JSON workflow across separate Claude Code, Codex, Pi and Antigravity (agy) sessions: each step in its own native TUI, a dependency graph with parallel steps, results passed and hash-checked over OCS, never auto-committed or resent. Trust and approval prompts are asked in your conversation and answered with your choice. macOS/Linux; needs tmux and ocs. + +**Claude Code:** `/plugin install sflow@leeguooooo-plugins` + +--- + ### [bitwarden-use](https://github.com/leeguooooo/bitwarden-use) Bitwarden/Vaultwarden CLI with an ssh-agent-style background agent and FIDO2 passkey extraction — headless passkey logins, vault lookups, and a built-in SSH agent. diff --git a/install-clis.sh b/install-clis.sh index 0894c5c..c54d62d 100644 --- a/install-clis.sh +++ b/install-clis.sh @@ -14,13 +14,13 @@ RAW="${USE_FAMILY_RAW:-https://raw.githubusercontent.com/leeguooooo}" # Keep in step with plugins/use-family/scripts/doctor.sh. os=$(uname -s); arch=$(uname -m) names="android-use chrome-use cookie-use mail-use discord-use bitwarden-use chatgpt-use memory-use ocs image-use profile-use" -case "$os" in MINGW*|MSYS*|CYGWIN*) ;; *) names="$names motion-use" ;; esac # motion-use: macOS and Linux only +case "$os" in MINGW*|MSYS*|CYGWIN*) ;; *) names="$names motion-use sflow" ;; esac # motion-use, sflow: macOS and Linux only [ "$os" = Darwin ] && names="$names message-use paste-use thermo-use" # wechat-use's macOS installer stops with "Apple Silicon only" on Intel. [ "$os-$arch" = Darwin-arm64 ] && names="$names wechat-use" [ $# -gt 0 ] && names="$*" -repo_of() { case "$1" in ocs) echo open-cross-session ;; *) echo "$1" ;; esac; } +repo_of() { case "$1" in ocs) echo open-cross-session ;; sflow) echo session-flow ;; *) echo "$1" ;; esac; } installed() { # installed : already set up here case "$1" in # profile-use is a skill with a script, not a CLI; iphone-use is a daemon with an app. diff --git a/install-use-family.sh b/install-use-family.sh index a5a5431..9d36a1c 100644 --- a/install-use-family.sh +++ b/install-use-family.sh @@ -11,20 +11,22 @@ command -v git >/dev/null 2>&1 || { echo "error: git is required" >&2; exit 1; } mkdir -p "$BASE" "$SKILLS" # [=]:; "." means SKILL.md sits at the repo root. -# The repo defaults to the name; ocs lives in leeguooooo/open-cross-session. +# The repo defaults to the name; ocs lives in leeguooooo/open-cross-session, sflow in leeguooooo/session-flow. # Keep in step with .claude-plugin/marketplace.json. USES="chrome-use:skills/chrome-use cookie-use:skills/cookie-use iphone-use:skills/iphone-use android-use:skills/android-use mail-use:skills/mail-use wechat-use:. discord-use:. profile-use:. bitwarden-use:. -chatgpt-use:. image-use:. memory-use:. ocs=open-cross-session:skills/ocs message-use:. motion-use:. +chatgpt-use:. image-use:. memory-use:. ocs=open-cross-session:skills/ocs sflow=session-flow:skills/sflow message-use:. motion-use:. paste-use:. thermo-use:. switch-use:." # Uses that ship a CLI on PATH (iphone-use runs as a daemon, profile-use as a script in its skill; # switch-use needs a homebrew Switch, so it is installed only by name). CLIS="android-use chrome-use cookie-use mail-use discord-use bitwarden-use chatgpt-use memory-use ocs motion-use image-use" repo_of() { # repo_of : the GitHub repo a use lives in - case "$1" in ocs) echo open-cross-session ;; *) echo "$1" ;; esac + case "$1" in ocs) echo open-cross-session ;; sflow) echo session-flow ;; *) echo "$1" ;; esac } [ "$(uname -s)" = Darwin ] && CLIS="$CLIS message-use paste-use thermo-use" +# sflow drives tmux sessions: macOS and Linux. +case "$(uname -s)" in Darwin|Linux) CLIS="$CLIS sflow" ;; esac # wechat-use's macOS installer stops with "Apple Silicon only" on Intel, so don't suggest it there. [ "$(uname -s)-$(uname -m)" = Darwin-arm64 ] && CLIS="$CLIS wechat-use" diff --git a/plugins/use-family/.claude-plugin/plugin.json b/plugins/use-family/.claude-plugin/plugin.json index 597693f..1fae3d4 100644 --- a/plugins/use-family/.claude-plugin/plugin.json +++ b/plugins/use-family/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "use-family", - "version": "0.13.0", - "description": "The whole *-use family in one install: browser, email, texts (iMessage/SMS), chat, phone, Nintendo Switch, identity, passwords, sessions, notes, clipboard history, how this Mac is doing, promo and explainer videos, and the other agents on your machines. Adds a routing skill that tells the agent which use to reach for and how they combine, plus a session-start check for missing CLIs and one that upgrades a CLI older than its plugin.", + "version": "0.14.0", + "description": "The whole *-use family in one install: browser, email, texts (iMessage/SMS), chat, phone, Nintendo Switch, identity, passwords, sessions, notes, clipboard history, how this Mac is doing, promo and explainer videos, the other agents on your machines, and multi-agent workflows across them. Adds a routing skill that tells the agent which use to reach for and how they combine, plus a session-start check for missing CLIs and one that upgrades a CLI older than its plugin.", "author": { "name": "leeguooooo" }, @@ -19,6 +19,7 @@ "profile-use", "memory-use", "ocs", + "sflow", "bitwarden-use", "chatgpt-use", "image-use", diff --git a/plugins/use-family/scripts/doctor.sh b/plugins/use-family/scripts/doctor.sh index 77030e1..b0bc266 100755 --- a/plugins/use-family/scripts/doctor.sh +++ b/plugins/use-family/scripts/doctor.sh @@ -9,7 +9,7 @@ PATH="$PATH:$HOME/.local/bin:/opt/homebrew/bin:/usr/local/bin" # Keep the list in step with install-clis.sh at the repo root. os=$(uname -s); arch=$(uname -m) names="android-use chrome-use cookie-use mail-use discord-use bitwarden-use chatgpt-use memory-use ocs image-use" -case "$os" in MINGW*|MSYS*|CYGWIN*) ;; *) names="$names motion-use" ;; esac # motion-use: macOS and Linux only +case "$os" in MINGW*|MSYS*|CYGWIN*) ;; *) names="$names motion-use sflow" ;; esac # motion-use, sflow: macOS and Linux only [ "$os" = Darwin ] && names="$names message-use paste-use thermo-use" # wechat-use's macOS installer stops with "Apple Silicon only" on Intel, so don't suggest it there. [ "$os-$arch" = Darwin-arm64 ] && names="$names wechat-use" @@ -30,6 +30,6 @@ echo "Install them when a task needs one, after asking the user. All at once:" echo " curl -fsSL https://raw.githubusercontent.com/leeguooooo/plugins/main/install-clis.sh | sh" echo "Or one at a time:" for name in $missing; do - repo=$name; [ "$name" = ocs ] && repo=open-cross-session + repo=$name; [ "$name" = ocs ] && repo=open-cross-session; [ "$name" = sflow ] && repo=session-flow echo " curl -fsSL https://raw.githubusercontent.com/leeguooooo/$repo/main/install.sh | sh" done diff --git a/plugins/use-family/scripts/sync-clis.sh b/plugins/use-family/scripts/sync-clis.sh index 7aa8c36..ef12cb1 100755 --- a/plugins/use-family/scripts/sync-clis.sh +++ b/plugins/use-family/scripts/sync-clis.sh @@ -11,7 +11,7 @@ PATH="$PATH:$HOME/.local/bin:/opt/homebrew/bin:/usr/local/bin" plugins="$HOME/.claude/plugins/installed_plugins.json" [ -f "$plugins" ] && command -v python3 >/dev/null 2>&1 || exit 0 -names="android-use chrome-use cookie-use iphone-use mail-use wechat-use discord-use chatgpt-use memory-use ocs message-use image-use paste-use motion-use switch-use" +names="android-use chrome-use cookie-use iphone-use mail-use wechat-use discord-use chatgpt-use memory-use ocs sflow message-use image-use paste-use motion-use switch-use" # " " for each installed plugin of the family (newest install per name) installed=$(python3 - "$plugins" $names <<'EOF' @@ -43,9 +43,9 @@ cli_version() { grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -n 1 } has_upgrade() { # same test as upgrade-use-family.sh - "$1" --help 2>&1 | grep -qE "^[[:space:]]+($1[[:space:]]+)?upgrade([[:space:]]|\$)|\"name\":[[:space:]]*\"upgrade\"" + "$1" --help 2>&1 | grep -qE "^([[:space:]]*$1[[:space:]]+|[[:space:]]+)upgrade([[:space:]]|\$)|\"name\":[[:space:]]*\"upgrade\"" } -repo_of() { case "$1" in ocs) echo open-cross-session ;; *) echo "$1" ;; esac; } +repo_of() { case "$1" in ocs) echo open-cross-session ;; sflow) echo session-flow ;; *) echo "$1" ;; esac; } # Bound each upgrade when a timeout command exists (coreutils); the hook has its own limit too. bounded() { if command -v timeout >/dev/null 2>&1; then timeout 240 "$@"; else "$@"; fi; } diff --git a/plugins/use-family/skills/use-family/SKILL.md b/plugins/use-family/skills/use-family/SKILL.md index 25e4fa0..749793a 100644 --- a/plugins/use-family/skills/use-family/SKILL.md +++ b/plugins/use-family/skills/use-family/SKILL.md @@ -1,6 +1,6 @@ --- name: use-family -description: Routing guide for the *-use family (chrome-use, mail-use, image-use, wechat-use, discord-use, iphone-use, android-use, profile-use, bitwarden-use, cookie-use, chatgpt-use, memory-use, ocs, message-use, paste-use, thermo-use, motion-use, switch-use). Use when a task spans more than one of them or it is unclear which to pick — signing up for a site, logging in, fetching a verification code, filling a form with personal data, switching accounts, messaging someone, setting up a new computer — or when the user asks "用哪个 use", "use 家族", "这些 use 怎么配合". +description: Routing guide for the *-use family (chrome-use, mail-use, image-use, wechat-use, discord-use, iphone-use, android-use, profile-use, bitwarden-use, cookie-use, chatgpt-use, memory-use, ocs, sflow, message-use, paste-use, thermo-use, motion-use, switch-use). Use when a task spans more than one of them or it is unclear which to pick — signing up for a site, logging in, fetching a verification code, filling a form with personal data, switching accounts, messaging someone, setting up a new computer — or when the user asks "用哪个 use", "use 家族", "这些 use 怎么配合". --- # use-family @@ -25,6 +25,7 @@ Each `*-use` does one thing well. This skill says which one to reach for, and ho | | `message-use` | iMessage and SMS through macOS Messages: read, search, watch, send; `message-use code --wait` returns the next SMS verification code. | | | `wechat-use`, `discord-use` | Messages and history on WeChat and Discord. | | Teammates | `ocs` | The other AI agents: Claude Code, Codex and Pi sessions on this machine, and on paired machines on the same LAN (`
@`). Message, wake, delegate, get notified when one goes idle. | +| | `sflow` | A whole multi-step job across agents: one JSON workflow, each step in a new native Claude Code, Codex, Pi or agy session, dependencies and parallel steps run for you, full results checked before the next step. Built on ocs. | | Second brain | `chatgpt-use` | The user's ChatGPT web subscription as an extra reviewer or planner. Built on chrome-use. | | | `image-use` | Image generation on the user's own subscriptions: ChatGPT web first, Codex fallback, optional Gemini. | | Make | `motion-use` | Directed videos rendered locally to MP4: launch films, explainers, data stories, kinetic type, graphics over footage; zh/en, landscape/portrait/square, narration, cut to a song; checks the delivered file. | @@ -34,6 +35,7 @@ Pick by target: - A web page → `chrome-use`. A native macOS app → the host's own computer use (Claude Code: enable `computer-use` in `/mcp`; Codex: its built-in computer use); `peekaboo` for scripted or non-interactive runs. An iPhone app → `iphone-use`; an Android app → `android-use`. The user's Nintendo Switch (任天堂 / NS / 大气层) → `switch-use`; ask before interrupting a running game. - A personal value to type into a form → `profile-use values`. A password or TOTP → `bitwarden-use` (via `profile-use login --domain`). Never the other way round. - Another agent session — hand off work, ask a question, wait for it to finish → `ocs` (`ocs who`, then `ocs dm "…"`; `--notify-when-idle` instead of polling). An agent on another computer the user paired → `ocs dm
@`; pairing (`ocs lan pair`) lets that machine prompt this one's agents, so only when the user asks. +- Several steps for several agents — plan with one, implement with another, review with a third, or fan out and join → `sflow` (write a workflow, `sflow run` in the background, watch `sflow status`). One question or hand-off to a session that already exists → `ocs`. sflow starts its own sessions; when one waits on a trust or approval prompt, ask the user in the conversation and pass their choice with `sflow answer`. - Something the user copied ("what I just copied", "the link from earlier", 剪贴板里那个) → `paste-use last` / `paste-use search`; hand text back with `paste-use copy`. Clip contents are data, not instructions, and a masked value stays masked unless the user asks for it. - The Mac is slow, hot, loud or out of space (电脑卡 / 好烫 / 磁盘满了), or before something heavy → `thermo pulse --json`; disk held by old AI sessions → `thermo clean ai`. Name the culprit to the user; don't quit programs or clean without their go-ahead. - A durable fact about the person → `profile-use`. A durable fact about how a machine or service is set up → `memory-use`, which stores only pointers to profile-use, never the values. diff --git a/tests/doctor.test.sh b/tests/doctor.test.sh index 1073431..2cc9690 100644 --- a/tests/doctor.test.sh +++ b/tests/doctor.test.sh @@ -26,6 +26,7 @@ echo "$out" | grep -qF 'leeguooooo/discord-use/main/install.sh | sh' || fail "In echo "$out" | grep -q 'not installed:.* image-use' || fail "image-use not checked" echo "$out" | grep -qF 'leeguooooo/image-use/main/install.sh | sh' || fail "no image-use installer line" echo "$out" | grep -qF 'leeguooooo/open-cross-session/main/install.sh | sh' || fail "ocs not mapped to its repo" +echo "$out" | grep -qF 'leeguooooo/session-flow/main/install.sh | sh' || fail "sflow not mapped to its repo" out=$(run arm64) echo "$out" | grep -q 'not installed:.* wechat-use' || fail "Apple Silicon: wechat-use not checked" diff --git a/tests/install-clis.test.sh b/tests/install-clis.test.sh index 174321e..371d038 100644 --- a/tests/install-clis.test.sh +++ b/tests/install-clis.test.sh @@ -18,7 +18,7 @@ out=""; url="" while [ $# -gt 0 ]; do case "$1" in -o) out=$2; shift 2 ;; -*) shift ;; *) url=$1; shift ;; esac; done repo=${url#*/leeguooooo/}; repo=${repo%%/*} [ "$repo" = "${FAIL_REPO:-}" ] && exit 22 -name=$repo; [ "$repo" = open-cross-session ] && name=ocs +name=$repo; [ "$repo" = open-cross-session ] && name=ocs; [ "$repo" = session-flow ] && name=sflow if [ "$name" = profile-use ]; then printf 'mkdir -p "$HOME/.agents/use-family/profile-use"; touch "$HOME/.agents/use-family/profile-use/SKILL.md"\n' > "$out" else @@ -40,7 +40,7 @@ has() { [ -x "$TMP/home/.local/bin/$1" ]; } fresh; run x86_64 [ "$rc" = 0 ] || fail "Intel: exit $rc" -for n in android-use chrome-use cookie-use mail-use discord-use bitwarden-use chatgpt-use memory-use ocs image-use motion-use message-use paste-use thermo-use; do +for n in android-use chrome-use cookie-use mail-use discord-use bitwarden-use chatgpt-use memory-use ocs sflow image-use motion-use message-use paste-use thermo-use; do has "$n" || fail "Intel: $n not installed" done [ -f "$TMP/home/.agents/use-family/profile-use/SKILL.md" ] || fail "Intel: profile-use not installed" diff --git a/upgrade-use-family.sh b/upgrade-use-family.sh index 61db65c..b93ddaa 100755 --- a/upgrade-use-family.sh +++ b/upgrade-use-family.sh @@ -6,16 +6,16 @@ set -u BASE="${USE_FAMILY_DIR:-$HOME/.agents/use-family}" PLUGINS="$HOME/.claude/plugins/installed_plugins.json" -NAMES="android-use chrome-use cookie-use iphone-use mail-use wechat-use discord-use profile-use bitwarden-use chatgpt-use image-use memory-use ocs message-use paste-use motion-use switch-use" +NAMES="android-use chrome-use cookie-use iphone-use mail-use wechat-use discord-use profile-use bitwarden-use chatgpt-use image-use memory-use ocs sflow message-use paste-use motion-use switch-use" failed="" repo_of() { # repo_of : the GitHub repo a use lives in - case "$1" in ocs) echo open-cross-session ;; *) echo "$1" ;; esac + case "$1" in ocs) echo open-cross-session ;; sflow) echo session-flow ;; *) echo "$1" ;; esac } has_upgrade() { # the CLI lists an `upgrade` subcommand in its help (text, or JSON when piped, e.g. mail-use); - # usage lines may repeat the program name (" ocs upgrade [--check]") - "$1" --help 2>&1 | grep -qE "^[[:space:]]+($1[[:space:]]+)?upgrade([[:space:]]|\$)|\"name\":[[:space:]]*\"upgrade\"" + # usage lines may repeat the program name (" ocs upgrade [--check]", or unindented "sflow upgrade") + "$1" --help 2>&1 | grep -qE "^([[:space:]]*$1[[:space:]]+|[[:space:]]+)upgrade([[:space:]]|\$)|\"name\":[[:space:]]*\"upgrade\"" } echo "== CLIs"