diff --git a/lib/rules/template-no-input-block.js b/lib/rules/template-no-input-block.js
index 5ad5344a4c..ffee36cbfb 100644
--- a/lib/rules/template-no-input-block.js
+++ b/lib/rules/template-no-input-block.js
@@ -18,6 +18,15 @@ module.exports = {
},
},
create(context) {
+ // The classic `{{input}}` helper is HBS-only — it is not an ambient
+ // strict-mode keyword. In `.gjs`/`.gts` any `{{#input}}` is necessarily
+ // a user binding (an imported or locally-declared identifier named
+ // `input`), so flagging it would corrupt the user's intent.
+ const isStrictMode = context.filename.endsWith('.gjs') || context.filename.endsWith('.gts');
+ if (isStrictMode) {
+ return {};
+ }
+
return {
GlimmerBlockStatement(node) {
if (node.path?.type === 'GlimmerPathExpression' && node.path.original === 'input') {
diff --git a/tests/lib/rules/template-no-input-block.js b/tests/lib/rules/template-no-input-block.js
index ba969fb301..5ec6b7c308 100644
--- a/tests/lib/rules/template-no-input-block.js
+++ b/tests/lib/rules/template-no-input-block.js
@@ -11,6 +11,28 @@ ruleTester.run('template-no-input-block', rule, {
'{{button}}',
'{{#x-button}}{{/x-button}}',
'{{input}}',
+
+ // GJS/GTS: the classic `{{input}}` helper is HBS-only — `input` is not
+ // an ambient strict-mode keyword. Any `{{#input}}` in strict mode is a
+ // user-imported binding (or an unbound name that the strict-mode
+ // compiler will reject on its own); flagging here would corrupt the
+ // user's intent for the imported case.
+ {
+ filename: 'test.gjs',
+ code: '{{#input}}content{{/input}}',
+ },
+ {
+ filename: 'test.gts',
+ code: '{{#input}}content{{/input}}',
+ },
+ {
+ filename: 'test.gjs',
+ code: "import input from './my-input';\n{{#input}}content{{/input}}",
+ },
+ {
+ filename: 'test.gjs',
+ code: "import input from './my-input';\n{{#input value=this.foo}}{{/input}}",
+ },
],
invalid: [
{