Open Object Manager on any org that's been live for a few years, click into a real object, and scroll the field list. Most of the Description column is blank. Not because anyone decided documentation didn't matter, but because Salesforce gives you no way to fill it in at scale and a genuinely tedious way to fill it in one field at a time. So it never happens, and the org's knowledge stays in the head of whoever built it.
This is two problems wearing one coat. The first is mechanical: there's no native bulk edit, so how do you write to hundreds of fields without clicking into each one. The second is the actual work: someone has to compose hundreds of accurate descriptions. Almost every guide solves the first and pretends the second isn't the reason you stalled. The second is the reason you stalled.
Before either, get the two fields straight, because people fill in the wrong one constantly.
Description and Help Text are not the same field
They look similar in Object Manager and they serve opposite audiences.
Description is admin-facing. It's documentation for whoever maintains the org — what the field is for, where its value comes from, which automation reads it, whether it's safe to delete. End users never see it. You get 1,000 characters, and it's editable on custom fields.
Help Text (the inline, field-level help) is user-facing. It's the tooltip that appears when someone hovers the info icon on a record. It maxes out at 510 characters, and you can set it on standard and managed-package fields too, not just custom ones.
The rule of thumb worth internalizing: Help Text says what a field is for to the person typing in it; Description says how it works to the person who has to maintain it. If your goal is internal documentation, onboarding the next admin, or giving downstream AI cleaner metadata to read, Description is the field you're filling. If your goal is reducing user error on a confusing field, that's Help Text. This post is about Description, but the mechanics below apply to both, and a serious cleanup usually touches both.
Two caveats to set expectations before you start. Fields from managed packages are frequently locked, so you may not be able to edit their Description at all. And standard fields don't expose an editable Description the way custom fields do; for those, Help Text is your only lever. So "every field" in practice means "every field you own," which is still most of the sprawl.
Help Text tells the user filling a field what it's for. Description tells the admin who has to maintain it how it works.
First, find the blanks — describe won't tell you
You'd think the describe call would hand you a tidy list of fields and their descriptions. It won't. The standard describe returns a lot about each field — type, length, picklist values, inline help — but not the Description. That's the single most common reason people think this data is harder to get at than it is.
The Description lives in the metadata layer, and the Tooling API reads it. Query FieldDefinition and you can pull every field on an object with its description, which lets you isolate exactly what's blank:
SELECT QualifiedApiName, Description
FROM FieldDefinition
WHERE EntityDefinition.QualifiedApiName = 'Account'
One gotcha that signals you know the platform: FieldDefinition can't be queried across the whole org in a single statement — you have to scope it to an EntityDefinition, so this runs per object and you iterate across your object list. Tedious to script, but it gives you a clean inventory of every blank Description to work from, which is the thing you actually need before you write anything.
The bulk-edit mechanism
There's no button for this. The supported way to write descriptions in bulk is the Metadata API: retrieve the field metadata, edit it, deploy it back.
In practice that means pulling the field files with the Salesforce CLI (sf project retrieve), editing the <description> element in each .field-meta.xml, and deploying with sf project deploy. A field file is straightforward XML:
<CustomField xmlns="http://soap.sforce.com/2006/04/metadata">
<fullName>Region__c</fullName>
<description>Sales territory region. Set by the lead-routing flow on conversion; read by the territory assignment rules. Safe to retire only if routing moves off this field.</description>
<type>Picklist</type>
</CustomField>
If the command line isn't your environment, Workbench will retrieve and deploy the same metadata through the browser, and there are AppExchange tools that let you edit descriptions from a spreadsheet and push the changes back. Pick whichever matches how you work. They all do the same job: move text into many fields at once.
And here's the catch every one of them shares. None of them writes the descriptions for you. The CLI, Workbench, the spreadsheet tool — they're all delivery mechanisms for content that has to already exist. Which is the wall you hit the first time.
The actual wall: writing them
Filling in one description is easy. Filling in four hundred is a multi-day slog, and it's worse than it sounds because the fields that most need documenting are the ones whose names tell you nothing. Region__c you can probably guess. Field_2__c, X_Status_New__c, Legacy_Flag_DNU__c — those are exactly the fields a new admin needs explained, and they're exactly the ones where you, today, have to go reconstruct the meaning from scratch: check the type, look at the picklist values, find what references the field, see whether it's even populated, then write a sentence. Times four hundred. This is the step where the project dies, every time.
So the real question isn't "how do I push descriptions in bulk." You've got three ways to do that. It's "how do I produce four hundred accurate descriptions without spending a week on it."
The shortcut, and where you still have to look
This is the gap SchemaForce closes. It generates a draft Description for each field from the context the field already carries — its name, type, picklist values, the relationships and automation that reference it, whether it's actually used — so instead of authoring from a blank box you're reviewing a proposed sentence and either accepting it or fixing it. Then you push the approved set back through the Metadata API. It reads schema and configuration only, never the contents of records, so you can run it against production without it touching a single customer value.
The honest part: review is not optional, and I'd distrust any tool that implies it is. For a field named Region__c with a clean picklist, a generated draft is usually right. For Field_2__c, the model has nothing real to work from — the name carries no signal — and it will produce a plausible guess that may be wrong. A confidently wrong description is worse than a blank one, because the next admin will trust it. So the workflow that actually works is generate, then review with a sharper eye on the cryptic fields than the obvious ones. That still collapses a multi-day job into an afternoon, which is the only reason it gets done at all.
One note on the AI angle, kept honest
You'll see a lot of pressure right now to populate descriptions so that Agentforce and other AI features understand your org better. That's real — populated metadata does give downstream AI cleaner context to ground on. But don't let it turn a useful chore into a governance crusade you'll never finish. The immediate, certain payoff of filling in your descriptions is human: the next admin who inherits this org, the auditor who asks what a field is for, the teammate debugging an automation at 5pm. The AI benefit is a genuine bonus on top of that. Fill them in for the humans, and the models get the upside for free.
Order of operations
- Decide which field you're filling.
Descriptionfor internal documentation, Help Text for user guidance. Usually both, but they're different jobs. - Inventory the blanks via the Tooling API's
FieldDefinition, scoped per object.describewon't show you descriptions. - Generate drafts from each field's own context rather than authoring from scratch — this is the step that decides whether the project finishes.
- Review, hardest on the cryptically-named fields where the source signal is weakest.
- Deploy in bulk through the Metadata API, with the CLI, Workbench, or a spreadsheet tool.
- Skip what you can't edit — managed-package fields and standard-field descriptions — and use Help Text where that's the only lever.
Do it in that order and the blank Description column stops being the thing you keep meaning to get to.



