## File: README.md

# [flow](https://myflow.sh)

> Everything you need to move your project faster

## Install

Install the latest release (macOS/Linux):

```sh
curl -fsSL https://myflow.sh/install.sh | sh
```

Then run:

```sh
~/.flow/bin/f --version
~/.flow/bin/f doctor
```

If `f` is not found by name immediately, open a new shell (`exec zsh -l` on zsh).

The installer verifies SHA-256 checksums when available. If you are installing a legacy release
that doesn't ship `checksums.txt`, it will warn and continue (GitHub download only). To bypass
verification explicitly (not recommended), set `FLOW_INSTALL_INSECURE=1`.

## Upgrade

Upgrade to the latest release:

```sh
f upgrade
```

Upgrade to the latest canary build:

```sh
f upgrade --canary
```

Switch back to stable:

```sh
f upgrade --stable
```

If you fork Flow (or publish releases under a different repo), set:

- `FLOW_UPGRADE_REPO=owner/repo`
- `FLOW_GITHUB_TOKEN` (or `GITHUB_TOKEN` / `GH_TOKEN`) to avoid GitHub API rate limits

If you are upgrading to a very old tag that doesn't ship `checksums.txt`, you can force bypassing
checksum verification with `FLOW_UPGRADE_INSECURE=1` (not recommended).

## Build From Source

Clone Flow, hydrate the pinned vendor snapshot, and install an optimized local build:

```sh
git clone https://github.com/nikivdev/flow.git
cd flow
./scripts/vendor/vendor-repo.sh hydrate
FLOW_PROFILE=release ./scripts/deploy.sh
~/bin/f --version
```

- `./scripts/vendor/vendor-repo.sh hydrate` reuses `.vendor/flow-vendor` if it already exists.
- If `.vendor/flow-vendor` is missing, it clones the pinned vendor repo from [`vendor.lock.toml`](vendor.lock.toml) and materializes `lib/vendor/*` from that exact commit.
- The pinned vendor repo is public: `https://github.com/nikivdev/flow-vendor`
- `FLOW_PROFILE=release ./scripts/deploy.sh` builds the optimized release binary and installs `f` / `flow` / `lin` into `~/bin` (and symlinks into `~/.local/bin` if that directory exists).

If you want to populate the vendor checkout yourself first, that works too:

```sh
git clone https://github.com/nikivdev/flow-vendor.git .vendor/flow-vendor
./scripts/vendor/vendor-repo.sh hydrate
```

## Dev Fast

Typical local loop:

```sh
f setup
f test
f deploy
```

- `f setup` checks the workspace and toolchain.
- `f test` runs the test suite.
- `f deploy` builds and installs the local CLI into your path.

If you want to inspect tasks first:

```sh
f tasks list
```

## Features

To see the current CLI surface:

```sh
f --help
```

For deeper docs, read [`docs/`](docs).

## Supported Platforms

Release artifacts are built for:

- macOS: `arm64`, `x86_64`
- Linux (glibc): `arm64`, `x86_64`

## Contributing

Use Flow and AI. For the full command surface, run `f --help`. For project docs and workflows, read [`docs/`](docs).

[](https://go.nikiv.dev/discord) [](https://x.com/nikivdev) [](https://nikiv.dev)

---

## File: Readme.md

# [flow](https://myflow.sh)

> Everything you need to move your project faster

## Install

Install the latest release (macOS/Linux):

```sh
curl -fsSL https://myflow.sh/install.sh | sh
```

Then run:

```sh
~/.flow/bin/f --version
~/.flow/bin/f doctor
```

If `f` is not found by name immediately, open a new shell (`exec zsh -l` on zsh).

The installer verifies SHA-256 checksums when available. If you are installing a legacy release
that doesn't ship `checksums.txt`, it will warn and continue (GitHub download only). To bypass
verification explicitly (not recommended), set `FLOW_INSTALL_INSECURE=1`.

## Upgrade

Upgrade to the latest release:

```sh
f upgrade
```

Upgrade to the latest canary build:

```sh
f upgrade --canary
```

Switch back to stable:

```sh
f upgrade --stable
```

If you fork Flow (or publish releases under a different repo), set:

- `FLOW_UPGRADE_REPO=owner/repo`
- `FLOW_GITHUB_TOKEN` (or `GITHUB_TOKEN` / `GH_TOKEN`) to avoid GitHub API rate limits

If you are upgrading to a very old tag that doesn't ship `checksums.txt`, you can force bypassing
checksum verification with `FLOW_UPGRADE_INSECURE=1` (not recommended).

## Build From Source

Clone Flow, hydrate the pinned vendor snapshot, and install an optimized local build:

```sh
git clone https://github.com/nikivdev/flow.git
cd flow
./scripts/vendor/vendor-repo.sh hydrate
FLOW_PROFILE=release ./scripts/deploy.sh
~/bin/f --version
```

- `./scripts/vendor/vendor-repo.sh hydrate` reuses `.vendor/flow-vendor` if it already exists.
- If `.vendor/flow-vendor` is missing, it clones the pinned vendor repo from [`vendor.lock.toml`](vendor.lock.toml) and materializes `lib/vendor/*` from that exact commit.
- The pinned vendor repo is public: `https://github.com/nikivdev/flow-vendor`
- `FLOW_PROFILE=release ./scripts/deploy.sh` builds the optimized release binary and installs `f` / `flow` / `lin` into `~/bin` (and symlinks into `~/.local/bin` if that directory exists).

If you want to populate the vendor checkout yourself first, that works too:

```sh
git clone https://github.com/nikivdev/flow-vendor.git .vendor/flow-vendor
./scripts/vendor/vendor-repo.sh hydrate
```

## Dev Fast

Typical local loop:

```sh
f setup
f test
f deploy
```

- `f setup` checks the workspace and toolchain.
- `f test` runs the test suite.
- `f deploy` builds and installs the local CLI into your path.

If you want to inspect tasks first:

```sh
f tasks list
```

## Features

To see the current CLI surface:

```sh
f --help
```

For deeper docs, read [`docs/`](docs).

## Supported Platforms

Release artifacts are built for:

- macOS: `arm64`, `x86_64`
- Linux (glibc): `arm64`, `x86_64`

## Contributing

Use Flow and AI. For the full command surface, run `f --help`. For project docs and workflows, read [`docs/`](docs).

[](https://go.nikiv.dev/discord) [](https://x.com/nikivdev) [](https://nikiv.dev)

---

## File: readme.md

# [flow](https://myflow.sh)

> Everything you need to move your project faster

## Install

Install the latest release (macOS/Linux):

```sh
curl -fsSL https://myflow.sh/install.sh | sh
```

Then run:

```sh
~/.flow/bin/f --version
~/.flow/bin/f doctor
```

If `f` is not found by name immediately, open a new shell (`exec zsh -l` on zsh).

The installer verifies SHA-256 checksums when available. If you are installing a legacy release
that doesn't ship `checksums.txt`, it will warn and continue (GitHub download only). To bypass
verification explicitly (not recommended), set `FLOW_INSTALL_INSECURE=1`.

## Upgrade

Upgrade to the latest release:

```sh
f upgrade
```

Upgrade to the latest canary build:

```sh
f upgrade --canary
```

Switch back to stable:

```sh
f upgrade --stable
```

If you fork Flow (or publish releases under a different repo), set:

- `FLOW_UPGRADE_REPO=owner/repo`
- `FLOW_GITHUB_TOKEN` (or `GITHUB_TOKEN` / `GH_TOKEN`) to avoid GitHub API rate limits

If you are upgrading to a very old tag that doesn't ship `checksums.txt`, you can force bypassing
checksum verification with `FLOW_UPGRADE_INSECURE=1` (not recommended).

## Build From Source

Clone Flow, hydrate the pinned vendor snapshot, and install an optimized local build:

```sh
git clone https://github.com/nikivdev/flow.git
cd flow
./scripts/vendor/vendor-repo.sh hydrate
FLOW_PROFILE=release ./scripts/deploy.sh
~/bin/f --version
```

- `./scripts/vendor/vendor-repo.sh hydrate` reuses `.vendor/flow-vendor` if it already exists.
- If `.vendor/flow-vendor` is missing, it clones the pinned vendor repo from [`vendor.lock.toml`](vendor.lock.toml) and materializes `lib/vendor/*` from that exact commit.
- The pinned vendor repo is public: `https://github.com/nikivdev/flow-vendor`
- `FLOW_PROFILE=release ./scripts/deploy.sh` builds the optimized release binary and installs `f` / `flow` / `lin` into `~/bin` (and symlinks into `~/.local/bin` if that directory exists).

If you want to populate the vendor checkout yourself first, that works too:

```sh
git clone https://github.com/nikivdev/flow-vendor.git .vendor/flow-vendor
./scripts/vendor/vendor-repo.sh hydrate
```

## Dev Fast

Typical local loop:

```sh
f setup
f test
f deploy
```

- `f setup` checks the workspace and toolchain.
- `f test` runs the test suite.
- `f deploy` builds and installs the local CLI into your path.

If you want to inspect tasks first:

```sh
f tasks list
```

## Features

To see the current CLI surface:

```sh
f --help
```

For deeper docs, read [`docs/`](docs).

## Supported Platforms

Release artifacts are built for:

- macOS: `arm64`, `x86_64`
- Linux (glibc): `arm64`, `x86_64`

## Contributing

Use Flow and AI. For the full command surface, run `f --help`. For project docs and workflows, read [`docs/`](docs).

[](https://go.nikiv.dev/discord) [](https://x.com/nikivdev) [](https://nikiv.dev)

---

## File: docs/bench/moonbit-rust-ffi-boundary.md

# MoonBit <-> Rust FFI Boundary Benchmark

This benchmark measures raw call overhead between MoonBit (native C backend) and Rust host functions.

## Scope

Measured:
- Rust local math baseline (`rust_inline_add`, `rust_fn_add`)
- Rust calling exported C ABI functions (`rust_extern_add`, `rust_extern_noop`)
- MoonBit calling Rust-exported C ABI (`moon_ffi_add`, `moon_ffi_noop`)

Not measured:
- app-level task execution
- process startup/teardown
- end-to-end Flow command latency

## Where the code lives

- `bench/ffi_host_boundary/src/lib.rs`
- `bench/ffi_host_boundary/src/bin/rust_boundary_bench.rs`
- `bench/moon_ffi_boundary/main.mbt`
- `bench/moon_ffi_boundary/moon.pkg.template.json`
- `scripts/bench-moonbit-rust-ffi.py`
- Flow task: `bench-ffi-boundary` in `flow.toml`

## Run commands

Direct script:

```bash
cd ~/code/flow
python3 scripts/bench-moonbit-rust-ffi.py --iters 10000000 --json-out /tmp/ffi.json
```

With machine-local tuning flags:

```bash
cd ~/code/flow
python3 scripts/bench-moonbit-rust-ffi.py --iters 10000000 --native-opt --json-out /tmp/ffi_native.json
```

Via Flow:

```bash
cd ~/code/flow
f bench-ffi-boundary --iters 10000000 --json-out /tmp/ffi_flow.json
```

## Latest measured numbers (this machine)

Method: 3 rounds each, 10M iterations/round, median ns/op.

| metric | baseline | native-opt | tuned/base |
|---|---:|---:|---:|
| rust_extern_add | 2.7683 | 2.8291 | 1.022x |
| rust_extern_noop | 2.7880 | 2.9140 | 1.045x |
| moon_ffi_add | 0.9005 | 1.1075 | 1.230x |
| moon_ffi_noop | 0.8576 | 0.8462 | 0.987x |

Interpretation:
- Boundary overhead is single-digit nanoseconds.
- On this machine, `--native-opt` did not consistently improve results; it was mixed/slightly worse for most metrics.
- You must benchmark on your target machine before locking optimization flags.

## Important measurement caveat

`moon_add` (pure MoonBit loop) can be optimized away by the compiler and report `0 ns`. Treat it as non-authoritative for boundary decisions.

Use FFI metrics (`moon_ffi_*`, `rust_extern_*`) as the primary signal.

## Optimizations implemented

1. Exported host functions stripped to minimal arithmetic (removed internal `black_box`).
2. Rust FFI functions marked `#[inline(never)]` to avoid accidental inlining in host-side tests.
3. Rust bench crate release profile tightened:
   - `lto = "fat"`
   - `codegen-units = 1`
   - `panic = "abort"`
   - `strip = true`
4. Moon native flags are configurable via template placeholder:
   - `cc-flags` in `moon.pkg.template.json`
5. Benchmark script supports `--native-opt`:
   - Rust: `RUSTFLAGS=-C target-cpu=native`
   - Moon native: `-O3 -march=native -mtune=native`

## Ideas borrowed from Moon toolchain

From `~/repos/moonbitlang/moon`:
- `Cargo.toml` uses explicit release profile controls (`lto`, `codegen-units`, `strip`) for predictable build/runtime tradeoffs.
- Native pipeline exposes per-package `cc-flags` / `cc-link-flags` (schema in `crates/moonbuild/template/pkg.schema.json`).
- TCC-run mode exists to speed dev-time run loops, not runtime performance; custom native flags disable that fast dev path.

Practical implication:
- For runtime benchmarks, tune native flags carefully and measure.
- For developer iteration speed, avoid unnecessary custom flags when tcc-run is beneficial.

## Decision guidance: should Rust core move to MoonBit for speed?

Based on these numbers: no, not for boundary speed alone.

Reason:
- Boundary is already near-zero cost (sub-3ns on this host).
- Any wins from migration will mostly come from architecture choices (fewer crossings, coarser APIs), not language-switch micro-optimizations.

Move code to MoonBit for:
- faster iteration/modeling
- portability or generation benefits
- maintainability

Keep in Rust when:
- syscall-heavy paths
- mature unsafe/perf-critical internals already stable

## Next benchmark to add (recommended)

Add a coarse-grained benchmark for real task payload crossing:
- one boundary call carrying a packed command
- compare against N tiny calls
- report payload sizes and p50/p95

That will better predict real Flow task runtime behavior than arithmetic no-op microbenchmarks.

---

## File: docs/bench/readme.md

# Bench Docs

- `moonbit-rust-ffi-boundary.md`: raw MoonBit <-> Rust boundary benchmark, commands, results, and optimization guidance.
- `cli-startup.md`: repeatable benchmark for Flow CLI startup and cheap read-only command latency.

---

## File: docs/commands/ai.md

# f ai

Manage Claude Code, Codex, and Cursor sessions for the current project.

Flow reads local session stores, filters by current project path, and gives you one interface for list/search/resume/copy/save.
When you need to reopen a repo's session from another working directory, use `--path ` on `resume` or provider-specific `continue`.
Cursor transcripts are supported for reading only.

Architecture note:

- for the underlying transport split between wrapped Codex CLI, `jd`, and `codex app-server`, see `docs/codex-interface.md`

## Quick Start

```bash
# Fuzzy-pick a recent session (Claude + Codex + Cursor)
f ai

# Provider-specific list/read
f ai claude list
f ai codex list
f ai codex sessions
f ai codex sessions --path ~/repos/mark3labs/kit
f ai cursor list
f codex resolve "latest"
f codex resolve "https://linear.app/.../project/.../overview" --json
f codex open "continue the deploy work"
f codex agent list
f codex agent show commit
f ai claude resume <session-id-or-name>
f ai codex resume <session-id-or-name>
f ai codex resume --path ~/work/example-project
f ai codex continue --path ~/work/example-project
f ai codex find --path ~/repos/openai/codex "where does codex store"
f ai codex find --all-history --path ~/repos/openai/codex "older migration plan"
f ai codex find --recent-days 30 --path ~/repos/openai/codex "thread/read"
f ai codex find --json --limit 5 --path ~/repos/openai/codex "thread/read"
f codex connect --path ~/repos/openai/codex --exact-cwd --json "app-server"
f codex connect --all-history --path ~/repos/openai/codex "old designer cutover"
f ai cursor context - /path/to/repo 3
f cursor copy

# Save a memorable alias for a session
f ai save reclaim-fix --id a38cf8bf-f4e2-4308-8b27-0254f89c4385
```

## Session Sources

- Claude: `~/.claude/projects//*.jsonl`
- Codex: `~/.codex/sessions/**/*.jsonl` (Flow matches by `session_meta.cwd`)
- Cursor: `~/.cursor/projects//agent-transcripts/<session-id>/<session-id>.jsonl`
- Saved aliases: `.ai/sessions/claude/index.json` in your repo

## Resume Behavior (Important)

### TTY requirement

Resume is interactive by design.

- `f ai claude resume ...` requires a terminal TTY.
- `f ai codex resume ...` requires a terminal TTY.
- In non-interactive shells, Flow exits with a clear error and non-zero status.
- Cursor does not currently expose a Flow resume/continue path; use `list`, `copy`, or `context`.

### Claude exact-ID behavior

If you pass an explicit session (`name`, `id`, or `id-prefix`), Flow is strict:

- it attempts `claude --resume `
- if Claude cannot open that exact session, Flow fails
- Flow does **not** auto-fallback to `--continue` for explicit sessions (prevents opening the wrong conversation)

### Claude no-arg behavior

For `f ai claude resume` with no argument:

- Flow picks most recent Claude session for this project
- if that resume fails, Flow may fallback to `claude --continue` in the same cwd (TTY only)

### Codex behavior

For Codex, Flow runs:

```bash
codex resume  --dangerously-bypass-approvals-and-sandbox
```

No fallback is applied on resume failure; Flow returns non-zero.

### Codex open and resolve

Use `open` when you want one Codex entrypoint that stays conservative about context:

```bash
f codex open
f codex open "continue the deploy work"
f codex open "resume latest"
f codex open --path ~/work/example-project "what was I doing here"
f codex resolve "https://linear.app/example-workspace/project/example-project-v1-1234567890ab/overview" --json
f codex doctor --path ~/work/example-project
```

Behavior:

- no query: start a fresh Codex session in the target repo
- explicit session lookup queries like `latest`, `resume session`, ordinals, or session IDs: resume the matching Codex session
- explicit recovery prompts like `what was I doing` or `continue the ... work`: build a compact recovery handoff and start a new session
- matching reference resolvers: inject only compact resolver output, then append the user request
- otherwise: start a new session with the raw query and no extra wrapper text

This keeps prompt cost flat unless Flow has a strong reason to recover or unroll context.
Use `f codex doctor` to confirm whether wrapper transport, runtime skills, and context budgets are actually active for the current repo.

### Codex connect and find

`f codex connect` and `f ai codex find` now use a Flow-managed local session-search index before
falling back to direct SQLite/transcript scans. The index is repo-scoped at query time, rebuilt
from the Codex state DB when needed, and keeps transcript snippets for better recall on natural
language queries.

By default, search now prefers sessions from roughly the last 7 days for faster and more accurate
ranking on active work, then automatically widens back to the full session history when the recent
window looks weak or sparse.

Useful commands:

```bash
f codex connect --path ~/repos/openai/codex --exact-cwd "app-server"
f codex connect --path ~/repos/openai/codex --exact-cwd --json "thread/read"
f codex connect --all-history --path ~/repos/openai/codex "old migration plan"
f ai codex find --path ~/repos/openai/codex "where does codex store"
f ai codex find --recent-days 30 --path ~/repos/openai/codex "thread/read"
f ai codex find --json --limit 5 --path ~/repos/openai/codex "where does codex store"
```

Behavior:

- `connect` stays the interactive handoff path and returns the exact session match
- `connect --json` prints the selected session instead of attaching
- `find` still resumes the top hit
- `find --json` is read-only and prints ranked candidates for inspection/eval work
- by default both commands prefer the last 7 days first, then widen if the recent window is weak
- use `--recent-days <N>` to widen the preferred recent window without fully disabling recency bias
- use `--all-history` to search the full history immediately
- if confidence is weak or the index misses, Flow still falls back to the older metadata and transcript paths instead of silently opening an arbitrary session

### Codex sessions after a crash or restart

If your Mac restarts and you lose the live Codex terminals, use:

```bash
f ai codex sessions
f ai codex sessions --path ~/repos/mark3labs/kit
```

Behavior:

- lists recent Codex sessions for the current path
- sorts by the last message timestamp descending
- shows the stable session id plus a preview of the latest message
- the numeric index matches `continue`, so you can reopen quickly

If you want to read or hand off a session instead of reopening it, use the native session bridge in Codex chat:

```text
see codex in ~/repos/mark3labs/kit
see 019cd046 codex session
read 019cd046 codex session deeply
```

Examples:

```bash
f ai codex continue 1 --path ~/repos/mark3labs/kit
f ai codex continue 019cd046 --path ~/repos/mark3labs/kit
f ai codex sessions --path ~/repos/mark3labs/kit --json
```

### Optional `flow.toml` resolver config

You can teach `f codex open` and `f codex resolve` to unroll repo-specific references:

```toml
[codex]
auto_resolve_references = true
prompt_context_budget_chars = 900
max_resolved_references = 1
sync_workflow_command = "./scripts/sync-safe"

[[codex.reference_resolver]]
name = "linear"
match = ["https://linear.app/*/issue/*", "https://linear.app/*/project/*"]
command = "my-linear-tool inspect {{ref}} --json"
inject_as = "linear"
```

Notes:

- configure this in repo `flow.toml` or global `~/.config/flow/flow.toml`
- `{{ref}}`, `{{query}}`, and `{{cwd}}` are available in resolver commands
- built-in Linear URL parsing works even without a custom resolver
- resolver output is compacted before prompt injection
- `prompt_context_budget_chars` hard-caps injected context before your request is appended
- `max_resolved_references` prevents broad unrolling from bloating one turn
- `sync_workflow_command` lets plain `sync branch` route into a repo-specific safe sync command instead of improvised Git/JJ steps

### Optional runtime skill transport

Flow can also materialize tiny per-launch runtime skills for current upstream Codex without forking Codex.

Enable it globally with:

```bash
f codex enable-global --full
f codex doctor --path ~/docs --assert-runtime --assert-schedule
```

Or configure it manually with:

```toml
[codex]
runtime_skills = true

[options]
codex_bin = "~/code/flow/scripts/codex-flow-wrapper"
```

For the `~/code/flow` repo specifically, the intended in-repo shape is:

```toml
[options]
codex_bin = "~/code/flow/scripts/codex-flow-wrapper"

[codex]
runtime_skills = true
auto_resolve_references = true
prompt_context_budget_chars = 1200
max_resolved_references = 2

[[codex.skill_source]]
name = "run-control-plane"
path = "~/run"
enabled = true
```

That keeps a fresh checkout Codex-first even before machine-local setup is remembered.

Current first-slice behavior:

- `f codex open "write plan"` can attach a tiny plan-writing runtime skill
- the runtime skill is exposed only for the launched Codex process
- Flow keeps the generated runtime state under `~/.config/flow/codex/runtime`

Inspect or clear runtime state:

```bash
f codex runtime show
f codex runtime clear
f codex log status
f codex log sync --limit 400
f codex memory status
f codex memory query --path ~/code/flow "codex control plane runtime skills"
f codex memory recent --path ~/docs
f codex doctor
```

Assertive health checks:

```bash
f codex doctor --path ~/docs --assert-runtime
f codex doctor --path ~/docs --assert-schedule
f codex doctor --path ~/docs --assert-learning
f codex doctor --path ~/docs --assert-autonomous
```

`--assert-learning` is intentionally strict: it fails until Flow has real
logged events, grounded outcome samples, and a non-empty scorecard for that
target.

Built-in plan writer:

```bash
cat <<'EOF' | f codex runtime write-plan --title "Example Plan"
# Example Plan

- item
EOF
```

By default this writes to today's `~/docs/plan/<day-of-month>/` bucket, for
example `~/docs/plan/23/` on the 23rd day of the month.

Completed `j` sessions are also mirrored automatically into `~/log/.ai/docs/session-changes/`
through `jd`, so durable home-log notes exist even when a repo-local `.ai/docs/`
promotion never happens.

### Run-owned agent bridge

Flow can execute run-owned Codex agents directly without copying their specs or
prompts into `~/code/flow`.

Useful commands:

```bash
f codex agent list
f codex agent list --json
f codex agent show commit
f codex agent run planner --path ~/code/flow "make a 3 phase rollout plan"
f codex agent run commit --path ~/repos/openai/codex "review the current diff and draft a safe commit"
f codex agent run planner --json --path ~/code/flow "reply with exactly: ok"
```

Behavior:

- Flow bridges into `~/run/scripts/agent-router.sh`
- the run-owned agent still executes through its own spec/runtime path in `~/run`
- `--path` controls the repo/worktree cwd used for the agent run
- `run` returns the agent's final output plus any durable artifact/trace paths
- `f codex doctor --path <repo>` reports whether the run-agent bridge is ready

Repo-local readiness check:

```bash
f codex doctor --path ~/code/flow --assert-runtime --assert-schedule
f codex skill-source list --path ~/code/flow
f codex agent list
```

### Skill eval and background refresh

Flow can learn which runtime skills are actually worth injecting from local
Codex usage history without replaying Codex in the hot path.

Useful commands:

```bash
f codex eval --path ~/work/example-project
f codex memory sync --limit 400
f codex memory recent --path ~/work/example-project --limit 12
f codex skill-eval show --path ~/work/example-project
f codex skill-eval run --path ~/work/example-project
f codex skill-eval cron --limit 400 --max-targets 12 --within-hours 168
f codex telemetry status
f codex telemetry flush --limit 200
f codex trace status
f codex trace current-session --json
f codex trace inspect  --json
f codex project-ai show --path ~/work/example-project --json
f codex project-ai recent --limit 12 --json
f codex skill-source list --path ~/work/example-project
f codex skill-source sync --path ~/work/example-project --skill find-skills
f codex agent list
f codex agent run planner --path ~/work/example-project "summarize the next rollout slice"
```

The Codex memory mirror:

- stores durable indexed memory under the Jazz2 root (`~/.jazz2/...` or `~/repos/garden-co/jazz2/.jazz2/...`)
- mirrors Flow’s route/outcome history into SQLite with WAL enabled
- extracts compact repo/code facts from repo capsules (summary, commands, important paths, docs hints)
- adds bounded live code-path retrieval for explicit repo references, so prompts like `see ~/code/flow ...` can inject likely files such as `src/ai.rs` or `docs/...` without dumping raw source
- indexes durable repo entrypoints and extracted symbols under the same Jazz2-rooted memory store, then supplements them with live symbol extraction from the top-ranked code files during `memory query` / `codex resolve`
- adds tiny symbol snippets for the top code hits, so coding prompts can carry actual struct/function shape without inlining whole files
- biases retrieval by intent: implementation/file-edit prompts prefer symbols, snippets, and `src/...` paths; summary/docs prompts prefer doc headings and docs paths
- stays best-effort so failed memory writes do not block normal Codex coding turns

The project-ai manifest:

- gives `jd` a bounded metadata view of repo-local `.ai/` scaffolding
- records counts and latest paths for skills, docs, reviews, tasks, and todos
- keeps default context fill minimal by exposing only compact hints, not raw content
- tracks query counts and recent repo usage so you can see whether the feature is actually being used
- is refreshed again by `f codex skill-eval cron`, so the mirror heals even if a hot-path write is skipped
- is queried automatically for explicit repo references during `f codex open` / `f codex resolve`

What `cron` does:

- scans only recent logged Flow Codex events
- syncs recent skill-eval logs into the Jazz2-backed memory mirror
- skips missing/moved repo paths
- rebuilds scorecards for a bounded number of recent repos
- never launches Codex or replays network work in the background

For your use case, this keeps learning cheap and safe enough to run regularly.

### Trace inspection for Flow-managed Codex sessions

Flow now assigns a trace envelope to all Flow-managed Codex launches, not just
special workflows like `check <github-pr-url>`.

That means sessions started or resumed through:

```bash
j ...
k <session-id>
f codex open ...
f codex resume ...
f codex continue ...
```

carry `FLOW_TRACE_*` env vars and emit at least one compact Flow telemetry
event, so the session becomes remotely inspectable.

Useful commands:

```bash
f codex trace status
f codex trace current-session --json
f codex trace inspect  --json
```

Behavior:

- `trace status` checks whether Maple MCP reads are configured and reachable
- `trace current-session` reads the active `FLOW_TRACE_ID` from the current
  Flow-managed Codex session, flushes recent Flow telemetry once, then attempts
  a remote trace read
- if Maple reads are partially configured but tenant access is still blocked,
  Flow returns the current trace metadata plus `readError` instead of failing
  without context

This keeps the workflow autonomous from inside Codex itself: once the session
was started through Flow, you can inspect the current trace without manually
copying ids.

`f codex eval --path ...` is the joined operator report:

- current runtime/doctor state
- recent route mix and context cost
- grounded skill scorecard highlights
- concrete “what to improve next” recommendations
- commands to deepen or fix the current state

If `jd` is running, it also keeps recent completion reconciliation warm and
now does a bounded background scorecard refresh, so the eval report does not go
stale as quickly between manual runs.

If the native session bridge skill is installed, `jd` also prewarms compact
handoff capsules for recent native Codex sessions whenever the Codex state DB
changes. That keeps the exact handoff path cheap, so pasting
`019d... codex session` into another chat is usually already a warm cache hit
instead of the first lookup having to build the capsule from the rollout.

Optional telemetry export follows the same local-first pattern: Flow keeps
local Codex logs canonical, and if `FLOW_CODEX_MAPLE_*` env vars are set it can
export redacted route/context/outcome spans to Maple without shipping raw
prompts or full repo paths. Use:

```bash
f codex telemetry status
f codex telemetry flush --limit 200
```

For local-only secrets, prefer `f env set --personal ...`. On macOS you may
need `f env unlock` once per day for background reads. Flow-launched Codex
sessions also inherit the same `FLOW_CODEX_MAPLE_*` values from the personal
store, while explicit shell env still wins for one-off tests.

When `jd` is running, the daemon also performs a bounded background export
pass so the external analytics view stays warm.

### macOS launchd schedule for skill-eval

If you want scorecards to stay fresh automatically on macOS:

```bash
f codex-skill-eval-launchd-install
f codex-skill-eval-launchd-status
f codex-skill-eval-launchd-logs
```

`f codex enable-global --full` installs this schedule for you.

Default schedule:

- every 30 minutes
- scan up to 400 recent events
- rebuild up to 12 recent repo scorecards
- ignore repos not seen in the last 168 hours

You can tune install-time bounds:

```bash
f codex-skill-eval-launchd-install --minutes 20 --limit 600 --max-targets 16 --within-hours 72
f codex-skill-eval-launchd-install --dry-run
```

Remove it with:

```bash
f codex-skill-eval-launchd-uninstall
```

### Cursor behavior

Cursor transcripts are read-only in Flow:

- `f ai cursor list` opens a picker and copies the selected transcript
- `f ai cursor copy` copies the latest Cursor transcript for this repo
- `f ai cursor context ...` copies the last N exchanges
- `f cursor ...` is a shortcut for the same provider-specific read commands

### Cross-directory resume

You can target another repo without changing directory:

```bash
f ai codex resume --path ~/work/example-project
f ai codex resume --path ~/work/example-project 019c61c5-0aef-71a1-b058-5c9ab43013d4
f ai codex continue --path ~/work/example-project
```

- `resume --path <repo>` resolves the requested session against that repo instead of the current cwd
- `continue --path <repo>` resumes the latest session for that repo
- explicit full Codex IDs still work directly even when your current cwd is different

## Session Selectors

`resume` accepts:

- saved alias from `.ai/sessions/claude/index.json`
- full session ID
- ID prefix (8+ chars)
- numeric index from list output (1-based)

Examples:

```bash
f ai resume my-feature
f ai resume a38cf8bf
f ai claude resume 2
f ai codex resume 019c61c5-0aef-71a1-b058-5c9ab43013d4
f ai cursor context 382ef1a3 /path/to/repo 2
```

## Content Copy Commands

```bash
# Copy full conversation to clipboard
f ai copy
f ai copy <session>

# Copy last N prompt/response turns
f ai context
f ai context <session>  <count>
```

Use `-` as session placeholder to trigger fuzzy selection:

```bash
f ai claude context - /path/to/repo 3
f ai cursor context - /path/to/repo 3
```

## Project Workflow (Recommended)

1. Start from repo root and inspect tasks:
   `f tasks list`
2. Resume exact session when continuing prior work:
   `f ai claude resume ` or `f ai codex resume `
3. Keep context current:
   `f skills sync` then `f skills reload`
4. Validate through tasks:
   `f test-related` / `f test`
5. Commit through Flow gates:
   `f commit`

This keeps sessions, tasks, skills, and commit quality checks in one loop.

## Everruns Bridge Mode

Flow also supports running a prompt through Everruns while routing client-side
`seq_*` tool calls to local `seqd`:

```bash
f ai everruns "open Safari and take a screenshot"
```

Key points:

- This path is additive. It does not replace `f ai claude ...` or `f ai codex ...`.
- Flow now reuses Seq's canonical Everruns bridge for:
  - `seq_*` tool definitions injected into new sessions
  - tool-name normalization (`seq_open_app`, `seq.open_app`, `seq:open-app`)
  - request correlation IDs (`request_id`, `run_id`, `tool_call_id`)
- Event transport is SSE-first (`/sse`) with automatic fallback to polling (`/events`) if SSE is unavailable.
- Optional Maple telemetry export can dual-write runtime traces to local + hosted ingest endpoints when `SEQ_EVERRUNS_MAPLE_*` env vars are configured.
- Existing Flow features remain unchanged (`f seq-rpc`, session resume/copy/context flows).

Setup and validation details are documented in:

- `docs/everruns-seq-bridge-integration.md`
- `docs/everruns-maple-runbook.md`

---

## File: docs/commands/commit.md

# f commit

AI-powered commit with deferred Codex review and GitEdit sync.

## Overview

Stages all changes, commits quickly by default, runs Codex deep review asynchronously in the background, pushes, and syncs AI sessions to gitedit.dev.

## Quick Start

```bash
# Default flow: commit now, Codex review runs in background
f commit

# Blocking pre-commit review (legacy behavior)
f commit --slow

# Fast commit with custom message (no AI review, no Codex follow-up)
f commit --fast "fix typo"
f commit --fast  # defaults to "." as message

# Queue for review (no push) + create jj review bookmark
f commit --queue

# Commit without pushing
f commit -n

# Include AI context in review
f commit --context

# Custom message
f commit -m "Fixes #123"
```

## Options

| Option | Short | Description |
|--------|-------|-------------|
| `--no-push` | `-n` | Skip pushing after commit |
| `--queue` | | Queue the commit for review (no push) |
| `--no-queue` | | Bypass queue and allow push |
| `--sync` | | Run synchronously (don't delegate to hub) |
| `--context` | | Include AI session context in code review |
| `--dry` | | Dry run: show context without committing |
| `--quick` | | Explicitly use fast commit + async Codex review (compat alias) |
| `--slow` | | Run blocking pre-commit review before commit |
| `--fast [MSG]` | | Fast commit with no AI review (defaults to ".") |
| `--codex` | | Use Codex instead of Claude for review |
| `--review-model <MODEL>` | | Choose specific review model |
| `--message <MSG>` | `-m` | Custom message appended to commit |
| `--tokens <N>` | `-t` | Max tokens for AI context (default: 1000) |

## Review Models

| Model | Description |
|-------|-------------|
| `claude-opus` | Claude Opus 1 for review (default) |
| `codex-high` | Codex high-capacity (gpt-5.1-codex-max) |
| `codex-mini` | Codex mini (gpt-5.1-codex-mini) |

```bash
# Use Codex
f commit --codex

# Specific model
f commit --review-model codex-high
```

---

## Fast Commit + Deferred Codex Review

`f commit` now uses this mode by default.

### Default (`f commit`) / `--quick` — commit now, Codex reviews later

Commits immediately (generates an AI commit message but skips the blocking code review), then spawns a background Codex review for that commit. The review result is queued and visible via `f commit-queue list`.

```bash
f commit
f commit --quick
```

What happens:
1. Stages all changes, generates commit message, commits, pushes
2. Queues the commit SHA for async review
3. Spawns a background Codex process that reviews the diff
4. You keep working — check results later with `f commit-queue list`

### `--slow` — run blocking review before commit

Runs the pre-commit AI review before creating the commit.

```bash
f commit --slow
f commit --slow --review-model codex-high
```

### `--fast` — instant commit, no review at all

Commits with a provided message (or `"."` if omitted). No AI review, no async follow-up. Useful for trivial changes.

```bash
f commit --fast "fix typo"
f commit --fast              # message defaults to "."
```

### When to use which

| Flag | AI message | Code review | Async review | Best for |
|------|-----------|-------------|-------------|----------|
| (none) | Yes | No | Yes (Codex background) | Default fast workflow |
| `--quick` | Yes | No | Yes (Codex background) | Explicit fast mode |
| `--slow` | Yes | Yes (blocking) | No | Pre-commit deep check |
| `--fast` | No (you provide) | No | No | Trivial/WIP commits |

### Opt Out Of Fast Default

If you want plain `f commit` to run blocking review by default, set:

```toml
[commit]
quick-default = false
```

With this set, plain `f commit` behaves like `f commit --slow` unless you explicitly pass `--quick`.

Run deep review in batches:

```bash
f reviews-todo codex --all
f reviews-todo list
```

### Myflow Fast + Deep Profile

For `~/code/myflow`, this profile gives a fast default loop while keeping deep Codex coverage:

```toml
[commit]
quick-default = true
queue = false
queue_on_issues = false

# Fast message generation path via zerg/ai (glm + cerebras), then fallbacks.
message_fallbacks = [
  "rise:zai:glm-5",
  "rise:cerebras:gpt-oss-120b",
  "remote",
  "openai"
]

# When you explicitly run blocking review, prefer fast models first.
review_fallbacks = [
  "glm5",
  "rise:cerebras:gpt-oss-120b",
  "codex-high"
]
```

Then operate with:

```bash
f commit
f reviews-todo codex --all
```

---

## What Happens

1. **Safety Checks**
   - Warns about sensitive files (.env, .pem, keys, credentials)
   - Warns about files with large diffs (500+ lines)
   - Runs invariant checks from `[invariants]` when configured

2. **Stage Changes**
   - Runs `git add -A` to stage all changes

3. **Code Review**
   - Sends diff to AI for review
   - Checks for bugs, security issues, best practices
   - Optionally includes AI session context (`--context`)

4. **Generate Message**
   - AI generates commit message from diff
   - Appends custom message if provided (`-m`)

5. **Commit**
   - Creates commit with generated message

6. **Queue (optional)**
   - Adds commit to the review queue (`f commit-queue list`)
   - Creates a jj review bookmark (e.g., `review/main-<sha>`)

7. **Push**
   - Pushes to remote (unless `--no-push` or `--queue`)

7. **GitEdit Sync**
   - Syncs AI session data to gitedit.dev

## Invariant Gate

If your project defines `[invariants]` in `flow.toml`, `f commit` evaluates the staged diff against those rules (forbidden patterns, dependency allowlist policy, file line limits).

- `mode = "warn"`: commit continues and findings are shown.
- `mode = "block"`: commit is blocked on warning/critical findings.
- Findings are injected into the AI review context.

---

## Usage Examples

### Basic Commit

```bash
# Review, commit, and push
f commit
```

### Local Commit Only

```bash
# Don't push to remote
f commit -n
```

### With AI Context

Include recent AI session context in the review:

```bash
f commit --context
f commit --context --tokens 2000  # More context
```

### Custom Message

Append additional context to the commit:

```bash
f commit -m "Fixes #123"
f commit -m "Co-authored-by: John <john@example.com>"
```

### Dry Run

See what would be reviewed without committing:

```bash
f commit --dry
```

### Synchronous Mode

Run directly without delegating to hub:

```bash
f commit --sync
```

---

## Safety Warnings

### Sensitive Files

Before committing, flow warns if staging files that look sensitive:

```
⚠ Warning: The following sensitive files are staged:
  - .env
  - credentials.json
  - private.key
```

Sensitive patterns include:
- `.env`, `.env.*`
- `credentials.json`, `secrets.json`
- `.pem`, `.key`, `id_rsa`, `id_ed25519`
- Files containing `password`, `secret`, `token`

### Secret Scan (Staged Diff)

Flow scans staged diffs for likely secrets (API keys, tokens, passwords). If a match
is detected, the commit is blocked. In an interactive terminal, flow offers to run
an auto-fix using `ai` to mask or replace the values, then asks for approval to
continue.

You can bypass the check for a single commit with:

```
FLOW_ALLOW_SECRET_COMMIT=1 f commit
```

### Large Diffs

Warns about files with significant changes:

```
⚠ Warning: The following files have large diffs:
  - src/generated.rs (1523 lines)
  - data/fixtures.json (834 lines)
```

Threshold: 500+ lines added/removed.

---

## Related Commands

| Command | Description |
|---------|-------------|
| `f commit` | Fast commit + deferred Codex review (default) |
| `f commitWithCheck` | Review without GitEdit sync |
| `f commitSimple` | No review, just AI commit message |

### commitWithCheck (alias: cc)

Same as `commit` but skips GitEdit sync:

```bash
f commitWithCheck
f cc  # Short alias
```

### commitSimple

Quick commit without code review:

```bash
f commitSimple
```

---

## Configuration

### Hub Delegation

By default, `f commit` delegates to the hub daemon for async processing. Use `--sync` for direct execution:

```bash
# Async via hub (default)
f commit

# Sync (direct)
f commit --sync
```

### Commit Message Tool

Optionally force a specific commit-message generator:

```toml
[commit]
message_tool = "kimi" # also supports: claude, rise, glm5, opencode, openrouter, remote, openai
message_model = "kimi-k2-thinking-turbo" # optional, tool-specific
```

If the forced tool fails, `f commit` now falls back through the configured/default chain.

### Review Tool (Kimi CLI)

Use Kimi Code CLI for code review:

```toml
[review]
tool = "kimi"
model = "kimi-k2-thinking-turbo" # optional; uses Kimi default if omitted
```

This uses `kimi --quiet` (print mode) with your existing Kimi CLI auth/config.

### Robust Fallbacks

`f commit` now uses multi-attempt fallback chains for both review and commit-message generation.

Default behavior:
- Review: primary selection, then `openrouter`, `claude`, `codex-high`
- Message: review-aligned/override tool, then `remote` (myflow), `openai`, `openrouter`
- If all message attempts fail and fail-open is enabled, Flow uses a deterministic local fallback message.

Configuration:

```toml
[commit]
review_fail_open = true
message_fail_open = true
review_fallbacks = ["openrouter", "claude", "codex-high"]
message_fallbacks = ["remote", "openai", "openrouter"]
```

Environment overrides:
- `FLOW_COMMIT_REVIEW_FAIL_OPEN=0|1`
- `FLOW_COMMIT_MESSAGE_FAIL_OPEN=0|1`
- `FLOW_COMMIT_REVIEW_FALLBACKS="openrouter,claude,codex-high"`
- `FLOW_COMMIT_MESSAGE_FALLBACKS="remote,openai,openrouter"`

Codex -> GLM5 fallback example:

```toml
[commit]
review_fallbacks = ["glm5", "openrouter", "claude"]
message_fallbacks = ["glm5", "remote", "openai"]
```

`glm5` maps to the Rise/internal route with model `zai:glm-5`.

### Queue Policy

Queue only when review finds issues (auto-push on a clean review):

```toml
[commit]
queue = true
queue_on_issues = true
```

`--queue` / `--no-queue` still override this behavior.

### Commit Quality Gates (Testing + Required Skills)

Use local gates to block commits that skip tests or required workflow skills:

```toml
[commit.testing]
mode = "block"
runner = "bun"
bun_repo_strict = true
require_related_tests = true
ai_scratch_test_dir = ".ai/test"
run_ai_scratch_tests = true
allow_ai_scratch_to_satisfy_gate = false
max_local_gate_seconds = 20

[commit.skill_gate]
mode = "block"
required = ["quality-bun-feature-delivery"]

[commit.skill_gate.min_version]
quality-bun-feature-delivery = 2
```

When `mode = "block"`, `f commit` fails until the test/skill requirements are satisfied.  
For Bun repos, run checks with `bun bd test ...` for debug-build validation. If no related tracked tests are found, Flow can run tests under `ai_scratch_test_dir` (default `.ai/test`) as a fallback signal.

### AI Session Context

When `--context` is enabled, includes recent Claude Code session context:

```bash
# Default: 1000 tokens of context
f commit --context

# More context
f commit --context --tokens 3000
```

---

## Examples

### Quick Bug Fix

```bash
# Fix bug, commit with context
vim src/lib.rs
f commit --context -m "Fixes null pointer in edge case"
```

### Feature Branch

```bash
# Work on feature
git checkout -b feature/new-api
# ... make changes ...

# Commit without push
f commit -n

# More changes...
f commit -n

# Final push
git push -u origin feature/new-api
```

### Review Before Commit

```bash
# See what would be reviewed
f commit --dry

# If satisfied, commit
f commit
```

---

## Troubleshooting

### "Sensitive files staged"

Either:
1. Add files to `.gitignore`
2. Unstage with `git reset HEAD <file>`
3. Proceed anyway if intentional

### Review taking too long

Use `--sync` to see progress directly:
```bash
f commit --sync
```

### Hub not responding

Fall back to sync mode:
```bash
f commit --sync
```

## See Also

- [upstream](upstream.md) - Sync forks before committing
- [publish](publish.md) - Publish after committing

---

## File: docs/commands/commits.md

# f commits

Browse commits with AI metadata and mark notable commits for quick access.

## Usage

```bash
f commits
f commits --limit 200
f commits --all
f commits top
f commits mark <hash>
f commits unmark <hash>
```

## Notable commits

Notable commits are stored in `.ai/internal/commits/top.txt` in the repo root. Each line is:

```
<full-hash>\t<label>
```

## Key bindings

When using fzf:

- `ctrl-t` — toggle notable for the selected commit.

---

## File: docs/commands/db.md

# db

Manage database workflows and backends (Jazz + Postgres).

## Usage

```bash
f db  <action>
```

## Jazz

Create Jazz2 app credentials and populate env vars for the current project.

```bash
f db jazz new --kind mirror --name gitedit-mirror
```

Resolution order for the credential bootstrap helper:

1. Local `jazz-tools` binary on `PATH`
2. Pinned `npx --yes jazz-tools@0.20.14`

For deliberate experiments, override the pinned fallback with:

```bash
FLOW_JAZZ_TOOLS_PACKAGE_SPEC=jazz-tools@<version> f db jazz new --kind mirror
```

## Postgres

Run Drizzle migrations for the default Postgres project (`~/org/la/la/server`).

```bash
f db postgres migrate
f db postgres migrate --generate
f db postgres generate
```

Environment resolution order for `DATABASE_URL`:

1. `--database-url` flag
2. `DATABASE_URL`
3. `PLANETSCALE_DATABASE_URL` / `PSCALE_DATABASE_URL`
4. `/.env` (DATABASE_URL)

Use `--project` to override the Postgres project directory.

---

## File: docs/commands/deploy.md

# f deploy

Deploy projects to hosts and cloud platforms.

## Overview

The `deploy` command handles deployment to multiple platforms:
- **Linux hosts** via SSH (with systemd + nginx)
- **Cloudflare Workers**
- **Railway**

Auto-detects the platform from your `flow.toml` configuration.
If `[flow].deploy_task` is set, `f deploy` runs that task first.
If no deployment config exists but a `deploy` task is defined, `f deploy` runs that task.
Use `f prod` to deploy directly from `[host]`, `[cloudflare]`, `[railway]`, or `[web]` (it skips `[flow].deploy_task`).

## Quick Start

```bash
# Auto-deploy based on flow.toml config
f deploy

# Production deploy (skips flow.deploy_task, uses deploy config or deploy-prod task)
f prod

# Run the project's release task (flow.release_task or fallback)
f deploy release

# Deploy to specific platform
f deploy host
f deploy cloudflare
f deploy railway

# Production deploy to specific platform
f prod host
f prod cloudflare

# Configure deployment defaults
f deploy config

# Deploy web site
f deploy web
```

## Subcommands

| Command | Alias | Description |
|---------|-------|-------------|
| `host` | `h` | Deploy to Linux host via SSH |
| `cloudflare` | `cf` | Deploy to Cloudflare Workers |
| `web` | | Deploy the web site (Cloudflare) |
| `setup` | | Interactive deploy setup (Cloudflare) |
| `railway` | | Deploy to Railway |
| `config` | | Configure deployment defaults (Linux host) |
| `release` | | Run the project's release task |
| `status` | | Show deployment status |
| `logs` | | View deployment logs |
| `restart` | | Restart the deployed service |
| `stop` | | Stop the deployed service |
| `shell` | | SSH into the host |
| `set-host` | `set` | Configure host for deployment |
| `show-host` | | Show current host configuration |
| `health` | | Check if deployment is healthy |

---

## Web Deployment

Deploys the web site using Cloudflare and your project tasks. Flow will:
- Ensure `[web]` exists in `flow.toml` (auto-fills `path` when possible).
- Add the `web.route` (or `web.domain/*`) to your wrangler config.
- Optionally create/update the Cloudflare DNS record for the domain/route.
- Apply env vars from cloud if `web.env_source = "cloud"` is set.
- Run `deploy-web` (or `deploy` as fallback).

```bash
f deploy web
```

If the Cloudflare API token is missing, Flow will guide you to create one and
store it in your env store as `CLOUDFLARE_API_TOKEN`.

If `web.domain`/`web.route` or `web.path` is missing, Flow will prompt for them
and update `flow.toml`.

If you opt into DNS management, Flow will prompt for record type/target and
create or update the Cloudflare DNS record (default: `A` to `192.0.2.1`,
proxied).

If cloud is unavailable, Flow can store envs locally when you choose
`web.env_source = "local"`.

Example `flow.toml`:

```toml
[web]
path = "packages/web"
domain = "example.com"
env_source = "cloud"
env_apply = "always"
env_keys = ["PUBLIC_API_URL"]
env_vars = ["PUBLIC_API_URL"]
```

## Host Deployment (Linux via SSH)

Deploy to any Linux server with SSH access. Flow handles:
- File syncing via rsync
- Systemd service creation
- Nginx reverse proxy setup
- SSL via Let's Encrypt

### Configuration

Add to `flow.toml`:

```toml
[flow]
deploy_task = "deploy-cli-release"

[host]
dest = "/opt/myapp"           # Remote destination path
run = "./server"              # Command to run the service
port = 3000                   # Port the service listens on
service = "myapp"             # Systemd service name (optional, defaults to folder name)
setup = "./scripts/setup.sh"  # Setup script to run after first sync (optional)
env_file = ".env.production"  # Path to .env file for secrets (optional)
env_source = "flow"           # Pull envs from Flow env store (optional)
env_keys = ["API_KEY"]        # Keys to fetch when env_source=flow/cloud (optional)
domain = "myapp.example.com"  # Public domain for nginx (optional)
ssl = true                    # Enable SSL via Let's Encrypt (optional)
```

Tip: `f setup deploy` can scaffold the `[host]` section and create a remote setup script.

### Setup Host

First, configure your SSH connection:

```bash
# Set host (stored globally at ~/.config/flow/deploy.json)
f deploy set-host user@host:port
f deploy set-host deploy@myserver.com:22
f deploy set-host root@192.168.1.100

# Interactive config (prefills from ~/.config/infra/config.json if present)
f deploy config

# Verify connection
f deploy shell
```

### Deploy

```bash
# Deploy to host
f deploy host

# Force re-run setup script
f deploy host --setup

# Build remotely instead of syncing local artifacts
f deploy host --remote-build
```

### What Happens

1. **Sync files** - rsync uploads project (excludes `target/`, `.git/`, `node_modules/`, `.env`, `*.log`)
2. **Copy env file** - If `env_file` is specified, copies it to `{dest}/.env`
   (or, if `env_source = "flow"`, fetches from Flow env store and writes `{dest}/.env`)
3. **Run setup** - Executes setup script on first deploy or with `--setup`
4. **Create systemd service** - Generates and enables `/etc/systemd/system/{service}.service`
5. **Configure nginx** - If `domain` is set, creates reverse proxy config
6. **Setup SSL** - If `ssl = true`, runs certbot for Let's Encrypt certificate
7. **Start service** - Runs `systemctl restart {service}`

### Manage Service

```bash
# View logs
f deploy logs                 # Since last deploy (host only)
f deploy logs -f              # Follow in real-time (since last deploy)
f deploy logs --all           # Full history (ignore deploy marker)
f deploy logs --all -n 500    # Show last 500 lines without deploy filter

# Restart/stop
f deploy restart
f deploy stop

# Check status
f deploy status

# SSH into server
f deploy shell

# Health check
f deploy health
f deploy health --url https://myapp.example.com/health
f deploy health --status 204  # Expect specific status code
```

Note: For host deploys, Flow records the last successful deploy time in `.flow/deploy-log.json` and uses it to scope `f deploy logs` output. Use `--all` to ignore it.

---

## Cloudflare Workers

Deploy to Cloudflare's edge network.

### Configuration

Add to `flow.toml`:

```toml
[cloudflare]
path = "worker"                    # Path to worker directory (optional, defaults to project root)
environment = "production"         # Wrangler environment name (optional)
env_file = ".env.cloudflare"       # Path to .env file for secrets (optional)
env_source = "cloud"              # Use cloud or local env store for secrets (optional)
env_keys = ["API_KEY", "SECRET"]   # Specific keys to fetch from env store (optional)
env_vars = ["PUBLIC_URL"]          # Keys to set as non-secret vars (optional)
deploy = "wrangler deploy"         # Custom deploy command (optional)
dev = "wrangler dev"               # Custom dev command (optional)
url = "https://my-worker.workers.dev"  # URL for health checks (optional)
```

### Prerequisites

- [Wrangler CLI](https://developers.cloudflare.com/workers/wrangler/) installed
- `wrangler.toml` in your worker directory
- Authenticated with `wrangler login`

### Deploy

```bash
# Deploy
f deploy cloudflare

# Deploy with secrets from env_file
f deploy cloudflare --secrets

# Run in dev mode
f deploy cloudflare --dev
```

### Production domain (for `f prod`)

Use `[prod]` to set a production domain or route for Workers. `f prod` will add
the route to your `wrangler.json/jsonc` before deploying.

```toml
[prod]
domain = "anysynth.nikiv.com"   # Will be mapped to route "anysynth.nikiv.com/*"
# route = "anysynth.nikiv.com/*"  # Use this for explicit patterns
```

### Interactive Setup

For first-time setup, use the interactive wizard:

```bash
f deploy setup
```

This walks you through:
1. Selecting worker directory (auto-discovers `wrangler.toml`)
2. Choosing .env file for secrets
3. Selecting Cloudflare environment (production, staging, etc.)
4. Picking which secrets to push
5. Updating `flow.toml` with your choices

If your `flow.toml` lists service keys (for example Stripe keys), the setup flow
will offer to run the matching service onboarding before applying envs.

### Secrets from cloud

If using cloud for secret management:

```toml
[cloudflare]
env_source = "cloud"
env_keys = ["ANTHROPIC_API_KEY", "DATABASE_URL"]  # Fetched as secrets
env_vars = ["PUBLIC_API_URL"]                      # Fetched as non-secret vars
environment = "production"
```

Then deploy:

```bash
f deploy cloudflare --secrets
```

If you want to use local Flow envs instead:

```toml
[cloudflare]
env_source = "local"
env_keys = ["ANTHROPIC_API_KEY", "DATABASE_URL"]
env_vars = ["PUBLIC_API_URL"]
```

If you need to fill missing values first:

```bash
f env guide
```

---

## Railway

Deploy to Railway's platform.

### Configuration

Add to `flow.toml`:

```toml
[railway]
project = "my-project"         # Railway project ID
service = "api"                # Service name (optional)
environment = "production"     # Environment name (optional)
start = "npm start"            # Start command (optional)
env_file = ".env.railway"      # Path to .env file (optional)
```

### Prerequisites

- [Railway CLI](https://docs.railway.app/develop/cli) installed (`npm install @railway/cli`)
- Authenticated with `railway login`

### Deploy

```bash
f deploy railway
```

What happens:
1. Links to Railway project if specified
2. Sets environment variables from `env_file`
3. Deploys with `railway up --detach`

---

## Health Checks

Check if your deployment is responding:

```bash
# Use domain from [host] or url from [cloudflare] config
f deploy health

# Custom URL
f deploy health --url https://api.example.com/health

# Expect specific status code
f deploy health --status 204
```

Returns:
- `Healthy (HTTP 200 in 0.15s)` on success
- `Unhealthy: expected HTTP 200, got 500` on wrong status
- `Unreachable: Connection refused` on network error

---

## Global Host Configuration

Host connection is stored globally at `~/.config/flow/deploy.json`:

```json
{
  "host": {
    "user": "deploy",
    "host": "myserver.com",
    "port": 22
  }
}
```

View/set:

```bash
f deploy show-host
f deploy set-host deploy@newserver.com:2222
```

---

## Examples

### Full Host Setup

```toml
# flow.toml
[host]
dest = "/opt/api"
run = "/opt/api/server"
port = 8080
service = "myapi"
setup = "cargo build --release && cp target/release/server /opt/api/"
env_file = ".env.production"
domain = "api.mycompany.com"
ssl = true
```

```bash
# First time setup
f deploy set-host root@myserver.com

# Deploy
f deploy host

# Check it's working
f deploy health
f deploy logs -f
```

### Full Cloudflare Setup

```toml
# flow.toml
[cloudflare]
path = "packages/worker"
environment = "production"
env_source = "cloud"
env_keys = ["OPENAI_API_KEY", "WEBHOOK_SECRET"]
url = "https://my-worker.mycompany.workers.dev"
```

```bash
# Store project secrets
f env project set -e production OPENAI_API_KEY=sk-...
f env project set -e production WEBHOOK_SECRET=whsec_...

# Deploy with secrets
f deploy cloudflare --secrets

# Verify
f deploy health
```

### CI/CD Integration

```yaml
# GitHub Actions
deploy:
  runs-on: ubuntu-latest
  steps:
    - uses: actions/checkout@v4
    - name: Deploy
      run: |
        f deploy set-host ${{ secrets.DEPLOY_HOST }}
        f deploy host
        f deploy health
```

---

## Troubleshooting

### "No host configured"

Run `f deploy set-host user@host:port` first.

### "No wrangler config found"

Ensure `wrangler.toml` exists in your worker directory, or run `wrangler init`.

### SSH connection fails

Test with `f deploy shell` to debug. Check:
- SSH key is in `~/.ssh/` and added to server
- Port is correct (default: 22)
- Server is reachable

### Secrets not updating

For Cloudflare, use `--secrets` flag: `f deploy cloudflare --secrets`

### Health check fails

Check URL is correct and service is running:
```bash
f deploy logs -f  # Check for errors
curl -v https://your-domain.com  # Test manually
```

---

## File: docs/commands/docs.md

# f docs

Manage documentation for a project. There are two doc systems:

- `.ai/docs` for AI-maintained internal docs.
- `docs/` for human-facing docs rendered by the docs hub.

## Quick Start

```bash
# Create docs/ with starter files
f docs new

# Open docs for the current project (auto-starts the hub)
f docs

# Deploy the current project's docs to Cloudflare Pages
f docs deploy
```

## Commands

### f docs new

Creates a `docs/` folder in the current project using the template in `~/new/docs`.
If `docs/` already exists, it merges in any missing template files and leaves
existing content untouched.

Options:

- `--path `: Target directory (defaults to current folder).
- `--force`: Overwrite if `docs/` already exists.

### f docs hub

Runs a single dev server that aggregates docs from `~/code` and `~/org`.
Use `FLOW_DOCS_FOCUS=1` to only index the current project for faster startup.

Options:

- `--host <HOST>` (default: `127.0.0.1`)
- `--port ` (default: `4410`)
- `--hub-root ` (default: `~/.config/flow/docs-hub`)
- `--template-root ` (default: `~/new/docs`)
- `--code-root ` (default: `~/code`)
- `--org-root ` (default: `~/org`)
- `--no-ai`: Skip `.ai/docs`.
- `--no-open`: Do not open the browser.
- `--sync-only`: Sync docs content and exit.

### f docs deploy

Deploys the current project's docs to Cloudflare Pages (uses the docs hub template).

Options:

- `--project <NAME>`: Pages project name (defaults to the flow.toml name).
- `--domain <DOMAIN>`: Attach a custom domain (optional).
- `--yes`: Skip confirmation prompts.

### f docs sync

Syncs `.ai/docs` metadata based on recent commits. Intended for AI doc upkeep.

### f docs list

Lists `.ai/docs` files for the current project.

### f docs status

Shows recent commits and `.ai/docs` file modification times.

It now also shows:

- recent Flow-managed Codex session packets stored under Flow state for the current project
- doc-review queue state counts for the current project

### f docs review-pending

Runs the bounded daemon-style review pass over pending session-doc packets stored in
Flow state and records promotion decisions into queue state plus each packet's
`promotion.json`.

Options:

- `-n, --limit <N>`: Maximum number of pending entries to review (default: `25`).

### f docs promote-session

Previews or applies promotion for a daemon-captured session-doc packet.

By default this is a dry run. It prints the chosen target under `.ai/docs/` and the
promoted markdown note. Raw packet bundles stay in Flow state; only promoted
durable notes are written into the repo.

Options:

- `<SESSION>`: Session id, session id prefix, or session key like `019d035d-...` or `019d035d-1773776290`
- `--apply`: Write the promoted note immediately

### f docs commit-pending

Commits promoted session-doc notes when the git diff is isolated to doc-only files.

This command refuses to commit if the worktree contains unrelated changes.

Options:

- `--dry-run`: Show the candidate files and commit message without staging or committing

### f docs edit

Opens a `.ai/docs` file in `$EDITOR`.

Example:

```bash
f docs edit architecture
```

---

## File: docs/commands/domains.md

# `f domains`

Manage shared local `*.localhost` routing with a single proxy on port `80`.

## Why

Without this, each repo can start its own proxy and race for port `80`.
`f domains` centralizes ownership with one engine at a time.

State lives in:

- `~/.config/flow/local-domains/routes.json`
- runtime artifacts under `~/.config/flow/local-domains/`

## Engines

- `docker` (default): shared nginx container (`flow-local-domains-proxy`)
- `native` (experimental): local C++ daemon (`domainsd-cpp`)

Select engine per command:

```bash
f domains --engine docker up
f domains --engine native up
```

Or via env:

```bash
export FLOW_DOMAINS_ENGINE=native
```

## Commands

```bash
f domains list
f domains add linsa.localhost 127.0.0.1:3481
f domains rm linsa.localhost
f domains up
f domains down
f domains doctor
f domains --engine native up
f domains --engine native down
f domains --engine native doctor
```

## Behavior

- `f domains up`
  - starts shared proxy on `:80`
  - fails fast if another process/container owns port `80`
- `f domains add`
  - validates `host` ends with `.localhost`
  - validates target format `host:port`
  - refuses overwrite unless `--replace`
  - reloads proxy if already running
- `f domains doctor`
  - shows route count
  - shows current owner of port `80`
  - highlights conflict ownership

## Native notes (experimental)

- Requires `clang++` to build `tools/domainsd-cpp/domainsd.cpp`.
- Current scope is HTTP/1.1 host routing with WebSocket upgrade passthrough and upstream keepalive pooling.
- Native daemon has built-in overload shedding (`503`) and upstream timeout protection (`504` on connect timeout).
- HTTP/2/TLS are not implemented yet.
- See `docs/local-domains-domainsd-cpp-spec.md`.
- myflow-specific setup: `docs/myflow-localhost-runbook.md`.
- Lifecycle integration: configure `[lifecycle.domains]` and use `f up` / `f down`.

### macOS no-docker bind to :80

If native startup fails with `Permission denied` on `127.0.0.1:80`, install launchd socket mode once:

```bash
cd ~/code/flow
sudo ./tools/domainsd-cpp/install-macos-launchd.sh
```

Then run:

```bash
f domains --engine native up
```

This keeps routing fully native and avoids Docker overhead while still using port `80`.

### Native tuning envs

You can tune the native daemon at startup via environment variables:

```bash
FLOW_DOMAINS_NATIVE_MAX_ACTIVE_CLIENTS=128
FLOW_DOMAINS_NATIVE_UPSTREAM_CONNECT_TIMEOUT_MS=10000
FLOW_DOMAINS_NATIVE_UPSTREAM_IO_TIMEOUT_MS=15000
FLOW_DOMAINS_NATIVE_CLIENT_IO_TIMEOUT_MS=30000
FLOW_DOMAINS_NATIVE_POOL_MAX_IDLE_PER_KEY=8
FLOW_DOMAINS_NATIVE_POOL_MAX_IDLE_TOTAL=256
FLOW_DOMAINS_NATIVE_POOL_IDLE_TIMEOUT_MS=15000
FLOW_DOMAINS_NATIVE_POOL_MAX_AGE_MS=120000
```
## Recommended Repo Pattern

Instead of per-repo docker proxy tasks:

```toml
[[tasks]]
name = "domains-up"
command = "f domains add myapp.localhost 127.0.0.1:3000 && f domains up"
```

This keeps one proxy process for all repos and avoids accidental domain hijacking.