diff --git a/README.md b/README.md
index 81129527c6..6d9d1d44a1 100644
--- a/README.md
+++ b/README.md
@@ -189,15 +189,16 @@ rules in templates can be disabled with eslint directives with mustache or html
### Best Practices
-| Name | Description | 💼 | 🔧 | 💡 |
-| :----------------------------------------------------------------------------------------------------- | :-------------------------------------------------------- | :- | :- | :- |
-| [template-builtin-component-arguments](docs/rules/template-builtin-component-arguments.md) | disallow setting certain attributes on builtin components | | | |
-| [template-no-action-modifiers](docs/rules/template-no-action-modifiers.md) | disallow usage of {{action}} modifiers | | | |
-| [template-no-arguments-for-html-elements](docs/rules/template-no-arguments-for-html-elements.md) | disallow @arguments on HTML elements | | | |
-| [template-no-array-prototype-extensions](docs/rules/template-no-array-prototype-extensions.md) | disallow usage of Ember Array prototype extensions | | | |
-| [template-no-block-params-for-html-elements](docs/rules/template-no-block-params-for-html-elements.md) | disallow block params on HTML elements | | | |
-| [template-no-debugger](docs/rules/template-no-debugger.md) | disallow {{debugger}} in templates | | | |
-| [template-no-log](docs/rules/template-no-log.md) | disallow {{log}} in templates | | | |
+| Name                                      | Description | 💼 | 🔧 | 💡 |
+| :----------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------- | :- | :- | :- |
+| [template-builtin-component-arguments](docs/rules/template-builtin-component-arguments.md) | disallow setting certain attributes on builtin components | | | |
+| [template-no-action-modifiers](docs/rules/template-no-action-modifiers.md) | disallow usage of {{action}} modifiers | | | |
+| [template-no-arguments-for-html-elements](docs/rules/template-no-arguments-for-html-elements.md) | disallow @arguments on HTML elements | | | |
+| [template-no-array-prototype-extensions](docs/rules/template-no-array-prototype-extensions.md) | disallow usage of Ember Array prototype extensions | | | |
+| [template-no-block-params-for-html-elements](docs/rules/template-no-block-params-for-html-elements.md) | disallow block params on HTML elements | | | |
+| [template-no-capital-arguments](docs/rules/template-no-capital-arguments.md) | disallow capital arguments (use lowercase @arg instead of @Arg) | | | |
+| [template-no-debugger](docs/rules/template-no-debugger.md) | disallow {{debugger}} in templates | | | |
+| [template-no-log](docs/rules/template-no-log.md) | disallow {{log}} in templates | | | |
### Components
diff --git a/docs/rules/template-no-capital-arguments.md b/docs/rules/template-no-capital-arguments.md
new file mode 100644
index 0000000000..e2048ec247
--- /dev/null
+++ b/docs/rules/template-no-capital-arguments.md
@@ -0,0 +1,43 @@
+# ember/template-no-capital-arguments
+
+
+
+Disallow capital letters in argument names. Use lowercase argument names (e.g., `@arg` instead of `@Arg`).
+
+## Rule Details
+
+This rule enforces the convention that argument names should start with lowercase letters.
+
+## Examples
+
+Examples of **incorrect** code for this rule:
+
+```gjs
+
+ {{@Arg}}
+
+```
+
+```gjs
+
+ {{@MyArgument}}
+
+```
+
+Examples of **correct** code for this rule:
+
+```gjs
+
+ {{@arg}}
+
+```
+
+```gjs
+
+ {{@myArgument}}
+
+```
+
+## References
+
+- [Ember Style Guide](https://github.com/ember-cli/ember-styleguide)
diff --git a/lib/rules/template-no-capital-arguments.js b/lib/rules/template-no-capital-arguments.js
new file mode 100644
index 0000000000..fe93bbb03d
--- /dev/null
+++ b/lib/rules/template-no-capital-arguments.js
@@ -0,0 +1,47 @@
+/** @type {import('eslint').Rule.RuleModule} */
+module.exports = {
+ meta: {
+ type: 'suggestion',
+ docs: {
+ description: 'disallow capital arguments (use lowercase @arg instead of @Arg)',
+ category: 'Best Practices',
+ recommended: false,
+ url: 'https://github.com/ember-cli/eslint-plugin-ember/tree/master/docs/rules/template-no-capital-arguments.md',
+ },
+ fixable: null,
+ schema: [],
+ messages: {
+ noCapitalArguments:
+ 'Argument names should start with lowercase. Use @{{lowercase}} instead of @{{name}}.',
+ },
+ strictGjs: true,
+ strictGts: true,
+ },
+
+ create(context) {
+ function checkPath(node, path) {
+ if (!path || !path.head) {
+ return;
+ }
+
+ const name = path.head.name || path.head;
+ if (typeof name === 'string' && name.startsWith('@') && /^@[A-Z]/.test(name)) {
+ const lowercase = name.charAt(0) + name.charAt(1).toLowerCase() + name.slice(2);
+ context.report({
+ node,
+ messageId: 'noCapitalArguments',
+ data: {
+ name,
+ lowercase,
+ },
+ });
+ }
+ }
+
+ return {
+ GlimmerPathExpression(node) {
+ checkPath(node, node);
+ },
+ };
+ },
+};
diff --git a/tests/lib/rules/template-no-capital-arguments.js b/tests/lib/rules/template-no-capital-arguments.js
new file mode 100644
index 0000000000..9886b5f01d
--- /dev/null
+++ b/tests/lib/rules/template-no-capital-arguments.js
@@ -0,0 +1,73 @@
+const { RuleTester } = require('eslint');
+const rule = require('../../../lib/rules/template-no-capital-arguments');
+
+const ruleTester = new RuleTester({
+ parser: require.resolve('ember-eslint-parser'),
+ parserOptions: { ecmaVersion: 2022, sourceType: 'module' },
+});
+
+ruleTester.run('template-no-capital-arguments', rule, {
+ valid: [
+ {
+ filename: 'my-component.gjs',
+ code: `
+ import Component from '@glimmer/component';
+ export default class MyComponent extends Component {
+
+ {{@arg}}
+
+ }
+ `,
+ output: null,
+ },
+ {
+ filename: 'my-component.gjs',
+ code: `
+ import Component from '@glimmer/component';
+ export default class MyComponent extends Component {
+
+ {{@myArgument}}
+
+ }
+ `,
+ output: null,
+ },
+ ],
+
+ invalid: [
+ {
+ filename: 'my-component.gjs',
+ code: `
+ import Component from '@glimmer/component';
+ export default class MyComponent extends Component {
+
+ {{@Arg}}
+
+ }
+ `,
+ output: null,
+ errors: [
+ {
+ messageId: 'noCapitalArguments',
+ },
+ ],
+ },
+ {
+ filename: 'my-component.gjs',
+ code: `
+ import Component from '@glimmer/component';
+ export default class MyComponent extends Component {
+
+ {{@MyArgument}}
+
+ }
+ `,
+ output: null,
+ errors: [
+ {
+ messageId: 'noCapitalArguments',
+ },
+ ],
+ },
+ ],
+});