Give Flow one small, language-agnostic way to execute CLIs that live outside the Flow Rust repo.
The first target is codex-session-browser, but the contract is intentionally
generic so the same bridge can later execute tools under:
~/code/lang/go/cli/*~/code/lang/rust/cli/*
Flow should discover external tools by scanning fixed roots for a manifest
named flow-tool.toml.
Initial roots:
~/code/lang/go/cli/*/flow-tool.toml~/code/lang/rust/cli/*/flow-tool.toml
The manifest's parent directory is the tool source_root.
Example:
version = 1
id = "codex-session-browser"
language = "go"
binary_name = "codex-session-browser"
description = "Browse Codex sessions for a repo and print the selected session ID."
[exec]
run = ["go", "run", "."]version- integer schema version
- v1 requires
1
id- stable Flow-facing tool identifier
- must be unique across discovered manifests
language- initial values:
go,rust
- initial values:
binary_name- preferred installed binary name if Flow later adds build/install support
[exec].run- argv prefix Flow executes in
source_root - Flow appends caller-provided args to this array
- argv prefix Flow executes in
description- human-readable summary for help or debugging
[exec].build- optional argv prefix for future install/build support
[exec].env- optional environment overrides for the tool process
For v1, Flow only needs this behavior:
- discover the manifest
- set
source_rootto the manifest parent directory - execute
[exec].run + passthrough_argsinsource_root - capture stdout, stderr, and exit status
- let the calling Flow command interpret stdout
This keeps the bridge generic. The bridge does not need to understand what the tool prints.
The Flow command that invokes the external tool owns the meaning of stdout.
Examples:
f ai codex browseexpects stdout to be the selected Codex session ID- a future tool might print JSON to stdout instead
- another tool may be fully interactive and only use exit status
The bridge should not special-case those semantics.
Go:
version = 1
id = "codex-session-browser"
language = "go"
binary_name = "codex-session-browser"
[exec]
run = ["go", "run", "."]Rust:
version = 1
id = "ctx"
language = "rust"
binary_name = "ctx"
[exec]
run = ["cargo", "run", "--quiet", "--"]- no plugin marketplace
- no dynamic remote installation
- no per-tool permission model
- no schema beyond local manifest discovery and argv execution
- no requirement that Flow build binaries before first use
The first tool using this contract is:
- source:
~/code/lang/go/cli/codex-session-browser - manifest:
~/code/lang/go/cli/codex-session-browser/flow-tool.toml - Flow caller:
f ai codex browse