diff --git a/README.md b/README.md
index a5a3d3070f..b2e4f6832e 100644
--- a/README.md
+++ b/README.md
@@ -340,6 +340,7 @@ rules in templates can be disabled with eslint directives with mustache or html
| [template-no-attrs-in-components](docs/rules/template-no-attrs-in-components.md) | disallow attrs in component templates | | | |
| [template-no-link-to-positional-params](docs/rules/template-no-link-to-positional-params.md) | disallow positional params in LinkTo component | | | |
| [template-no-link-to-tagname](docs/rules/template-no-link-to-tagname.md) | disallow tagName attribute on LinkTo component | | | |
+| [template-no-unbound](docs/rules/template-no-unbound.md) | disallow {{unbound}} helper | | | |
| [template-no-with](docs/rules/template-no-with.md) | disallow {{with}} helper | | | |
### Ember Data
diff --git a/docs/rules/template-no-unbound.md b/docs/rules/template-no-unbound.md
new file mode 100644
index 0000000000..a9044f146e
--- /dev/null
+++ b/docs/rules/template-no-unbound.md
@@ -0,0 +1,31 @@
+# ember/template-no-unbound
+
+> **HBS Only**: This rule applies to classic `.hbs` template files only (loose mode). It is not relevant for `gjs`/`gts` files (strict mode), where these patterns cannot occur.
+
+
+
+`{{unbound}}` is a legacy hold over from the days in which Ember's template engine was less performant. Its use today
+is vestigial, and it no longer offers performance benefits.
+
+It is also a poor practice to use it for rendering only the initial value of a property that may later change.
+
+## Examples
+
+This rule **forbids** the following:
+
+```gjs
+
+ {{unbound aVar}}
+
+```
+
+```gjs
+
+ {{some-component foo=(unbound aVar)}}
+
+```
+
+## References
+
+- [deprecations/unbound block syntax](https://deprecations.emberjs.com/v1.x/#toc_block-and-multi-argument-unbound-helper)
+- [Ember api/unbound helper](https://api.emberjs.com/ember/release/classes/Ember.Templates.helpers/methods/each?anchor=unbound)
diff --git a/lib/rules/template-no-unbound.js b/lib/rules/template-no-unbound.js
new file mode 100644
index 0000000000..29eb9d2c07
--- /dev/null
+++ b/lib/rules/template-no-unbound.js
@@ -0,0 +1,36 @@
+/** @type {import('eslint').Rule.RuleModule} */
+module.exports = {
+ meta: {
+ type: 'suggestion',
+ docs: {
+ description: 'disallow {{unbound}} helper',
+ category: 'Deprecations',
+ url: 'https://github.com/ember-cli/eslint-plugin-ember/tree/master/docs/rules/template-no-unbound.md',
+ templateMode: 'loose',
+ },
+ schema: [],
+ messages: { unexpected: 'Unexpected {{unboundHelper}} usage.' },
+ originallyFrom: {
+ name: 'ember-template-lint',
+ rule: 'lib/rules/no-unbound.js',
+ docs: 'docs/rule/no-unbound.md',
+ tests: 'test/unit/rules/no-unbound-test.js',
+ },
+ },
+ create(context) {
+ function check(node) {
+ if (node.path?.type === 'GlimmerPathExpression' && node.path.original === 'unbound') {
+ context.report({
+ node,
+ messageId: 'unexpected',
+ data: { unboundHelper: '{{unbound}}' },
+ });
+ }
+ }
+ return {
+ GlimmerMustacheStatement: check,
+ GlimmerBlockStatement: check,
+ GlimmerSubExpression: check,
+ };
+ },
+};
diff --git a/tests/lib/rules/template-no-unbound.js b/tests/lib/rules/template-no-unbound.js
new file mode 100644
index 0000000000..5a7013f477
--- /dev/null
+++ b/tests/lib/rules/template-no-unbound.js
@@ -0,0 +1,53 @@
+const rule = require('../../../lib/rules/template-no-unbound');
+const RuleTester = require('eslint').RuleTester;
+
+const validHbs = ['{{foo}}', '{{button}}'];
+
+const invalidHbs = [
+ {
+ code: '{{unbound foo}}',
+ output: null,
+ errors: [{ message: 'Unexpected {{unbound}} usage.' }],
+ },
+ {
+ code: '{{my-thing foo=(unbound foo)}}',
+ output: null,
+ errors: [{ message: 'Unexpected {{unbound}} usage.' }],
+ },
+];
+
+function wrapTemplate(entry) {
+ if (typeof entry === 'string') {
+ return `${entry}`;
+ }
+
+ return {
+ ...entry,
+ code: `${entry.code}`,
+ output: entry.output ? `${entry.output}` : entry.output,
+ errors: entry.errors.map(() => ({ messageId: 'unexpected' })),
+ };
+}
+
+const gjsRuleTester = new RuleTester({
+ parser: require.resolve('ember-eslint-parser'),
+ parserOptions: { ecmaVersion: 2022, sourceType: 'module' },
+});
+
+gjsRuleTester.run('template-no-unbound', rule, {
+ valid: validHbs.map(wrapTemplate),
+ invalid: invalidHbs.map(wrapTemplate),
+});
+
+const hbsRuleTester = new RuleTester({
+ parser: require.resolve('ember-eslint-parser/hbs'),
+ parserOptions: {
+ ecmaVersion: 2022,
+ sourceType: 'module',
+ },
+});
+
+hbsRuleTester.run('template-no-unbound', rule, {
+ valid: validHbs,
+ invalid: invalidHbs,
+});