diff --git a/docs/public-docs/chain-operators/reference/batcher-configuration.mdx b/docs/public-docs/chain-operators/reference/batcher-configuration.mdx
index 776dbc66c18..04dc3e76ad5 100644
--- a/docs/public-docs/chain-operators/reference/batcher-configuration.mdx
+++ b/docs/public-docs/chain-operators/reference/batcher-configuration.mdx
@@ -4,761 +4,63 @@ description: Reference for all op-batcher configuration options, covering CLI fl
diataxis: reference
---
+import OpBatcherFlags from '/snippets/generated/op-batcher-flags.mdx';
+
This page catalogues every configuration option for the op-batcher, the service
-that posts L2 sequencer data to L1 to make it available for verifiers. The
-options are from the `--help` in [v1.10.0](https://github.com/ethereum-optimism/optimism/releases/tag/op-batcher%2Fv1.10.0).
+that posts L2 sequencer data to L1 to make it available for verifiers.
+
+The flag tables below are generated directly from the op-batcher's flag
+definitions in the monorepo (`op-batcher/flags`), and CI keeps them in sync
+with the source: a flag change that is not reflected here fails the build, so
+the tables cannot silently fall behind a release. Every flag can also be set
+through the environment variable listed next to it.
For guidance on choosing values — the batcher policy, cost tuning, multi-blob
transactions, and sequencer throttling — see the
[batcher configuration guide](/chain-operators/guides/configuration/batcher).
-## Batch generation
-
-### batch-type
-
-The batch type. 0 for `SingularBatch` and 1 for `SpanBatch`. The default value
-is `0` for `SingularBatch`.
-See the [span batch feature page](/op-stack/features/span-batches) to learn more.
-
-
- `--batch-type=`
- `--batch-type=singular`
- `OP_BATCHER_BATCH_TYPE=`
-
-
-### max-blocks-per-span-batch
-
-Maximum number of blocks to add to a span batch. The default value is `0`,
-meaning no maximum.
-
-
- `--max-blocks-per-span-batch=`
- `--max-blocks-per-span-batch=0`
- `OP_BATCHER_MAX_BLOCKS_PER_SPAN_BATCH=0`
-
-
-### compression-algo
-
-The compression algorithm to use. Valid options: zlib, brotli, brotli-9,
-brotli-10, brotli-11. The default value is `zlib`.
-
-
- `--compression-algo=`
- `--compression-algo=zlib`
- `OP_BATCHER_COMPRESSION_ALGO=zlib`
-
-
-### compressor
+## Flags
-The type of compressor. Valid options: none, ratio, shadow. The default value
-is `shadow`.
+
-
- `--compressor=`
- `--compressor=shadow`
- `OP_BATCHER_COMPRESSOR=shadow`
-
-
-### approx-compr-ratio
+## Throttling
-Only relevant for ratio compressor. The approximate compression ratio (`<=1.0`). The default value is `0.6`.
+The `throttle.*` flags control how the batcher limits data availability (DA)
+usage when a backlog builds up. When the amount of sequenced data that has not
+yet been posted to L1 (the `unsafe_da_bytes` metric) exceeds
+`--throttle.unsafe-da-bytes-lower-threshold`, the batcher instructs block
+builders — over the `--l2-eth-rpc` endpoints, plus any endpoints listed in
+`--throttle.additional-endpoints` — to limit transaction and block DA sizes,
+scaling between the configured upper and lower size limits as the backlog
+grows.
-
- `--approx-compr-ratio=`
- `--approx-compr-ratio=0.6`
- `OP_BATCHER_APPROX_COMPR_RATIO=0.6`
-
+`--throttle.controller-type` selects how throttling intensity ramps with the
+backlog: `step`, `linear`, `quadratic` (the default), or the experimental
+`pid` controller, which is tuned with the six `throttle.pid-*` flags.
-### poll-interval
+For the design of the throttling subsystem, including the PID controller, see
+[`op-batcher/throttling.md`](https://github.com/ethereum-optimism/optimism/blob/develop/op-batcher/throttling.md)
+in the monorepo.
-How frequently to poll L2 for new blocks. The default value is `6s`.
+## Notes on selected flags
-
- `--poll-interval=`
- `--poll-interval=6s`
- `OP_BATCHER_POLL_INTERVAL=6s`
-
+### batch-type
-## Batch submission
+Span batches (`--batch-type=1`) aggregate consecutive L2 blocks into a single
+batch for better compression. See the
+[span batch feature page](/op-stack/features/span-batches) to learn more.
### data-availability-type
- Setting this flag to `auto` will allow the batcher to automatically switch between `calldata` and `blobs` based on the current L1 gas price.
+ Setting this flag to `auto` allows the batcher to automatically switch
+ between `calldata` and `blobs` based on the current L1 gas price.
-The data availability type to use for submitting batches to the L1. Valid
-options: `calldata`, `blobs`, and `auto`. The default value is `calldata`.
-
-
- `--data-availability-type=`
- `--data-availability-type=calldata`
- `OP_BATCHER_DATA_AVAILABILITY_TYPE=calldata`
-
-
-### target-num-frames
-
-The target number of frames to create per channel. Controls number of blobs per
-blob tx, if using Blob DA. The default value is `1`.
-
-
- `--target-num-frames=`
- `--target-num-frames=1`
- `OP_BATCHER_TARGET_NUM_FRAMES=1`
-
-
-### max-channel-duration
-
-The maximum duration of L1-blocks to keep a channel open. 0 to disable. The
-default value is `0`.
-
-
- `--max-channel-duration=`
- `--max-channel-duration=0`
- `OP_BATCHER_MAX_CHANNEL_DURATION=0`
-
-
-### sub-safety-margin
-
-The batcher tx submission safety margin (in #L1-blocks) to subtract from a
-channel's timeout and sequencing window, to guarantee safe inclusion of a
-channel on L1. The default value is `10`.
-
-
- `--sub-safety-margin=`
- `--sub-safety-margin=10`
- `OP_BATCHER_SUB_SAFETY_MARGIN=10s`
-
-
-### max-l1-tx-size-bytes
-
-The maximum size of a batch tx submitted to L1. Ignored for blobs, where max
-blob size will be used. The default value is `120000`.
-
-
- `--max-l1-tx-size-bytes=`
- `--max-l1-tx-size-bytes=120000`
- `OP_BATCHER_MAX_L1_TX_SIZE_BYTES=120000`
-
-
-## Batcher startup
-
-### wait-node-sync
-
-Indicates if, during startup, the batcher should wait for a recent batcher tx
-on L1 to finalize (via more block confirmations). This should help avoid
-duplicate batcher txs. The default value is `false`.
-
-
- `--wait-node-sync=`
- `--wait-node-sync=false`
- `OP_BATCHER_WAIT_NODE_SYNC=false`
-
-
-### check-recent-txs-depth
-
-Indicates how many blocks back the batcher should look during startup for a
-recent batch tx on L1. This can speed up waiting for node sync. It should be
-set to the verifier confirmation depth of the sequencer (e.g. 4). The default
-value is `0`.
-
-
- `--check-recent-txs-depth=`
- `--check-recent-txs-depth=0`
- `OP_BATCHER_CHECK_RECENT_TXS_DEPTH=0`
-
-
-### stopped
-
-Initialize the batcher in a stopped state. The batcher can be started using the
-admin\_startBatcher RPC. The default value is `false`.
-
-
- `--stopped=`
- `--stopped=false`
- `OP_BATCHER_STOPPED=false`
-
-
-## Throttling
-
-The batcher supports throttling configuration to limit DA usage for transactions and blocks, and to control throttle intensity via several controller types. The following flags are available:
-
-### throttle.additional-endpoints
-Comma-separated list of endpoints to distribute throttling configuration to (in addition to the L2 endpoints specified with `--l2-eth-rpc`).
-
-
- `--throttle.additional-endpoints=,,...`
- `--throttle.additional-endpoints=http://builder1:8545,http://builder2:8545`
- `OP_BATCHER_THROTTLE_ADDITIONAL_ENDPOINTS=http://builder1:8545,http://builder2:8545`
-
-
-### throttle.tx-size-lower-limit
-The DA size limit for individual transactions when the throttle intensity is at its maximum. `0` disables limits; use `1` as the smallest effective limit.
-
-
- `--throttle.tx-size-lower-limit=`
- `--throttle.tx-size-lower-limit=150`
- `OP_BATCHER_THROTTLE_TX_SIZE_LOWER_LIMIT=150`
-
-
-### throttle.tx-size-upper-limit
-The DA size limit for individual transactions as throttle intensity approaches `0` (minimal throttling). Not applied when throttling is inactive.
-
-
- `--throttle.tx-size-upper-limit=`
- `--throttle.tx-size-upper-limit=20000`
- `OP_BATCHER_THROTTLE_TX_SIZE_UPPER_LIMIT=20000`
-
-
-### throttle.block-size-lower-limit
-The DA size limit for blocks when throttle intensity is at maximum (applies for linear and quadratic controllers). `0` disables limits; use `1` as the smallest effective limit.
-
-
- `--throttle.block-size-lower-limit=`
- `--throttle.block-size-lower-limit=2000`
- `OP_BATCHER_THROTTLE_BLOCK_SIZE_LOWER_LIMIT=2000`
-
-
-### throttle.block-size-upper-limit
-The DA size limit for blocks when throttling is inactive (throttle intensity = 0).
-
-
- `--throttle.block-size-upper-limit=`
- `--throttle.block-size-upper-limit=130000`
- `OP_BATCHER_THROTTLE_BLOCK_SIZE_UPPER_LIMIT=130000`
-
-
-### throttle.controller-type
-Type of throttle controller to use. Valid values: `step`, `linear`, or `quadratic` (default).
-
-
- `--throttle.controller-type=`
- `--throttle.controller-type=quadratic`
- `OP_BATCHER_THROTTLE_CONTROLLER_TYPE=quadratic`
-
-
-### throttle.unsafe-da-bytes-lower-threshold
-Threshold on `unsafe_da_bytes` beyond which the batcher will start to throttle the block builder. `0` disables throttling.
-
-
- `--throttle.unsafe-da-bytes-lower-threshold=`
- `--throttle.unsafe-da-bytes-lower-threshold=3200000`
- `OP_BATCHER_THROTTLE_UNSAFE_DA_BYTES_LOWER_THRESHOLD=3200000`
-
-
-### throttle.unsafe-da-bytes-upper-threshold
-Threshold on `unsafe_da_bytes` at which throttling reaches maximum intensity (applies for linear and quadratic controllers).
-
-
- `--throttle.unsafe-da-bytes-upper-threshold=`
- `--throttle.unsafe-da-bytes-upper-threshold=12800000`
- `OP_BATCHER_THROTTLE_UNSAFE_DA_BYTES_UPPER_THRESHOLD=12800000`
-
-
-## Transaction manager
-
-### num-confirmations
-
-Number of confirmations which we will wait after sending a transaction. The
-default value is `10`.
-
-
- `--num-confirmations=`
- `--num-confirmations=10`
- `OP_BATCHER_NUM_CONFIRMATIONS=10`
-
-
-### max-pending-tx
-
-The maximum number of pending transactions. 0 for no limit. The default value
-is `1`.
-
-
- `--max-pending-tx=`
- `--max-pending-tx=1`
- `OP_BATCHER_MAX_PENDING_TX=1`
-
-
-### resubmission-timeout
-
-Duration we will wait before resubmitting a transaction to L1. The default
-value is `48s`.
-
-
- `--resubmission-timeout=`
- `--resubmission-timeout=48s`
- `OP_BATCHER_RESUBMISSION_TIMEOUT=48s`
-
-
-### safe-abort-nonce-too-low-count
-
-Number of ErrNonceTooLow observations required to give up on a tx at a
-particular nonce without receiving confirmation. The default value is `3`.
-
-
- `--safe-abort-nonce-too-low-count=`
- `--safe-abort-nonce-too-low-count=3`
- `OP_BATCHER_SAFE_ABORT_NONCE_TOO_LOW_COUNT=3`
-
-
-### txmgr.min-basefee
-
-Enforces a minimum base fee (in GWei) to assume when determining tx fees. 1
-GWei by default. The default value is `1`.
-
-
- `--txmgr.min-basefee=`
- `--txmgr.min-basefee=1`
- `OP_BATCHER_TXMGR_MIN_BASEFEE=1`
-
-
-### txmgr.min-tip-cap
-
-Enforces a minimum tip cap (in GWei) to use when determining tx fees. 1 GWei by
-default. The default value is `1`.
-
-
- `--txmgr.min-tip-cap=`
- `--txmgr.min-tip-cap=1`
- `OP_BATCHER_TXMGR_MIN_TIP_CAP=1`
-
-
-### fee-limit-multiplier
-
-The multiplier applied to fee suggestions to put a hard limit on fee increases.
-The default value is `5`.
-
-
- `--fee-limit-multiplier=`
- `--fee-limit-multiplier=5`
- `OP_BATCHER_TXMGR_FEE_LIMIT_MULTIPLIER=5`
-
-
-### txmgr.fee-limit-threshold
-
-The minimum threshold (in GWei) at which fee bumping starts to be capped.
-Allows arbitrary fee bumps below this threshold. The default value is `100`.
-
-
- `--txmgr.fee-limit-threshold=`
- `--txmgr.fee-limit-threshold=100`
- `OP_BATCHER_TXMGR_FEE_LIMIT_THRESHOLD=100`
-
-
-### txmgr.receipt-query-interval
-
-Frequency to poll for receipts. The default value is `12s`.
-
-
- `--txmgr.receipt-query-interval=`
- `--txmgr.receipt-query-interval=12s`
- `OP_BATCHER_TXMGR_RECEIPT_QUERY_INTERVAL=12s`
-
-
-### txmgr.not-in-mempool-timeout
-
-Timeout for aborting a tx send if the tx does not make it to the mempool. The
-default value is `2m0s`.
-
-
- `--txmgr.not-in-mempool-timeout=`
- `--txmgr.not-in-mempool-timeout=2m0s`
- `OP_BATCHER_TXMGR_TX_NOT_IN_MEMPOOL_TIMEOUT=2m0s`
-
-
-### txmgr.send-timeout
-
-Timeout for sending transactions. If 0 it is disabled. The default value is
-`0s`.
-
-
- `--txmgr.send-timeout=`
- `--txmgr.send-timeout=0s`
- `OP_BATCHER_TXMGR_TX_SEND_TIMEOUT=0s`
-
-
-## Authentication and wallet
-
-### private-key
-
-The private key to use with the service. Must not be used with mnemonic.
-
-
- `--private-key=`
- `--private-key=`
- `OP_BATCHER_PRIVATE_KEY=`
-
-
-### mnemonic
-
-The mnemonic used to derive the wallets for either the service.
-
-
- `--mnemonic=`
- `--mnemonic=`
- `OP_BATCHER_MNEMONIC=`
-
-
-### hd-path
-
-The HD path used to derive the sequencer wallet from the mnemonic. The mnemonic
-flag must also be set.
-
-
- `--hd-path=`
- `--hd-path=`
- `OP_BATCHER_HD_PATH=`
-
-
+### altda.*
-### signer.address
-
-Address the signer is signing transactions for.
-
-
- `--signer.address=`
- `--signer.address=`
- `OP_BATCHER_SIGNER_ADDRESS=`
-
-
-### signer.endpoint
-
-Signer endpoint the client will connect to.
-
-
- `--signer.endpoint=`
- `--signer.endpoint=`
- `OP_BATCHER_SIGNER_ENDPOINT=`
-
-
-### signer.header
-
-Headers to pass to the remote signer. Format `key=value`.\
-Value can contain any character allowed in an HTTP header.\
-When using env vars, split multiple headers with commas.\
-When using flags, provide one key-value pair per flag.
-
-
- `--signer.header=`
- `--signer.header="Authorization=Bearer 123abc"`
- `OP_BATCHER_SIGNER_HEADER=Authorization=Bearer 123abc`
-
-
-### signer.tls.ca
-
-tls ca cert path. The default value is `tls/ca.crt`.
-
-
- `--signer.tls.ca=`
- `--signer.tls.ca=tls/ca.crt`
- `OP_BATCHER_SIGNER_TLS_CA=tls/ca.crt`
-
-
-### signer.tls.cert
-
-tls cert path. The default value is `tls/tls.crt`.
-
-
- `--signer.tls.cert=`
- `--signer.tls.cert=tls/tls.crt`
- `OP_BATCHER_SIGNER_TLS_CERT=`
-
-
-### signer.tls.key
-
-tls key. The default value is `tls/tls.key`.
-
-
- `--signer.tls.key=`
- `--signer.tls.key=tls/tls.key`
- `OP_BATCHER_SIGNER_TLS_KEY=`
-
-
-## Network connections
-
-### l1-eth-rpc
-
-HTTP provider URL for L1.
-
-
- `--l1-eth-rpc=`
- `--l1-eth-rpc`
- `OP_BATCHER_L1_ETH_RPC=`
-
-
-### l2-eth-rpc
-
-HTTP provider URL for L2 execution engine. A comma-separated list enables the
-active L2 endpoint provider. Such a list needs to match the number of
-rollup-rpcs provided.
-
-
- `--l2-eth-rpc=`
- `--l2-eth-rpc=`
- `OP_BATCHER_L2_ETH_RPC=`
-
-
-### rollup-rpc
-
-HTTP provider URL for Rollup node. A comma-separated list enables the active L2
-endpoint provider. Such a list needs to match the number of l2-eth-rpcs
-provided.
-
-
- `--rollup-rpc=`
- `--rollup-rpc=`
- `OP_BATCHER_ROLLUP_RPC=`
-
-
-### rpc.addr
-
-rpc listening address. The default value is `0.0.0.0`.
-
-
- `--rpc.addr=`
- `--rpc.addr=0.0.0.0`
- `OP_BATCHER_RPC_ADDR=0.0.0.0`
-
-
-### rpc.enable-admin
-
-Enable the admin API. The default value is `false`.
-
-
- `--rpc.enable-admin=`
- `--rpc.enable-admin=false`
- `OP_BATCHER_RPC_ENABLE_ADMIN=false`
-
-
-### rpc.port
-
-rpc listening port. The default value is `8545`.
-
-
- `--rpc.port=`
- `--rpc.port=8545`
- `OP_BATCHER_RPC_PORT=8545`
-
-
-### network-timeout
-
-Timeout for all network operations. The default value is `10s`.
-
-
- `--network-timeout=`
- `--network-timeout=10s`
- `OP_BATCHER_NETWORK_TIMEOUT=10s`
-
-
-## Alt-DA mode (Beta feature)
-
-### altda.enabled
-
-Enable Alt-DA mode, Alt-DA mode is a Beta feature of the OP Stack.
+The `altda.*` flags configure Alt-DA mode, a Beta feature of the OP Stack.
While it has received initial review from core contributors, it is still
-undergoing testing, and may have bugs or other issues.
-The default value is `false`.
-
-
- `--altda.enabled=`
- `--altda.enabled=false`
- `OP_BATCHER_ALTDA_ENABLED=false`
-
-
-### altda.da-server
-
-HTTP address of a DA Server.
-
-
- `--altda.da-server=`
- `--altda.da-server=http://da.example.com:1234`
- `OP_BATCHER_ALTDA_DA_SERVER=http://da.example.com:1234`
-
-
-### altda.da-service
-
-Use DA service type where commitments are generated by Alt-DA server. The default
-value is `false`.
-
-
- `--altda.da-service=`
- `--altda.da-service=true`
- `OP_BATCHER_ALTDA_DA_SERVER=true`
-
-
-### altda.get-timeout
-
-Timeout for get requests. **0 means no timeout**.
-
-
- `--altda.get-timeout=`
- `--altda.get-timeout=5s`
- `OP_BATCHER_ALTDA_GET_TIMEOUT=5s`
-
-
-### altda.put-timeout
-
-Timeout for put requests. **0 means no timeout**.
-
-
- `--altda.put-timeout=`
- `--altda.put-timeout=10s`
- `OP_BATCHER_ALTDA_PUT_TIMEOUT=10s`
-
-
-### altda.max-concurrent-da-requests
-
-Maximum number of concurrent requests to the DA server.
-
-
- `--altda.max-concurrent-da-requests=`
- `--altda.max-concurrent-da-requests=4`
- `OP_BATCHER_ALTDA_MAX_CONCURRENT_DA_REQUESTS=4`
-
-
-### altda.verify-on-read
-
-Verify input data matches the commitments from the DA storage service.
-
-
- `--altda.verify-on-read=`
- `--altda.verify-on-read=true`
- `OP_BATCHER_ALTDA_VERIFY_ON_READ=true`
-
-
-## Logging and monitoring
-
-### log.level
-
-The lowest log level that will be output. The default value is `INFO`.
-
-
- `--log.level=`
- `--log.level=INFO`
- `OP_BATCHER_LOG_LEVEL=INFO`
-
-
-### log.format
-
-Format the log output. Supported formats: 'text', 'terminal', 'logfmt', 'json',
-'json-pretty'. The default value is `text`.
-
-
- `--log.format=`
- `--log.format=text`
- `OP_BATCHER_LOG_FORMAT=text`
-
-
-### log.color
-
-Color the log output if in terminal mode. The default value is `false`.
-
-
- `--log.color=`
- `--log.color=false`
- `OP_BATCHER_LOG_COLOR=false`
-
-
-### log.pid
-
-Show PID in the log.
-
-
- `--log.pid=`
- `--log.pid=true`
- `OP_BATCHER_LOG_PID=true`
-
-
-### metrics.enabled
-
-Enable the metrics server. The default value is `false`.
-
-
- `--metrics.enabled=`
- `--metrics.enabled=false`
- `OP_BATCHER_METRICS_ENABLED=false`
-
-
-## Miscellaneous
-
-### active-sequencer-check-duration
-
-The duration between checks to determine the active sequencer endpoint. The
-default value is `2m0s`.
-
-
- `--active-sequencer-check-duration=`
- `--active-sequencer-check-duration=2m0s`
- `OP_BATCHER_ACTIVE_SEQUENCER_CHECK_DURATION=2m0s`
-
-
-### pprof.addr
-
-pprof listening address. The default value is `0.0.0.0`.
-
-
- `--pprof.addr=`
- `--pprof.addr=0.0.0.0`
- `OP_BATCHER_PPROF_ADDR=0.0.0.0`
-
-
-### pprof.enabled
-
-Enable the pprof server. The default value is `false`.
-
-
- `--pprof.enabled=`
- `--pprof.enabled=false`
- `OP_BATCHER_PPROF_ENABLED=false`
-
-
-### pprof.path
-
-pprof file path. If it is a directory, the path is `{dir}/{profileType}.prof`.
-
-
- `--pprof.path=`
- `--pprof.path=`
- `OP_BATCHER_PPROF_PATH=`
-
-
-### pprof.port
-
-pprof listening port. The default value is `6060`.
-
-
- `--pprof.port=`
- `--pprof.port=6060`
- `OP_BATCHER_PPROF_PORT=6060`
-
-
-### pprof.type
-
-pprof profile type. One of cpu, heap, goroutine, threadcreate, block, mutex,
-allocs.
-
-
- `--pprof.type=`
- `--pprof.type`
- `OP_BATCHER_PPROF_TYPE=`
-
-
-### help
-
-Show help. The default value is false.
-
-
- `--help=`
- `--help=false`
- `OP_BATCHER_HELP=false`
-
-
-### version
-
-Print the version. The default value is false.
-
-
- `--version=`
- `--version=false`
- `OP_BATCHER_VERSION=false`
-
+undergoing testing, and may have bugs or other issues. See the
+[Alt-DA mode guide](/chain-operators/guides/features/alt-da-mode-guide) for
+setup instructions.
diff --git a/docs/public-docs/scripts/gen-flags/README.md b/docs/public-docs/scripts/gen-flags/README.md
new file mode 100644
index 00000000000..fe6818a3fb7
--- /dev/null
+++ b/docs/public-docs/scripts/gen-flags/README.md
@@ -0,0 +1,107 @@
+# gen-flags — generated flag references for docs.optimism.io
+
+Generates the MDX flag-reference tables under `docs/public-docs/snippets/generated/`
+from the urfave/cli flag definitions the OP Stack Go services actually register.
+The docs pages import these snippets instead of hand-transcribing `--help`
+output, so the published flag catalogs cannot silently fall behind a release.
+
+## Usage
+
+Run from the monorepo root:
+
+```bash
+go run ./docs/public-docs/scripts/gen-flags
+```
+
+To verify the committed snippets match what the current source tree generates
+without rewriting them (exits nonzero on any difference):
+
+```bash
+go run ./docs/public-docs/scripts/gen-flags -check
+```
+
+The monorepo Go build embeds `op-core/superchain/superchain-configs.zip`
+(gitignored). On a fresh checkout, build it first:
+
+```bash
+just build-superchain-go
+```
+
+## How it works
+
+- `main.go` imports each component's composed flag slice (for op-batcher,
+ `op-batcher/flags.Flags` — including the op-service flag families appended in
+ its `init()`: rpc, log, metrics, pprof, txmgr, altda) and renders one snippet
+ per component: `snippets/generated/-flags.mdx`.
+- Flag name, usage, default, and environment variable come from urfave/cli's
+ own `DocGenerationFlag` accessors, so the output matches `--help` semantics.
+ Hidden flags are skipped.
+- `manifest.json` records the finalized release tag each snippet was generated
+ at (e.g. `op-batcher/v1.16.11`), and the snippet's provenance line names the
+ same tag. The two are updated together, only on regeneration.
+
+## Regenerating for a new release
+
+The snippets document *released* software, so regeneration is keyed to
+finalized release tags — not to every change on `develop`. When a new
+finalized (non-rc, non-pre-release) `op-batcher/v*` tag is published:
+
+1. Check out that tag — or, if working from another commit, verify the
+ flag-defining packages are identical to the tag first:
+ `op-batcher/flags/` and the flag families it appends (`op-service/rpc`,
+ `op-service/log`, `op-service/metrics`, `op-service/oppprof`,
+ `op-service/txmgr`, `op-alt-da`), e.g. with
+ `git diff HEAD -- `.
+2. Update the component's `tag` in `manifest.json` to the new release tag.
+3. Run the generator; the snippet and its provenance line are rewritten
+ together. Commit the manifest and snippet in the same change.
+
+Never hand-edit the generated snippets (`-check` fails on any hand edit), and
+never regenerate from unreleased code: if the flags changed since the manifest
+tag, the regenerated table would document behavior no released binary has.
+
+Enforcement runs as a review-gated Mintlify docs automation on a weekly
+schedule: it compares the newest finalized `op-batcher/v*` tag against the
+tag in `manifest.json` and, when a newer release exists, regenerates per the
+steps above and proposes the change for human review. Local runs of the
+generator (`-check` for verification) cover the gap between scheduled runs.
+
+## Adding a component
+
+1. Add the component's flag slice to the `components` table in `main.go`,
+ mirroring its required-flag names (the components keep their required
+ slices unexported; a runtime sanity check catches renames).
+2. Add its latest finalized release tag to `manifest.json`.
+3. Run the generator and import the new snippet from the component's
+ reference page.
+4. Extend the docs automation prompt to watch the new component's release
+ tag pattern.
+
+## Ownership
+
+Everything in this pipeline lives under `docs/public-docs/`, so it is covered
+by the existing CODEOWNERS rule
+(`/docs/public-docs/ @ethereum-optimism/solutions`) — no dedicated entries
+are needed. Per the ownership model in the Solutions repo's
+`projects/docs-improver/plans/option-b-truth-from-source.md`:
+
+| Artifact | Author of record | Reviewer | Stale-reference triage |
+| --- | --- | --- | --- |
+| Generator code + docs automation (this directory, the Mintlify automation config) | Matthew Cruz (@sbvegan), docs owner — proposed, pending confirmation | @ethereum-optimism/solutions (via the `/docs/public-docs/` CODEOWNERS rule) | Author of record |
+| Generated snippets (`snippets/generated/`) | The pipeline — nobody hand-edits; `-check` fails on hand edits by construction | @ethereum-optimism/solutions review the automation's regeneration PRs | A snippet that can't be regenerated cleanly is filed as an `accuracy`-labelled issue on the Solutions board |
+| Flag facts (`op-batcher/flags/`, op-service flag families) | Component engineers | Component team | Component team; the docs table follows at the next finalized release |
+
+Known residual gaps (accepted, by design):
+
+- The table documents the manifest release tag, not `develop`. Flag changes
+ merged after a release are intentionally not reflected until the next
+ finalized tag is published and the automation (or a maintainer) regenerates.
+- The required-flag list is mirrored in `main.go` because the components do
+ not export it. A rename fails the generator's sanity check; adding a brand
+ new required flag without updating the mirror would list it as optional.
+- op-batcher's `--compressor` option list (`compressor.KindKeys`) is built
+ from map iteration, so its order changes on every process start — in
+ `op-batcher --help` itself, not just here. The generator sorts that one
+ list (`canonicalizeUsage` in `main.go`) so output is deterministic; the
+ proper fix is sorting `KindKeys` at the source (one line in
+ `op-batcher/compressor/compressors.go`), proposed as a follow-up.
diff --git a/docs/public-docs/scripts/gen-flags/main.go b/docs/public-docs/scripts/gen-flags/main.go
new file mode 100644
index 00000000000..eba79276e58
--- /dev/null
+++ b/docs/public-docs/scripts/gen-flags/main.go
@@ -0,0 +1,285 @@
+// Command gen-flags generates MDX flag-reference tables for OP Stack Go
+// services from their urfave/cli flag definitions, so the docs flag catalogs
+// are derived from source instead of hand-transcribed from `--help` output.
+//
+// For each component listed in components below, the tool walks the composed
+// flag slice the binary actually registers (including the flag families
+// appended from op-service: rpc, log, metrics, pprof, txmgr, altda) and emits
+// a snippet into docs/public-docs/snippets/generated/. The snippet carries a
+// do-not-edit header and a provenance line naming the release tag recorded in
+// manifest.json.
+//
+// Run from the monorepo root:
+//
+// go run ./docs/public-docs/scripts/gen-flags
+//
+// Regeneration is keyed to finalized component releases: the snippets are
+// generated from the source at the release tag recorded in manifest.json and
+// refreshed when a new finalized (non-rc) tag is published — see README.md in
+// this directory for the procedure. Pass -check to verify the committed
+// snippets match what the current source tree generates without rewriting
+// them.
+package main
+
+import (
+ "encoding/json"
+ "flag"
+ "fmt"
+ "os"
+ "path/filepath"
+ "sort"
+ "strings"
+
+ "github.com/urfave/cli/v2"
+
+ batcherflags "github.com/ethereum-optimism/optimism/op-batcher/flags"
+)
+
+// component describes one service whose flags are rendered into a snippet.
+type component struct {
+ // name is the service name, e.g. "op-batcher". The snippet is written to
+ // /generated/-flags.mdx and the release tag is looked
+ // up under this key in manifest.json.
+ name string
+ // flags is the composed flag slice the binary registers.
+ flags []cli.Flag
+ // required lists the flag names the service's CheckRequired enforces.
+ // urfave/cli does not expose this (the components keep their required
+ // slices unexported), so it is mirrored here; a sanity check below
+ // verifies every listed name exists in the flag slice.
+ required []string
+}
+
+var components = []component{
+ {
+ name: "op-batcher",
+ flags: batcherflags.Flags,
+ // Mirrors requiredFlags in op-batcher/flags/flags.go.
+ required: []string{"l1-eth-rpc", "l2-eth-rpc", "rollup-rpc"},
+ },
+}
+
+// manifest maps component name -> finalized release tag recorded in the
+// provenance line, e.g. "op-batcher" -> "op-batcher/v1.16.11". The tag is
+// bumped, and the snippet regenerated, when a new finalized (non-rc)
+// component release is published.
+type manifest map[string]struct {
+ Tag string `json:"tag"`
+}
+
+type row struct {
+ name string
+ usage string
+ defaultText string
+ envVar string
+}
+
+func main() {
+ docsDir := flag.String("docs-dir", "docs/public-docs", "path to the docs root (run from the monorepo root)")
+ check := flag.Bool("check", false, "compare committed snippets against generated output instead of writing; exit nonzero on any difference")
+ flag.Parse()
+
+ docsRoot, err := filepath.Abs(filepath.Clean(*docsDir))
+ if err != nil {
+ fatalf("resolving docs dir %s: %v", *docsDir, err)
+ }
+
+ manifestPath, err := pathUnder(docsRoot, "scripts", "gen-flags", "manifest.json")
+ if err != nil {
+ fatalf("%v", err)
+ }
+ raw, err := os.ReadFile(manifestPath)
+ if err != nil {
+ fatalf("reading %s (run from the monorepo root): %v", manifestPath, err)
+ }
+ var m manifest
+ if err := json.Unmarshal(raw, &m); err != nil {
+ fatalf("parsing %s: %v", manifestPath, err)
+ }
+
+ outDir, err := pathUnder(docsRoot, "snippets", "generated")
+ if err != nil {
+ fatalf("%v", err)
+ }
+ if err := os.MkdirAll(outDir, 0o750); err != nil {
+ fatalf("creating %s: %v", outDir, err)
+ }
+
+ for _, c := range components {
+ entry, ok := m[c.name]
+ if !ok || entry.Tag == "" {
+ fatalf("no release tag for %q in %s", c.name, manifestPath)
+ }
+ outPath, err := pathUnder(docsRoot, "snippets", "generated", c.name+"-flags.mdx")
+ if err != nil {
+ fatalf("%v", err)
+ }
+ content, err := render(c, entry.Tag)
+ if err != nil {
+ fatalf("rendering %s: %v", c.name, err)
+ }
+ if *check {
+ committed, err := os.ReadFile(outPath)
+ if err != nil {
+ fatalf("reading committed snippet %s: %v", outPath, err)
+ }
+ if string(committed) != content {
+ fatalf("%s does not match generated output for %s (tag %s); regenerate per README.md", outPath, c.name, entry.Tag)
+ }
+ fmt.Printf("ok: %s matches generated output (%d flags, %s)\n", outPath, len(c.flags), entry.Tag)
+ continue
+ }
+ if err := os.WriteFile(outPath, []byte(content), 0o640); err != nil {
+ fatalf("writing %s: %v", outPath, err)
+ }
+ fmt.Printf("wrote %s (%d flags)\n", outPath, len(c.flags))
+ }
+}
+
+func render(c component, tag string) (string, error) {
+ requiredSet := make(map[string]bool, len(c.required))
+ for _, name := range c.required {
+ requiredSet[name] = true
+ }
+
+ var required, optional []row
+ seen := make(map[string]bool)
+ for _, f := range c.flags {
+ if vf, ok := f.(cli.VisibleFlag); ok && !vf.IsVisible() {
+ continue
+ }
+ df, ok := f.(cli.DocGenerationFlag)
+ if !ok {
+ return "", fmt.Errorf("flag %v does not implement cli.DocGenerationFlag", f.Names())
+ }
+ name := f.Names()[0]
+ if seen[name] {
+ return "", fmt.Errorf("duplicate flag name %q", name)
+ }
+ seen[name] = true
+ r := row{
+ name: name,
+ usage: canonicalizeUsage(c.name, name, df.GetUsage()),
+ defaultText: df.GetDefaultText(),
+ }
+ if envVars := df.GetEnvVars(); len(envVars) > 0 {
+ r.envVar = envVars[0]
+ }
+ if requiredSet[name] {
+ required = append(required, r)
+ } else {
+ optional = append(optional, r)
+ }
+ }
+
+ // Sanity check: every declared required flag must exist in the slice, so
+ // a rename in the component surfaces here instead of drifting silently.
+ for _, name := range c.required {
+ if !seen[name] {
+ return "", fmt.Errorf("required flag %q not found in %s flag definitions", name, c.name)
+ }
+ }
+
+ sort.Slice(required, func(i, j int) bool { return required[i].name < required[j].name })
+ sort.Slice(optional, func(i, j int) bool { return optional[i].name < optional[j].name })
+
+ var b strings.Builder
+ fmt.Fprintf(&b, `{/*
+ GENERATED FILE — DO NOT EDIT.
+
+ Generated by docs/public-docs/scripts/gen-flags from the %[1]s urfave/cli
+ flag definitions at the release tag below. Do not hand-edit; regenerate
+ per docs/public-docs/scripts/gen-flags/README.md when a new finalized
+ %[1]s release is published:
+
+ go run ./docs/public-docs/scripts/gen-flags
+*/}
+
+Generated from [`+"`%[2]s`"+`](https://github.com/ethereum-optimism/optimism/releases/tag/%[3]s)
+flag definitions. %[4]d flags: %[5]d required, %[6]d optional.
+
+`, c.name, tag, strings.ReplaceAll(tag, "/", "%2F"), len(required)+len(optional), len(required), len(optional))
+
+ b.WriteString("### Required flags\n\n")
+ b.WriteString("| Flag | Description | Environment variable |\n")
+ b.WriteString("| --- | --- | --- |\n")
+ for _, r := range required {
+ fmt.Fprintf(&b, "| `--%s` | %s | %s |\n", r.name, cell(r.usage), envCell(r.envVar))
+ }
+
+ b.WriteString("\n### Optional flags\n\n")
+ b.WriteString("| Flag | Description | Default | Environment variable |\n")
+ b.WriteString("| --- | --- | --- | --- |\n")
+ for _, r := range optional {
+ fmt.Fprintf(&b, "| `--%s` | %s | %s | %s |\n", r.name, cell(r.usage), defaultCell(r.defaultText), envCell(r.envVar))
+ }
+
+ return b.String(), nil
+}
+
+// canonicalizeUsage makes usage strings that are nondeterministic at the
+// source stable across runs, so regeneration is byte-stable. op-batcher
+// builds the --compressor option list from map iteration
+// (op-batcher/compressor.KindKeys via slices.Collect(maps.Keys(...))), so its
+// order changes on every process start — including in `op-batcher --help`
+// itself. Sort that one list here. Remove this once KindKeys is sorted
+// upstream (proposed as a follow-up to the B1 slice).
+func canonicalizeUsage(component, flagName, usage string) string {
+ if component == "op-batcher" && flagName == "compressor" {
+ const marker = "Valid options: "
+ if i := strings.Index(usage, marker); i >= 0 {
+ head, list := usage[:i+len(marker)], usage[i+len(marker):]
+ options := strings.Split(list, ", ")
+ sort.Strings(options)
+ return head + strings.Join(options, ", ")
+ }
+ }
+ return usage
+}
+
+// cell escapes a usage string for use inside an MDX table cell: newlines
+// become spaces, and characters MDX would treat as JSX or expression syntax
+// ({, }, <) or as a column separator (|) are escaped.
+func cell(s string) string {
+ s = strings.Join(strings.Fields(s), " ")
+ replacer := strings.NewReplacer(
+ "|", "\\|",
+ "{", "\\{",
+ "}", "\\}",
+ "<", "\\<",
+ )
+ return replacer.Replace(s)
+}
+
+func defaultCell(s string) string {
+ if s == "" {
+ return "—"
+ }
+ return "`" + strings.ReplaceAll(s, "|", "\\|") + "`"
+}
+
+func envCell(s string) string {
+ if s == "" {
+ return "—"
+ }
+ return "`" + s + "`"
+}
+
+// pathUnder joins elems onto root, cleans the result, and verifies the
+// resolved path still lies under root. Every path this tool reads or writes
+// is built from in-repo constants (component names from the components table,
+// manifest.json), not user input, but the check keeps a future bad component
+// name or docs-dir value from escaping the docs tree.
+func pathUnder(root string, elems ...string) (string, error) {
+ p := filepath.Clean(filepath.Join(append([]string{root}, elems...)...))
+ rel, err := filepath.Rel(root, p)
+ if err != nil || rel == ".." || strings.HasPrefix(rel, ".."+string(filepath.Separator)) {
+ return "", fmt.Errorf("path %s escapes docs dir %s", p, root)
+ }
+ return p, nil
+}
+
+func fatalf(format string, args ...any) {
+ fmt.Fprintf(os.Stderr, "gen-flags: "+format+"\n", args...)
+ os.Exit(1)
+}
diff --git a/docs/public-docs/scripts/gen-flags/manifest.json b/docs/public-docs/scripts/gen-flags/manifest.json
new file mode 100644
index 00000000000..2a8eeb8c351
--- /dev/null
+++ b/docs/public-docs/scripts/gen-flags/manifest.json
@@ -0,0 +1,5 @@
+{
+ "op-batcher": {
+ "tag": "op-batcher/v1.16.11"
+ }
+}
diff --git a/docs/public-docs/snippets/generated/op-batcher-flags.mdx b/docs/public-docs/snippets/generated/op-batcher-flags.mdx
new file mode 100644
index 00000000000..c76b497d9ec
--- /dev/null
+++ b/docs/public-docs/snippets/generated/op-batcher-flags.mdx
@@ -0,0 +1,110 @@
+{/*
+ GENERATED FILE — DO NOT EDIT.
+
+ Generated by docs/public-docs/scripts/gen-flags from the op-batcher urfave/cli
+ flag definitions at the release tag below. Do not hand-edit; regenerate
+ per docs/public-docs/scripts/gen-flags/README.md when a new finalized
+ op-batcher release is published:
+
+ go run ./docs/public-docs/scripts/gen-flags
+*/}
+
+Generated from [`op-batcher/v1.16.11`](https://github.com/ethereum-optimism/optimism/releases/tag/op-batcher%2Fv1.16.11)
+flag definitions. 87 flags: 3 required, 84 optional.
+
+### Required flags
+
+| Flag | Description | Environment variable |
+| --- | --- | --- |
+| `--l1-eth-rpc` | HTTP provider URL for L1 | `OP_BATCHER_L1_ETH_RPC` |
+| `--l2-eth-rpc` | HTTP provider URL for L2 execution engine. A comma-separated list enables the active L2 endpoint provider. Such a list needs to match the number of rollup-rpcs provided. | `OP_BATCHER_L2_ETH_RPC` |
+| `--rollup-rpc` | HTTP provider URL for Rollup node. A comma-separated list enables the active L2 endpoint provider. Such a list needs to match the number of l2-eth-rpcs provided. | `OP_BATCHER_ROLLUP_RPC` |
+
+### Optional flags
+
+| Flag | Description | Default | Environment variable |
+| --- | --- | --- | --- |
+| `--active-sequencer-check-duration` | The duration between checks to determine the active sequencer endpoint. | `5s` | `OP_BATCHER_ACTIVE_SEQUENCER_CHECK_DURATION` |
+| `--altda.da-server` | HTTP address of a DA Server | — | `OP_BATCHER_ALTDA_DA_SERVER` |
+| `--altda.da-service` | Use DA service type where commitments are generated by Alt-DA server | `false` | `OP_BATCHER_ALTDA_DA_SERVICE` |
+| `--altda.enabled` | Enable Alt-DA mode Alt-DA Mode is a Beta feature of the MIT licensed OP Stack. While it has received initial review from core contributors, it is still undergoing testing, and may have bugs or other issues. | `false` | `OP_BATCHER_ALTDA_ENABLED` |
+| `--altda.get-timeout` | Timeout for get requests. 0 means no timeout. | `0s` | `OP_BATCHER_ALTDA_GET_TIMEOUT` |
+| `--altda.max-concurrent-da-requests` | Maximum number of concurrent requests to the DA server | `1` | `OP_BATCHER_ALTDA_MAX_CONCURRENT_DA_REQUESTS` |
+| `--altda.put-timeout` | Timeout for put requests. 0 means no timeout. | `0s` | `OP_BATCHER_ALTDA_PUT_TIMEOUT` |
+| `--altda.verify-on-read` | Verify input data matches the commitments from the DA storage service | `true` | `OP_BATCHER_ALTDA_VERIFY_ON_READ` |
+| `--approx-compr-ratio` | The approximate compression ratio (\<= 1.0). Only relevant for ratio compressor. | `0.6` | `OP_BATCHER_APPROX_COMPR_RATIO` |
+| `--batch-type` | The batch type. 0 for SingularBatch and 1 for SpanBatch. | `singular` | `OP_BATCHER_BATCH_TYPE` |
+| `--check-recent-txs-depth` | Indicates how many blocks back the batcher should look during startup for a recent batch tx on L1. This can speed up waiting for node sync. It should be set to the verifier confirmation depth of the sequencer (e.g. 4). | `0` | `OP_BATCHER_CHECK_RECENT_TXS_DEPTH` |
+| `--compression-algo` | The compression algorithm to use. Valid options: zlib, brotli, brotli-9, brotli-10, brotli-11 | `zlib` | `OP_BATCHER_COMPRESSION_ALGO` |
+| `--compressor` | The type of compressor. Valid options: none, ratio, shadow | `"shadow"` | `OP_BATCHER_COMPRESSOR` |
+| `--data-availability-type` | The data availability type to use for submitting batches to the L1. Valid options: calldata, blobs, auto | `calldata` | `OP_BATCHER_DATA_AVAILABILITY_TYPE` |
+| `--fee-limit-multiplier` | The multiplier applied to fee suggestions to put a hard limit on fee increases | `5` | `OP_BATCHER_TXMGR_FEE_LIMIT_MULTIPLIER` |
+| `--hd-path` | The HD path used to derive the sequencer wallet from the mnemonic. The mnemonic flag must also be set. | — | `OP_BATCHER_HD_PATH` |
+| `--log.color` | Color the log output if in terminal mode | `false` | `OP_BATCHER_LOG_COLOR` |
+| `--log.format` | Format the log output. Supported formats: text, terminal, logfmt, logfmtms, json, jsonms | `text` | `OP_BATCHER_LOG_FORMAT` |
+| `--log.level` | The lowest log level that will be output | `INFO` | `OP_BATCHER_LOG_LEVEL` |
+| `--log.pid` | Show pid in the log | `false` | `OP_BATCHER_LOG_PID` |
+| `--max-blocks-per-span-batch` | Maximum number of blocks to add to a span batch. Default is 0 - no maximum. | `0` | `OP_BATCHER_MAX_BLOCKS_PER_SPAN_BATCH` |
+| `--max-channel-duration` | The maximum duration of L1-blocks to keep a channel open. 0 to disable. | `0` | `OP_BATCHER_MAX_CHANNEL_DURATION` |
+| `--max-l1-tx-size-bytes` | The maximum size of a batch tx submitted to L1. Ignored for blobs, where max blob size will be used. | `120000` | `OP_BATCHER_MAX_L1_TX_SIZE_BYTES` |
+| `--max-pending-tx` | The maximum number of pending transactions. 0 for no limit. | `1` | `OP_BATCHER_MAX_PENDING_TX` |
+| `--metrics.addr` | Metrics listening address | `"0.0.0.0"` | `OP_BATCHER_METRICS_ADDR` |
+| `--metrics.enabled` | Enable the metrics server | `false` | `OP_BATCHER_METRICS_ENABLED` |
+| `--metrics.port` | Metrics listening port | `7300` | `OP_BATCHER_METRICS_PORT` |
+| `--mnemonic` | The mnemonic used to derive the wallets for either the service | — | `OP_BATCHER_MNEMONIC` |
+| `--network-timeout` | Timeout for all network operations | `10s` | `OP_BATCHER_NETWORK_TIMEOUT` |
+| `--num-confirmations` | Number of confirmations which we will wait after sending a transaction | `10` | `OP_BATCHER_NUM_CONFIRMATIONS` |
+| `--poll-interval` | How frequently to poll L2 for new blocks | `6s` | `OP_BATCHER_POLL_INTERVAL` |
+| `--pprof.addr` | pprof listening address | `"0.0.0.0"` | `OP_BATCHER_PPROF_ADDR` |
+| `--pprof.enabled` | Enable the pprof server | `false` | `OP_BATCHER_PPROF_ENABLED` |
+| `--pprof.path` | pprof file path. If it is a directory, the path is \{dir\}/\{profileType\}.prof | — | `OP_BATCHER_PPROF_PATH` |
+| `--pprof.port` | pprof listening port | `6060` | `OP_BATCHER_PPROF_PORT` |
+| `--pprof.type` | pprof profile type. One of cpu, heap, goroutine, threadcreate, block, mutex, allocs | — | `OP_BATCHER_PPROF_TYPE` |
+| `--private-key` | The private key to use with the service. Must not be used with mnemonic. | — | `OP_BATCHER_PRIVATE_KEY` |
+| `--resubmission-timeout` | Duration we will wait before resubmitting a transaction to L1 | `48s` | `OP_BATCHER_RESUBMISSION_TIMEOUT` |
+| `--rpc.addr` | rpc listening address | `"0.0.0.0"` | `OP_BATCHER_RPC_ADDR` |
+| `--rpc.enable-admin` | Enable the admin API | `false` | `OP_BATCHER_RPC_ENABLE_ADMIN` |
+| `--rpc.port` | rpc listening port | `8545` | `OP_BATCHER_RPC_PORT` |
+| `--safe-abort-nonce-too-low-count` | Number of ErrNonceTooLow observations required to give up on a tx at a particular nonce without receiving confirmation | `3` | `OP_BATCHER_SAFE_ABORT_NONCE_TOO_LOW_COUNT` |
+| `--sequencer-hd-path` | DEPRECATED: The HD path used to derive the sequencer wallet from the mnemonic. The mnemonic flag must also be set. | — | `OP_BATCHER_SEQUENCER_HD_PATH` |
+| `--signer.address` | Address the signer is signing requests for | — | `OP_BATCHER_SIGNER_ADDRESS` |
+| `--signer.endpoint` | Signer endpoint the client will connect to | — | `OP_BATCHER_SIGNER_ENDPOINT` |
+| `--signer.header` | Headers to pass to the remote signer. Format `key=value`. Value can contain any character allowed in a HTTP header. When using env vars, split with commas. When using flags one key value pair per flag. | — | `OP_BATCHER_SIGNER_HEADER` |
+| `--signer.tls.ca` | tls ca cert path | `"tls/ca.crt"` | `OP_BATCHER_SIGNER_TLS_CA` |
+| `--signer.tls.cert` | tls cert path | `"tls/tls.crt"` | `OP_BATCHER_SIGNER_TLS_CERT` |
+| `--signer.tls.enabled` | Enable or disable TLS client authentication for the signer | `true` | `OP_BATCHER_SIGNER_TLS_ENABLED` |
+| `--signer.tls.key` | tls key | `"tls/tls.key"` | `OP_BATCHER_SIGNER_TLS_KEY` |
+| `--stopped` | Initialize the batcher in a stopped state. The batcher can be started using the admin_startBatcher RPC | `false` | `OP_BATCHER_STOPPED` |
+| `--sub-safety-margin` | The batcher tx submission safety margin (in #L1-blocks) to subtract from a channel's timeout and sequencing window, to guarantee safe inclusion of a channel on L1. | `10` | `OP_BATCHER_SUB_SAFETY_MARGIN` |
+| `--target-num-frames` | The target number of frames to create per channel. Controls number of blobs per blob tx, if using Blob DA. | `1` | `OP_BATCHER_TARGET_NUM_FRAMES` |
+| `--throttle.additional-endpoints` | Comma-separated list of endpoints to distribute throttling configuration to (in addition to the L2 endpoints specified with --l2-eth-rpc). | — | `OP_BATCHER_THROTTLE_ADDITIONAL_ENDPOINTS` |
+| `--throttle.block-size-lower-limit` | The limit on the DA size of blocks when we are at maximum throttle intensity (linear and quadratic controllers only). 0 means no limits will ever be applied, so consider 1 the smallest effective limit. | `2000` | `OP_BATCHER_THROTTLE_BLOCK_SIZE_LOWER_LIMIT` |
+| `--throttle.block-size-upper-limit` | The limit on the DA size of blocks when we are at 0 throttle intensity (applied when throttling is inactive) | `130000` | `OP_BATCHER_THROTTLE_BLOCK_SIZE_UPPER_LIMIT` |
+| `--throttle.controller-type` | Type of throttle controller to use: 'step', 'linear', 'quadratic' (default) or 'pid' (EXPERIMENTAL - use with caution) | `"quadratic"` | `OP_BATCHER_THROTTLE_CONTROLLER_TYPE` |
+| `--throttle.pid-integral-max` | EXPERIMENTAL: PID controller maximum integral windup. Only relevant if --throttle-controller-type is set to 'pid' | `1000` | `OP_BATCHER_THROTTLE_PID_INTEGRAL_MAX` |
+| `--throttle.pid-kd` | EXPERIMENTAL: PID controller derivative gain. Only relevant if --throttle-controller-type is set to 'pid' | `0.05` | `OP_BATCHER_THROTTLE_PID_KD` |
+| `--throttle.pid-ki` | EXPERIMENTAL: PID controller integral gain. Only relevant if --throttle-controller-type is set to 'pid' | `0.01` | `OP_BATCHER_THROTTLE_PID_KI` |
+| `--throttle.pid-kp` | EXPERIMENTAL: PID controller proportional gain. Only relevant if --throttle-controller-type is set to 'pid' | `0.33` | `OP_BATCHER_THROTTLE_PID_KP` |
+| `--throttle.pid-output-max` | EXPERIMENTAL: PID controller maximum output. Only relevant if --throttle-controller-type is set to 'pid' | `1` | `OP_BATCHER_THROTTLE_PID_OUTPUT_MAX` |
+| `--throttle.pid-sample-time` | EXPERIMENTAL: PID controller sample time interval, default is 2s | `2s` | `OP_BATCHER_THROTTLE_PID_SAMPLE_TIME` |
+| `--throttle.tx-size-lower-limit` | The limit on the DA size of transactions when we are at maximum throttle intensity. 0 means no limits will ever be applied, so consider 1 the smallest effective limit. | `150` | `OP_BATCHER_THROTTLE_TX_SIZE_LOWER_LIMIT` |
+| `--throttle.tx-size-upper-limit` | The limit on the DA size of transactions when we are at 0+ throttle intensity (limit of the intensity as it approaches 0 from positive values). Not applied when throttling is inactive. | `20000` | `OP_BATCHER_THROTTLE_TX_SIZE_UPPER_LIMIT` |
+| `--throttle.unsafe-da-bytes-lower-threshold` | The threshold on unsafe_da_bytes beyond which the batcher will start to throttle the block builder. Zero disables throttling. | `3200000` | `OP_BATCHER_THROTTLE_UNSAFE_DA_BYTES_LOWER_THRESHOLD` |
+| `--throttle.unsafe-da-bytes-upper-threshold` | Threshold on unsafe_da_bytes at which throttling has the maximum intensity (linear and quadratic controllers only) | `12800000` | `OP_BATCHER_THROTTLE_UNSAFE_DA_BYTES_UPPER_THRESHOLD` |
+| `--txmgr.already-published-custom-errs` | List of custom RPC error messages that indicate that a transaction has already been published. | — | `OP_BATCHER_TXMGR_ALREADY_PUBLISHED_CUSTOM_ERRS` |
+| `--txmgr.blob-tip-cap-dynamic` | Use dynamic blob tip cap from the blob tip oracle instead of static tip cap for blob transactions. Regular transactions still use min-tip-cap/max-tip-cap. | `false` | `OP_BATCHER_TXMGR_BLOB_TIP_CAP_DYNAMIC` |
+| `--txmgr.blob-tip-cap-percentile` | Percentile of recent blob tx tips to use for suggestion (1-100). Only used when blob-tip-cap-dynamic is enabled. | `60` | `OP_BATCHER_TXMGR_BLOB_TIP_CAP_PERCENTILE` |
+| `--txmgr.blob-tip-cap-range` | Number of recent blocks to analyze for blob tip cap distribution. Only used when blob-tip-cap-dynamic is enabled. | `20` | `OP_BATCHER_TXMGR_BLOB_TIP_CAP_RANGE` |
+| `--txmgr.cell-proof-time` | Enables cell proofs in blob transactions for Fusaka (EIP-7742) compatibility from the provided unix timestamp. Should be set to the L1 Fusaka time. May be left blank for Ethereum Mainnet, Sepolia, Holesky, or Hoodi L1s. | `18446744073709551615` | `OP_BATCHER_TXMGR_CELL_PROOF_TIME` |
+| `--txmgr.fee-limit-threshold` | The minimum threshold (in GWei) at which fee bumping starts to be capped. Allows arbitrary fee bumps below this threshold. | `100` | `OP_BATCHER_TXMGR_FEE_LIMIT_THRESHOLD` |
+| `--txmgr.max-basefee` | Enforces a maximum base fee (in GWei) to assume when determining tx fees, `TxMgr` returns an error when exceeded. Disabled by default. | `0` | `OP_BATCHER_TXMGR_MAX_BASEFEE` |
+| `--txmgr.max-retries` | Maximum number of times to resubmit a transaction to L1 on a transient error. Set to 0 to disable retries. | `10` | `OP_BATCHER_TXMGR_MAX_RETRIES` |
+| `--txmgr.max-tip-cap` | Enforces a maximum tip cap (in GWei) to use when determining tx fees, `TxMgr` returns an error when exceeded. Disabled by default. | `0` | `OP_BATCHER_TXMGR_MAX_TIP_CAP` |
+| `--txmgr.min-basefee` | Enforces a minimum base fee (in GWei) to assume when determining tx fees. 1 GWei by default. | `1` | `OP_BATCHER_TXMGR_MIN_BASEFEE` |
+| `--txmgr.min-tip-cap` | Enforces a minimum tip cap (in GWei) to use when determining tx fees. 1 GWei by default. | `1` | `OP_BATCHER_TXMGR_MIN_TIP_CAP` |
+| `--txmgr.not-in-mempool-timeout` | Timeout for aborting a tx send if the tx does not make it to the mempool. | `2m0s` | `OP_BATCHER_TXMGR_TX_NOT_IN_MEMPOOL_TIMEOUT` |
+| `--txmgr.rebroadcast-interval` | Interval at which a published transaction will be rebroadcasted if it has not yet been mined. Should be less than ResubmissionTimeout to have an effect. | `12s` | `OP_BATCHER_TXMGR_REBROADCAST_INTERVAL` |
+| `--txmgr.receipt-query-interval` | Frequency to poll for receipts | `12s` | `OP_BATCHER_TXMGR_RECEIPT_QUERY_INTERVAL` |
+| `--txmgr.retry-interval` | Duration we will wait before resubmitting a transaction to L1 on a transient error. Values \<= 0 will result in retrying immediately. Should be less than ResubmissionTimeout to have an effect. | `1s` | `OP_BATCHER_TXMGR_RETRY_INTERVAL` |
+| `--txmgr.send-timeout` | Timeout for sending transactions. If 0 it is disabled. | `0s` | `OP_BATCHER_TXMGR_TX_SEND_TIMEOUT` |
+| `--wait-node-sync` | Indicates if, during startup, the batcher should wait for a recent batcher tx on L1 to finalize (via more block confirmations). This should help avoid duplicate batcher txs. | `false` | `OP_BATCHER_WAIT_NODE_SYNC` |