ft sync runs runMediaFetchWithProgress automatically after the bookmark sync completes (unless --no-media is passed). The standalone ft fetch-media command accepts --limit <n> for capping how many pending bookmarks' media gets fetched in one run — but ft sync doesn't surface the equivalent, so ft sync always fetches all pending media in one shot.
For users with large media backlogs (e.g., after a --rebuild, or a first sync against a corpus with thousands of un-downloaded items), this either blocks for a long time or runs into rate limits. The workaround is ft sync --no-media && ft fetch-media --limit <n> as two commands; surfacing the flag on sync directly would match the existing ft fetch-media --limit contract and let downstream tools (CLI users, third-party wrappers) cap a single ft sync invocation.
The plumbing already exists
The helper runMediaFetchWithProgress at src/cli.ts:207 already accepts the limit parameter:
async function runMediaFetchWithProgress(
options: { limit?: number; maxBytes?: number; skipProfileImages?: boolean } = {}
): Promise<MediaFetchManifest>
ft fetch-media invokes it WITH limit (src/cli.ts:1515-1521):
await runMediaFetchWithProgress({
limit: typeof options.limit === 'number' && !Number.isNaN(options.limit) ? options.limit : undefined,
maxBytes: ...,
skipProfileImages: ...,
});
ft sync invokes it WITHOUT limit (src/cli.ts:800):
const postSyncMediaFetch = async (): Promise<void> => {
if (!downloadMedia) return;
await runMediaFetchWithProgress({
maxBytes: mediaMaxBytes,
skipProfileImages: Boolean(options.skipProfileImages),
});
console.log('');
};
No limit field passed → runMediaFetchWithProgress defaults to unlimited.
ft sync's current flag list (around src/cli.ts:740-742) has --no-media, --media-max-bytes, --skip-profile-images — but no media-limit equivalent.
Suggested fix
Two changes in src/cli.ts:
- Add the option to the
ft sync command definition, mirroring the existing --media-max-bytes shape:
.option('--media-limit <n>', 'Cap on pending bookmarks whose media gets fetched after sync (default: all)', (v: string) => Number(v))
- Pass it through at line 800:
await runMediaFetchWithProgress({
limit: typeof options.mediaLimit === 'number' && !Number.isNaN(options.mediaLimit) ? options.mediaLimit : undefined,
maxBytes: mediaMaxBytes,
skipProfileImages: Boolean(options.skipProfileImages),
});
That's the full change — the helper already does the right thing with limit: undefined (unlimited) vs a number (cap). No new logic, no schema, no migration.
Naming nit
--media-limit mirrors the existing --media-max-bytes (both media- prefixed on the sync command, distinguishing them from bookmark-pagination flags like --max-pages). Could also be --media-batch <n> or --fetch-limit <n> — maintainer's call.
ft syncrunsrunMediaFetchWithProgressautomatically after the bookmark sync completes (unless--no-mediais passed). The standaloneft fetch-mediacommand accepts--limit <n>for capping how many pending bookmarks' media gets fetched in one run — butft syncdoesn't surface the equivalent, soft syncalways fetches all pending media in one shot.For users with large media backlogs (e.g., after a
--rebuild, or a first sync against a corpus with thousands of un-downloaded items), this either blocks for a long time or runs into rate limits. The workaround isft sync --no-media && ft fetch-media --limit <n>as two commands; surfacing the flag on sync directly would match the existingft fetch-media --limitcontract and let downstream tools (CLI users, third-party wrappers) cap a singleft syncinvocation.The plumbing already exists
The helper
runMediaFetchWithProgressatsrc/cli.ts:207already accepts thelimitparameter:ft fetch-mediainvokes it WITHlimit(src/cli.ts:1515-1521):ft syncinvokes it WITHOUTlimit(src/cli.ts:800):No
limitfield passed →runMediaFetchWithProgressdefaults to unlimited.ft sync's current flag list (aroundsrc/cli.ts:740-742) has--no-media,--media-max-bytes,--skip-profile-images— but no media-limit equivalent.Suggested fix
Two changes in
src/cli.ts:ft synccommand definition, mirroring the existing--media-max-bytesshape:That's the full change — the helper already does the right thing with
limit: undefined(unlimited) vs a number (cap). No new logic, no schema, no migration.Naming nit
--media-limitmirrors the existing--media-max-bytes(bothmedia-prefixed on the sync command, distinguishing them from bookmark-pagination flags like--max-pages). Could also be--media-batch <n>or--fetch-limit <n>— maintainer's call.