The Problem with YAML and Linter Logic

Maintaining linters means anticipating developer workflows. For agent configuration files, specifically those using SKILL.md, AGENTS.md, and CLAUDE.md, a crucial rule mandates declaring external CLI dependencies. This prevents CI failures when a developer assumes a tool is globally available, but it isn't on the build agent.

The rule specifies that if an external CLI is called, it must be declared. The intended mechanism for this declaration is within the file's frontmatter, using a key like requires.

requires: codex

This single-string format works perfectly when there's only one dependency. However, YAML, by its nature, supports lists for collections. Developers following standard YAML practices would naturally represent multiple dependencies as a list. This leads to a structure like:

requires:
  - codex
  - gem

The Linter's Flaw

The linter, however, was not designed to handle this list format. It appears to have been programmed with a rigid expectation of a single string value for the requires key. Consequently, when it encountered the YAML list structure, it flagged it as an error. This is counterintuitive because the list format is not only valid YAML but the correct and idiomatic way to specify multiple requirements.

The linter's logic was failing to differentiate between a single dependency declared as a string and multiple dependencies declared as a list. Both are legitimate ways to specify requirements, but the linter treated the list as an invalid deviation from its expected single-string pattern. This resulted in the linter incorrectly warning the developers who were, in fact, adhering to best practices for managing multiple dependencies.

The author encountered this issue three times, each instance pointing in the same erroneous direction. This suggests a consistent misunderstanding in the linter's parsing or rule implementation regarding YAML's data structures. The consequence is that developers using the linter are penalized for writing more robust and scalable configuration files. They are forced to either ignore the warning, understanding it's a false positive, or contort their configuration into less conventional formats to appease the linter.

Why This Matters for Developers

This scenario highlights a common pitfall in tool development: over-optimization for a specific, narrow use case at the expense of broader compatibility and standard practices. The linter's goal is to ensure configurations are portable and don't break CI/CD pipelines. However, by failing to correctly interpret a standard YAML list for multiple dependencies, it actively hinders developers who are trying to manage complex projects with several external tools.

The expectation that all dependencies would be declared as a single string is a fragile assumption. As projects grow and incorporate more external CLIs or libraries, the single-string format quickly becomes unmanageable. The YAML list is the natural progression, offering clarity and ease of maintenance. When a linter flags this as an error, it creates friction and discourages good configuration hygiene.

Developers facing this issue are left with a few undesirable options:

  • Ignore the warning: This means living with a persistent, albeit false, error in their CI pipeline, which can be a distraction.
  • Workaround the linter: This might involve complex conditional logic or scripting to satisfy the linter's narrow interpretation, adding unnecessary complexity to the configuration itself.
  • Contribute a fix: For open-source linters, the burden falls on the user to identify the bug and submit a pull request, which requires understanding the linter's codebase and the nuances of YAML parsing.

The surprising detail here is not the existence of a linter bug, but that the bug specifically targets and penalizes the more scalable and idiomatic approach to dependency management within YAML configurations. It’s a case where the tool meant to enforce correctness is itself incorrect.

The Path Forward: A More Robust Linter

For the maintainers of this linter, the fix is straightforward: update the rule to correctly parse and validate YAML lists for the requires key. This involves a deeper understanding of YAML parsing libraries and how to distinguish between a single scalar value and a sequence.

The broader implication is a reminder for all tool developers. Linters, parsers, and configuration validation tools must be built with an awareness of common language idioms and data structures. Assuming a single, simple case when a more complex, standard structure is also prevalent leads to developer frustration and undermines the tool's utility. A linter should guide developers toward best practices, not penalize them for following them.

If you are a developer managing agent configurations, be aware that certain linters might flag valid YAML lists as errors. Verify the linter's behavior and consider contributing to open-source projects if you encounter such issues. This is how we collectively build better tools.