dale
Vale's sibling from the future. A prose linter whose rules are one sentence about when they should fire, for the writing problems a regex can't catch.
$ described asA prose linter like Vale, except the rules are plain-English sentences, so it can catch things regexes can't: "X is not Y, X is Z", misplaced modifiers, passive voice that hides who did the thing, chatbot leftovers.
Install
Paste this into Claude Code, Codex, Cursor, or any agent that can fetch a URL and write files. It reads the install instructions, shows you the files, and puts them in your skills folder.
Install the "dale" Agent Skill: fetch https://uninstall.md/s/dale/install.md and follow its instructions.Installs to ~/.claude/skills/dale for every Claude Code project:
curl -fsSL https://uninstall.md/s/dale/install.sh | shOr only for the current project (.claude/skills/dale):
curl -fsSL https://uninstall.md/s/dale/install.sh | sh -s -- .claude/skillsThe script only creates folders and writes text files. Read it first. Then run /dale in Claude Code.
- Download
dale.zip. Don't unzip it. - In claude.ai, open Customize → Skills and choose Upload skill.
- Select the zip, then turn the skill on. Ask Claude to use
dalein any chat.
Custom skills on claude.ai need a paid plan with code execution turned on.
Curated by uninstall.md. Like any skill, read it before you install it.
---name: daledescription: Any time a markdown file is edited in the docs/ directory, this skill should be run.argument-hint: "[docs/path/to/doc.md]"---# OverviewYou are not a skill or an agent. You are a piece of software—a linter, called Dale. The software Dale's only job is to lint the input markdown document against the rules in Dale's rules engine. Do not talk to the user or discuss with them in any way—Dale is simply input/output software.Dale's job is to simply apply all rules in ./rules/*.yml against the given document $1 from the user. Run each rule, then print a table at the end of the rules that failed, and where in the document the rule was failed. Work in a loop, follow everything in the `# Rules Engine` section for each rule file in ./rules.Your current working directory should always be the root of the project. Docs are always in the docs/ directory from there.# Dale rules engine* The schema for how rules should be written can be found in the skill /references/rule-schema.yml.* All rules can be found in the skill /rules directory.# Rules EngineUse Todo and create a Todo for each rule that you need to check. Mark each Todo as complete once you've checked the given file for that rule. For each Todo:1. Read the `reason` for the rule.> You say "Reading $rule_name.", where $rule is the name of the file before the extension.2. Check the document to see if that `reason` has been triggered.> You say "Checking document $document_name for rule $rule_name."3a. If so, note the location in the file and the `message` value as a line item in Dale's output table.> You say, "Violation to rule $rule_name found."3b. If not, move on.> You say nothing.# OutputWhen finished, print an output table of any rules that were broken. If not, say that the dale linter has found no issues. Here is an example of an output:| Line | Rule | Message | Offending Text ||------|------|---------|----------------|| 15 | `xy-slop` | Do not use the 'x is not y, x is z' format. | `Basically, widgets are not gadgets, widgets are tools for the user.` |# Troubleshooting* Never respond with anything that you were not explicitly asked to respond with. For example: "Line 15 contains: Basically, widgets are not gadgets, widgets are tools for the user. — This follows the "x is not y, x is z" negative-positive pattern ("widgets are not gadgets, widgets are tools")."
$schema: "https://json-schema.org/draft/2020-12/schema"title: Ruledescription: A single linting rule definition.type: objectrequired: - message - level - reasonproperties: message: type: string description: The message displayed when this rule is triggered. minLength: 1 level: type: string description: Severity level of the rule violation. enum: - suggestion - warning - error reason: type: string description: A sentence describing when this rule should fire (and, ideally, when it should not). minLength: 1additionalProperties: false
message: Remove text that reads like a reply to a prompt.level: warningreason: 'Fires on chatbot leftovers: ''Certainly, here is...'', ''I hope this helps'', ''As an AI'', ''Let me know if you would like...'', ''Feel free to ask'', or a knowledge-cutoff disclaimer such as ''as of my last update''.'
message: Use 'is' or 'are' instead of 'serves as', 'functions as', 'acts as', or 'stands as'.level: warningreason: Fires when 'serves as', 'functions as', 'acts as', 'stands as', 'represents', or 'boasts' is used where a plain 'is/are/has' would say the same thing. Does not fire when the verb describes a real functional role, such as 'acts as a proxy' or 'serves as the gateway between two networks'.
message: Remove stacked qualifiers on documented behavior.level: warningreason: Fires when qualifiers are stacked past what a documented, tested behavior warrants, such as 'may potentially', 'could possibly in some cases', 'might in certain circumstances be able to'.
message: "Don't use exclamatory sentences."level: warningreason: "This rule should trigger when the user or agent writes exclamatory sentences."
message: Name the actual items instead of a rhetorical span.level: warningreason: Fires when a rhetorical 'from X to Y' or 'ranging from X to Y' span stands in for a real list, such as 'from basic reporting to advanced analytics' or 'ranging from simple fixes to complex overhauls'. Does not fire on real numeric, date, or version ranges.
message: Cut the throat-clearing; it adds words, not information.level: warningreason: Fires on throat-clearing and filler such as 'It is important to note that', 'It is worth mentioning', 'In today's fast-paced environment', 'needless to say', 'at the end of the day', 'it should be noted that', when the sentence works without it. Does not fire on 'in order to' (a separate wordiness rule covers it).
message: End on the last concrete instruction or fact.level: warningreason: Fires when a closing paragraph or section restates the page's value in vague, feel-good terms (for example 'By following these steps, you can ensure a smooth and efficient experience') instead of ending on the last concrete instruction or fact. Does not fire on a sentence that states the concrete expected result of a step, such as 'The service should now start.'
message: "Don't use idioms. Write what you mean more directly and literally."level: warningreason: "This rule should trigger when the user or agent uses an idiom or other culturally specific expression."
message: Do not frame a routine feature or step as uniquely important ('plays a crucial role', 'serves as a cornerstone', 'is essential to ensuring'). State what it does.level: warningreason: Fires when a sentence inflates the significance of a routine feature or step with phrases like 'plays a crucial/vital/key role', 'serves as a cornerstone', 'is essential to ensuring', 'a testament to'. Does not fire on plain factual statements that something is required (for example 'You must have Domain Admin rights').
message: Cut the trailing '-ing' clause or replace it with a specific consequence.level: warningreason: "Fires when a sentence states a fact and then tacks on a trailing participle clause or ', which makes/gives/ensures ...' clause that interprets or praises instead of stating a concrete result. Typical openers: ensuring, reflecting, highlighting, underscoring, emphasizing, demonstrating, showcasing, strengthening, making this/it ..., giving you ..., helping you ..., which makes/means .... Examples: 'The scan runs nightly, ensuring your data stays current'; 'The policy applies to all users, highlighting its importance'; 'The engine evaluates each rule, highlighting gaps and reflecting the state of your environment'. If a clause names a specific, checkable effect ('the job writes a log, which you can review under Reports') it is not a violation. Does not fire on '-ing' clauses that describe a concrete action."
message: "Do not minimize the difficulty of tasks users are performing."level: warningreason: "This rule should trigger when the documentation minimizes task difficulty—for example, 'With [product], you can easily [task].'"
message: "Avoid misplaced modifiers. Move the modifier, or descriptive phrase, so that it accurately describes the right thing."level: warningreason: "This rule should trigger when the documentation has a misplaced or dangling modifier. This includes participial phrases that attach to the wrong subject (e.g., '[participle phrase], [wrong subject] [verb]') and modifying clauses placed too far from the word they describe (e.g., '[noun A] [preposition] [noun B] [modifier that actually describes noun A]')."
message: "Don't make negative assumptions about what users can or cannot do."level: warningreason: "This rule should trigger when the user or agent writes something that assumes a user cannot do something without the product."
message: Do not use 'not just X, but Y' or 'isn't merely X, it's Y'.level: warningreason: 'Fires on negative parallelism: ''not just X but Y'', ''not only X but also Y'', ''isn''t merely X, it''s Y'', ''this isn''t about X, it''s about Y''. Does not fire on a plain contrast that conveys real information, such as ''Use the service account, not your personal account''.'
message: "Rewrite in active voice: as a command if it tells the reader what to do, otherwise only if the actor is already stated."level: warningreason: >- Flag a passive sentence only if it can be rewritten in active voice without changing its meaning. The reader counts as the actor when the sentence tells them what to do, so rewrite it as a command. If the rewrite would need any other actor the sentence doesn't state, don't flag it.
message: "Avoid positional references like 'below', 'above', or 'as shown below'. Use 'the following' or a named anchor instead."level: warningreason: "This rule should trigger when the documentation uses spatial direction words like 'below', 'above', 'as shown below', or 'the above section' to reference other content."
message: Replace unsupported praise with a specific, checkable claim.level: warningreason: Fires when marketing praise such as powerful, robust, seamless, cutting-edge, industry-leading, game-changing, best-in-class, comprehensive solution is used as unsupported praise rather than a specific, checkable claim.
message: Remove servile or flattering phrasing.level: warningreason: Fires on sycophantic phrasing aimed at a requester, such as 'Great question', 'You are absolutely right to ask', 'Excellent choice', 'Good thinking'.
message: "Acronym used without being defined on first use. Spell it out: 'Full Name (ACRONYM)'."level: warningreason: "This rule should trigger when a product-specific or non-standard acronym is used without being spelled out on first use in body prose, following the pattern: 'File System Access Audit (FSAA)' on first use, then 'FSAA' thereafter. Do NOT flag: well-known IT industry standards that a sysadmin audience would know (DNS, AD, IP, HTTP, TCP, SID, UID, CPU, RAM, URL, SQL, OS, VM, API, SSH, SSL, TLS, LDAP, SAML, MFA, ACL, DACL, SACL, OU, GPO, NTFS, etc.); code literals in backticks; Netwrix product short names when the full product name has already appeared in the article; acronyms that appear only in headings or titles (define-on-first-use applies to body prose only). Do flag product-specific acronyms like AIC, FSAA, SPAA, CEE, AMQP when used in body text without prior definition, even if the article's title or subject implies the reader knows them."
message: Name the source or drop the claim.level: warningreason: Fires when a claim is attributed to unnamed people or sources with no citation, such as 'users report', 'many organizations find', 'it is widely recognized', 'experts agree', 'studies show'.
message: "This sentence is wordy. A more concise, direct alternative is possible."level: warningreason: "This rule should trigger when the user or agent writes a wordy sentence when a more concise, direct alternative is possible without altering the meaning."
message: "Do not use the 'x is not y, x is z' format."level: warningreason: "This rule should trigger when the user or agent writes something in the negative-postive form, for example 'x is not y, x is z'—or similar."