diff --git a/docs/source/api/generation.rst b/docs/source/api/generation.rst
index 8e7b0b4961b34154e3c20694f1e69c225de6623b..7a0d0131f1206248a21b7a49fa77f81bd42fdc38 100644
--- a/docs/source/api/generation.rst
+++ b/docs/source/api/generation.rst
@@ -21,9 +21,6 @@ Categories, Parameter Types, and Special Values
 .. autoclass:: _GlobalNamespace
 .. autodata:: GLOBAL_NAMESPACE
 
-.. autoclass:: OutputMode
-    :members:
-
 .. autoclass:: FileExtensions
     :members:
 
diff --git a/docs/source/usage/config_and_cli.md b/docs/source/usage/config_and_cli.md
index 1fdc9df1e7fdb3468fc74de1de3c7b4b720e8ef1..785ff52ed1d5153b04be9e900363af156ff94e7c 100644
--- a/docs/source/usage/config_and_cli.md
+++ b/docs/source/usage/config_and_cli.md
@@ -42,13 +42,15 @@ The file extensions of the generated files can be modified through
 {any}`cfg.extensions.header <FileExtensions.header>`
 and {any}`cfg.extensions.impl <FileExtensions.impl>`;
 and the output directory of the code generator can be set through {any}`cfg.output_directory <SfgConfig.output_directory>`.
+The [header-only mode](#header_only_mode) can be enabled using {any}`cfg.header_only <SfgConfig.header_only>`.
 
 :::{danger}
 
-When running generator scripts through [CMake](#cmake_integration), you should *never* set the file extensions
-and the output directory in the inline configuration.
-Both are managed by the pystencils-sfg CMake module, and setting them manually inside the script will
-lead to an error.
+When running generator scripts through [CMake](#cmake_integration), the file extensions,
+output directory, and header-only mode settings will be managed fully by the pystencils-sfg
+CMake module and the (optional) project configuration module.
+They should therefore not be set in the inline configuration,
+as this will likely lead to errors being raised during code generation.
 :::
 
 ### Outer Namespace
@@ -76,7 +78,7 @@ on invocation. These include:
 - `--sfg-output-dir <path>`: Set the output directory of the generator script. This corresponds to {any}`SfgConfig.output_directory`.
 - `--sfg-file-extensions <exts>`: Set the file extensions used for the generated files;
   `exts` must be a comma-separated list not containing any spaces. Corresponds to {any}`SfgConfig.extensions`.
-- `--sfg-output-mode <mode>`: Set the output mode of the generator script. Corresponds to {any}`SfgConfig.output_mode`.
+- `[--no]--sfg-header-only`: Enable or disable header-only code generation. Corresponds to {any}`SfgConfig.header_only`.
 
 If any configuration option is set to conflicting values on the command line and in the inline configuration,
 the generator script will terminate with an error.
@@ -88,6 +90,17 @@ with the `--help` flag:
 $ python kernels.py --help
 ```
 
+(header_only_mode)=
+## Header-Only Mode
+
+When the header-only output mode is enabled,
+the code generator will emit only a header file and no separate implementation file.
+In this case, the composer will automatically place all function, method,
+and kernel definitions in the header file.
+
+Header-only code generation can be enabled by setting the `--header-only` command-line flag
+or the {any}`SfgConfig.header_only` configuration option.
+
 (custom_cli_args)=
 ## Adding Custom Command-Line Options
 
diff --git a/docs/source/usage/project_integration.md b/docs/source/usage/project_integration.md
index 47b1b6875a502f9c8011df1b51964a85b1ad6281..0ad13e8b98572f721107512e6b2b466a5730c859 100644
--- a/docs/source/usage/project_integration.md
+++ b/docs/source/usage/project_integration.md
@@ -120,9 +120,9 @@ pystencilssfg_generate_target_sources( <target>
     [SCRIPT_ARGS arg1 [arg2 ...]]
     [DEPENDS dependency1.py [dependency2.py...]]
     [FILE_EXTENSIONS <header-extension> <impl-extension>]
-    [OUTPUT_MODE <standalone|inline|header-only>]
     [CONFIG_MODULE <path-to-config-module.py>]
     [OUTPUT_DIRECTORY <output-directory>]
+    [HEADER_ONLY]
 )
 ```
 
@@ -135,12 +135,13 @@ The function takes the following options:
  - `SCRIPT_ARGS`: A list of custom command line arguments passed to the generator scripts; see [](#custom_cli_args)
  - `DEPENDS`: A list of dependencies for the generator scripts
  - `FILE_EXTENSION`: The desired extensions for the generated files
- - `OUTPUT_MODE`: Sets the output mode of the code generator; see {any}`SfgConfig.output_mode`.
  - `CONFIG_MODULE`: Set the configuration module for all scripts registered with this call.
    If set, this overrides the value of `PystencilsSfg_CONFIG_MODULE`
    in the current scope (see [](#cmake_set_config_module))
  - `OUTPUT_DIRECTORY`: Custom output directory for generated files. If `OUTPUT_DIRECTORY` is a relative path,
    it will be interpreted relative to the current build directory.
+ - `HEADER_ONLY`: If this option is set, instruct the generator scripts to only generate header files
+   (see {any}`SfgConfig.header_only`).
 
 If `OUTPUT_DIRECTORY` is *not* specified, any C++ header files generated by the above call
 can be included in any files belonging to `target` via:
diff --git a/integration/test_sycl_buffer.py b/integration/test_sycl_buffer.py
index a1e52eb85af599814a2192b726afd4aae2fd084d..a49d4e492136c24c03182db971f0ce07726b8872 100644
--- a/integration/test_sycl_buffer.py
+++ b/integration/test_sycl_buffer.py
@@ -1,14 +1,14 @@
 from pystencils import Target, CreateKernelConfig, no_jit
 from lbmpy import create_lb_update_rule, LBMOptimisation
-from pystencilssfg import SourceFileGenerator, SfgConfig, OutputMode
-from pystencilssfg.lang.cpp.sycl_accessor import sycl_accessor_ref
+from pystencilssfg import SourceFileGenerator, SfgConfig
+from pystencilssfg.lang.cpp.sycl_accessor import SyclAccessor
 import pystencilssfg.extensions.sycl as sycl
 from itertools import chain
 
 sfg_config = SfgConfig(
     output_directory="out/test_sycl_buffer",
     outer_namespace="gen_code",
-    output_mode=OutputMode.INLINE,
+    header_only=True
 )
 
 with SourceFileGenerator(sfg_config) as sfg:
@@ -21,7 +21,7 @@ with SourceFileGenerator(sfg_config) as sfg:
     cgh = sfg.sycl_handler("handler")
     rang = sfg.sycl_range(update.method.dim, "range")
     mappings = [
-        sfg.map_field(field, sycl_accessor_ref(field))
+        sfg.map_field(field, SyclAccessor.from_field(field))
         for field in chain(update.free_fields, update.bound_fields)
     ]
 
diff --git a/src/pystencilssfg/__init__.py b/src/pystencilssfg/__init__.py
index fea6f8a10e198f86f18be34a6cad381ed3238e19..cea370c65d25242cfb0399e89a5dc7f42058f4ec 100644
--- a/src/pystencilssfg/__init__.py
+++ b/src/pystencilssfg/__init__.py
@@ -1,4 +1,4 @@
-from .config import SfgConfig, GLOBAL_NAMESPACE, OutputMode
+from .config import SfgConfig, GLOBAL_NAMESPACE
 from .generator import SourceFileGenerator
 from .composer import SfgComposer
 from .context import SfgContext
@@ -8,7 +8,6 @@ from .exceptions import SfgException
 __all__ = [
     "SfgConfig",
     "GLOBAL_NAMESPACE",
-    "OutputMode",
     "SourceFileGenerator",
     "SfgComposer",
     "SfgContext",
diff --git a/src/pystencilssfg/cmake/modules/PystencilsSfg.cmake b/src/pystencilssfg/cmake/modules/PystencilsSfg.cmake
index 0779599a0bd9dd1d90a5a1f1fd5f351f6a2fcde4..eb4c2346ec53e044fd12899a613cbc17a5ad9f86 100644
--- a/src/pystencilssfg/cmake/modules/PystencilsSfg.cmake
+++ b/src/pystencilssfg/cmake/modules/PystencilsSfg.cmake
@@ -54,15 +54,17 @@ endfunction()
 
 
 function(pystencilssfg_generate_target_sources TARGET)
-    set(options)
-    set(oneValueArgs OUTPUT_MODE CONFIG_MODULE OUTPUT_DIRECTORY)
+    set(options HEADER_ONLY)
+    set(oneValueArgs CONFIG_MODULE OUTPUT_DIRECTORY)
     set(multiValueArgs SCRIPTS DEPENDS FILE_EXTENSIONS SCRIPT_ARGS)
     cmake_parse_arguments(_pssfg "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
 
     set(generatorArgs)
 
-    if(DEFINED _pssfg_OUTPUT_MODE)
-        list(APPEND generatorArgs "--sfg-output-mode=${_pssfg_OUTPUT_MODE}")
+    if(_pssfg_HEADER_ONLY)
+        list(APPEND generatorArgs "--sfg-header-only")
+    else()
+        list(APPEND generatorArgs "--no-sfg-header-only")
     endif()
 
     if(DEFINED _pssfg_CONFIG_MODULE)
diff --git a/src/pystencilssfg/composer/basic_composer.py b/src/pystencilssfg/composer/basic_composer.py
index 49b6c73e8bd06b0d5fb44402b8af285362072b29..ff1ab2df679aeefd2112d539b90dd59cf93e015b 100644
--- a/src/pystencilssfg/composer/basic_composer.py
+++ b/src/pystencilssfg/composer/basic_composer.py
@@ -88,11 +88,16 @@ SequencerArg: TypeAlias = tuple | ExprLike | SfgCallTreeNode | SfgNodeBuilder
 class KernelsAdder:
     """Handle on a kernel namespace that permits registering kernels."""
 
-    def __init__(self, ctx: SfgContext, loc: SfgNamespaceBlock):
-        self._ctx = ctx
-        self._loc = loc
-        assert isinstance(loc.namespace, SfgKernelNamespace)
-        self._kernel_namespace = loc.namespace
+    def __init__(self, cursor: SfgCursor, knamespace: SfgKernelNamespace):
+        self._cursor = cursor
+        self._kernel_namespace = knamespace
+        self._inline: bool = False
+        self._loc: SfgNamespaceBlock | None = None
+
+    def inline(self) -> KernelsAdder:
+        """Generate kernel definitions ``inline`` in the header file."""
+        self._inline = True
+        return self
 
     def add(self, kernel: Kernel, name: str | None = None):
         """Adds an existing pystencils AST to this namespace.
@@ -111,14 +116,22 @@ class KernelsAdder:
         if name is not None:
             kernel.name = kernel_name
 
-        khandle = SfgKernelHandle(kernel_name, self._kernel_namespace, kernel)
+        khandle = SfgKernelHandle(
+            kernel_name, self._kernel_namespace, kernel, inline=self._inline
+        )
         self._kernel_namespace.add_kernel(khandle)
 
-        self._loc.elements.append(SfgEntityDef(khandle))
+        loc = self._get_loc()
+        loc.elements.append(SfgEntityDef(khandle))
 
         for header in kernel.required_headers:
-            assert self._ctx.impl_file is not None
-            self._ctx.impl_file.includes.append(HeaderFile.parse(header))
+            hfile = HeaderFile.parse(header)
+            if self._inline:
+                self._cursor.context.header_file.includes.append(hfile)
+            else:
+                impl_file = self._cursor.context.impl_file
+                assert impl_file is not None
+                impl_file.includes.append(hfile)
 
         return khandle
 
@@ -147,6 +160,18 @@ class KernelsAdder:
         kernel = create_kernel(assignments, config=config)
         return self.add(kernel)
 
+    def _get_loc(self) -> SfgNamespaceBlock:
+        if self._loc is None:
+            kns_block = SfgNamespaceBlock(self._kernel_namespace)
+
+            if self._inline:
+                self._cursor.write_header(kns_block)
+            else:
+                self._cursor.write_impl(kns_block)
+
+            self._loc = kns_block
+        return self._loc
+
 
 class SfgBasicComposer(SfgIComposer):
     """Composer for basic source components, and base class for all composer mix-ins."""
@@ -281,9 +306,10 @@ class SfgBasicComposer(SfgIComposer):
                 f"The existing entity {kns.fqname} is not a kernel namespace"
             )
 
-        kns_block = SfgNamespaceBlock(kns)
-        self._cursor.write_impl(kns_block)
-        return KernelsAdder(self._ctx, kns_block)
+        kadder = KernelsAdder(self._cursor, kns)
+        if self._ctx.impl_file is None:
+            kadder.inline()
+        return kadder
 
     def include(self, header: str | HeaderFile, private: bool = False):
         """Include a header file.
@@ -356,6 +382,9 @@ class SfgBasicComposer(SfgIComposer):
             )
             seq.returns(return_type)
 
+        if self._ctx.impl_file is None:
+            seq.inline()
+
         return seq
 
     def call(self, kernel_handle: SfgKernelHandle) -> SfgCallTreeNode:
diff --git a/src/pystencilssfg/composer/class_composer.py b/src/pystencilssfg/composer/class_composer.py
index 7787150c5bffd4e7332aecd2ff7a4a66cac0adc6..5dbb4c65d53c9305225239cdaf9753413d07d106 100644
--- a/src/pystencilssfg/composer/class_composer.py
+++ b/src/pystencilssfg/composer/class_composer.py
@@ -253,7 +253,10 @@ class SfgClassComposer(SfgComposerMixIn):
             name: The method name
         """
 
-        return SfgMethodSequencer(self._cursor, name)
+        seq = SfgMethodSequencer(self._cursor, name)
+        if self._ctx.impl_file is None:
+            seq.inline()
+        return seq
 
     #   INTERNALS
 
diff --git a/src/pystencilssfg/config.py b/src/pystencilssfg/config.py
index bbe2389946c4b426dcbd14c5e3e4205b81cef976..34d2f27c0fe2364786a7a58a8afe02ae11654154 100644
--- a/src/pystencilssfg/config.py
+++ b/src/pystencilssfg/config.py
@@ -1,11 +1,10 @@
 from __future__ import annotations
 
-from argparse import ArgumentParser
+from argparse import ArgumentParser, BooleanOptionalAction
 
 from types import ModuleType
 from typing import Any, Sequence, Callable
 from dataclasses import dataclass
-from enum import Enum, auto
 from os import path
 from importlib import util as iutil
 from pathlib import Path
@@ -25,7 +24,7 @@ class FileExtensions(ConfigBase):
     header: BasicOption[str] = BasicOption("hpp")
     """File extension for generated header file."""
 
-    impl: BasicOption[str] = BasicOption()
+    impl: BasicOption[str] = BasicOption("cpp")
     """File extension for generated implementation file."""
 
     @header.validate
@@ -37,25 +36,6 @@ class FileExtensions(ConfigBase):
         return ext
 
 
-class OutputMode(Enum):
-    """Output mode of the source file generator."""
-
-    STANDALONE = auto()
-    """Generate a header/implementation file pair (e.g. ``.hpp/.cpp``) where the implementation file will
-    be compiled to a standalone object."""
-
-    INLINE = auto()
-    """Generate a header/inline implementation file pair (e.g. ``.hpp/.ipp``) where all implementations
-    are inlined by including the implementation file at the end of the header file."""
-
-    HEADER_ONLY = auto()
-    """Generate only a header file.
-
-    At the moment, header-only mode does not support generation of kernels and requires that all functions
-    and methods are marked ``inline``.
-    """
-
-
 @dataclass
 class CodeStyle(ConfigBase):
     """Options affecting the code style used by the source file generator."""
@@ -137,14 +117,10 @@ class SfgConfig(ConfigBase):
             FileExtensions.impl
     """
 
-    output_mode: BasicOption[OutputMode] = BasicOption(OutputMode.STANDALONE)
-    """The generator's output mode; defines which files to generate, and the set of legal file extensions.
+    header_only: BasicOption[bool] = BasicOption(False)
+    """If set to `True`, generate only a header file.
 
-    Possible parameters:
-        .. autosummary::
-            OutputMode.STANDALONE
-            OutputMode.INLINE
-            OutputMode.HEADER_ONLY
+    This will cause all definitions to be generated ``inline``.
     """
 
     outer_namespace: BasicOption[str | _GlobalNamespace] = BasicOption(GLOBAL_NAMESPACE)
@@ -187,16 +163,9 @@ class SfgConfig(ConfigBase):
         header_ext = self.extensions.get_option("header")
         impl_ext = self.extensions.get_option("impl")
         output_files = [output_dir / f"{basename}.{header_ext}"]
-        output_mode = self.get_option("output_mode")
-
-        if impl_ext is None:
-            match output_mode:
-                case OutputMode.INLINE:
-                    impl_ext = "ipp"
-                case OutputMode.STANDALONE:
-                    impl_ext = "cpp"
+        header_only = self.get_option("header_only")
 
-        if output_mode != OutputMode.HEADER_ONLY:
+        if not header_only:
             assert impl_ext is not None
             output_files.append(output_dir / f"{basename}.{impl_ext}")
 
@@ -219,11 +188,10 @@ class CommandLineParameters:
             help="Comma-separated list of file extensions",
         )
         config_group.add_argument(
-            "--sfg-output-mode",
-            type=str,
-            default=None,
-            choices=("standalone", "inline", "header-only"),
-            dest="output_mode",
+            "--sfg-header-only",
+            action=BooleanOptionalAction,
+            dest="header_only",
+            help="Generate only a header file.",
         )
         config_group.add_argument(
             "--sfg-config-module", type=str, default=None, dest="config_module_path"
@@ -234,21 +202,7 @@ class CommandLineParameters:
     def __init__(self, args) -> None:
         self._cl_config_module_path: str | None = args.config_module_path
 
-        if args.output_mode is not None:
-            match args.output_mode.lower():
-                case "standalone":
-                    output_mode = OutputMode.STANDALONE
-                case "inline":
-                    output_mode = OutputMode.INLINE
-                case "header-only":
-                    output_mode = OutputMode.HEADER_ONLY
-                case _:
-                    assert False, "invalid output mode"
-        else:
-            output_mode = None
-
-        self._cl_output_mode = output_mode
-
+        self._cl_header_only: bool | None = args.header_only
         self._cl_output_dir: str | None = args.output_directory
 
         if args.file_extensions is not None:
@@ -279,8 +233,8 @@ class CommandLineParameters:
         ):
             self._config_module.configure_sfg(cfg)
 
-        if self._cl_output_mode is not None:
-            cfg.output_mode = self._cl_output_mode
+        if self._cl_header_only is not None:
+            cfg.header_only = self._cl_header_only
         if self._cl_header_ext is not None:
             cfg.extensions.header = self._cl_header_ext
         if self._cl_impl_ext is not None:
@@ -292,7 +246,7 @@ class CommandLineParameters:
 
     def find_conflicts(self, cfg: SfgConfig):
         for name, mine, theirs in (
-            ("output_mode", self._cl_output_mode, cfg.output_mode),
+            ("header_only", self._cl_header_only, cfg.header_only),
             ("extensions.header", self._cl_header_ext, cfg.extensions.header),
             ("extensions.impl", self._cl_impl_ext, cfg.extensions.impl),
             ("output_directory", self._cl_output_dir, cfg.output_directory),
@@ -320,7 +274,7 @@ class CommandLineParameters:
         extensions = tuple((ext[1:] if ext[0] == "." else ext) for ext in extensions)
 
         HEADER_FILE_EXTENSIONS = {"h", "hpp", "hxx", "h++", "cuh"}
-        IMPL_FILE_EXTENSIONS = {"c", "cpp", "cxx", "c++", "cu", ".impl.h", "ipp", "hip"}
+        IMPL_FILE_EXTENSIONS = {"c", "cpp", "cxx", "c++", "cu", "hip"}
 
         for ext in extensions:
             if ext in HEADER_FILE_EXTENSIONS:
diff --git a/src/pystencilssfg/context.py b/src/pystencilssfg/context.py
index 199c678ba28e449f42b29c56147b9a4fd0d523bb..1622a1e3bd33259cd89eef171ad043c4ea9ef536 100644
--- a/src/pystencilssfg/context.py
+++ b/src/pystencilssfg/context.py
@@ -115,6 +115,10 @@ class SfgCursor:
             else:
                 self._loc[f] = f.elements
 
+    @property
+    def context(self) -> SfgContext:
+        return self._ctx
+
     @property
     def current_namespace(self) -> SfgNamespace:
         return self._cur_namespace
diff --git a/src/pystencilssfg/emission/file_printer.py b/src/pystencilssfg/emission/file_printer.py
index 765bf70550504fd499746504236f1adaa224664a..648e41971336fac709f21848f729b025de27ff36 100644
--- a/src/pystencilssfg/emission/file_printer.py
+++ b/src/pystencilssfg/emission/file_printer.py
@@ -27,9 +27,7 @@ from ..config import CodeStyle
 class SfgFilePrinter:
     def __init__(self, code_style: CodeStyle) -> None:
         self._code_style = code_style
-        self._kernel_printer = CAstPrinter(
-            indent_width=code_style.get_option("indent_width")
-        )
+        self._indent_width = code_style.get_option("indent_width")
 
     def __call__(self, file: SfgSourceFile) -> str:
         code = ""
@@ -86,7 +84,11 @@ class SfgFilePrinter:
     ) -> str:
         match declared_entity:
             case SfgKernelHandle(kernel):
-                return self._kernel_printer.print_signature(kernel) + ";"
+                kernel_printer = CAstPrinter(
+                    indent_width=self._indent_width,
+                    func_prefix="inline" if declared_entity.inline else None,
+                )
+                return kernel_printer.print_signature(kernel) + ";"
 
             case SfgFunction(name, _, params) | SfgMethod(name, _, params):
                 return self._func_signature(declared_entity, inclass) + ";"
@@ -113,7 +115,11 @@ class SfgFilePrinter:
     ) -> str:
         match defined_entity:
             case SfgKernelHandle(kernel):
-                return self._kernel_printer(kernel)
+                kernel_printer = CAstPrinter(
+                    indent_width=self._indent_width,
+                    func_prefix="inline" if defined_entity.inline else None,
+                )
+                return kernel_printer(kernel)
 
             case SfgFunction(name, tree, params) | SfgMethod(name, tree, params):
                 sig = self._func_signature(defined_entity, inclass)
diff --git a/src/pystencilssfg/generator.py b/src/pystencilssfg/generator.py
index 91a124a8439c06dcb22853975cf08a5e9526ecde..c314d67bbc45d5da639d3b7a2b2f92667cc77586 100644
--- a/src/pystencilssfg/generator.py
+++ b/src/pystencilssfg/generator.py
@@ -4,7 +4,6 @@ from typing import Callable, Any
 from .config import (
     SfgConfig,
     CommandLineParameters,
-    OutputMode,
     _GlobalNamespace,
 )
 from .context import SfgContext
@@ -78,7 +77,7 @@ class SourceFileGenerator:
             cli_params.find_conflicts(sfg_config)
             config.override(sfg_config)
 
-        self._output_mode: OutputMode = config.get_option("output_mode")
+        self._header_only: bool = config.get_option("header_only")
         self._output_dir: Path = config.get_option("output_directory")
 
         output_files = config._get_output_files(basename)
@@ -90,20 +89,15 @@ class SourceFileGenerator:
         )
         self._impl_file: SfgSourceFile | None
 
-        match self._output_mode:
-            case OutputMode.HEADER_ONLY:
-                self._impl_file = None
-            case OutputMode.STANDALONE:
-                self._impl_file = SfgSourceFile(
-                    output_files[1].name, SfgSourceFileType.TRANSLATION_UNIT
-                )
-                self._impl_file.includes.append(
-                    HeaderFile.parse(self._header_file.name)
-                )
-            case OutputMode.INLINE:
-                self._impl_file = SfgSourceFile(
-                    output_files[1].name, SfgSourceFileType.HEADER
-                )
+        if self._header_only:
+            self._impl_file = None
+        else:
+            self._impl_file = SfgSourceFile(
+                output_files[1].name, SfgSourceFileType.TRANSLATION_UNIT
+            )
+            self._impl_file.includes.append(
+                HeaderFile.parse(self._header_file.name)
+            )
 
         #   TODO: Find a way to not hard-code the restrict qualifier in pystencils
         self._header_file.elements.append("#define RESTRICT __restrict__")
@@ -150,10 +144,6 @@ class SourceFileGenerator:
                 impl_path.unlink()
 
     def _finish_files(self) -> None:
-        if self._output_mode == OutputMode.INLINE:
-            assert self._impl_file is not None
-            self._header_file.elements.append(f'#include "{self._impl_file.name}"')
-
         from .ir import collect_includes
 
         header_includes = collect_includes(self._header_file)
diff --git a/src/pystencilssfg/ir/entities.py b/src/pystencilssfg/ir/entities.py
index 40abb148d90eb35300afd0af4e25d2f8df1c091e..0edde2209a7ec7bab102de33202aecd3011bfd8a 100644
--- a/src/pystencilssfg/ir/entities.py
+++ b/src/pystencilssfg/ir/entities.py
@@ -141,12 +141,20 @@ class SfgKernelHandle(SfgCodeEntity):
 
     __match_args__ = ("kernel", "parameters")
 
-    def __init__(self, name: str, namespace: SfgKernelNamespace, kernel: Kernel):
+    def __init__(
+        self,
+        name: str,
+        namespace: SfgKernelNamespace,
+        kernel: Kernel,
+        inline: bool = False,
+    ):
         super().__init__(name, namespace)
 
         self._kernel = kernel
         self._parameters = [SfgKernelParamVar(p) for p in kernel.parameters]
 
+        self._inline: bool = inline
+
         self._scalar_params: set[SfgVar] = set()
         self._fields: set[Field] = set()
 
@@ -176,6 +184,10 @@ class SfgKernelHandle(SfgCodeEntity):
         """Underlying pystencils kernel object"""
         return self._kernel
 
+    @property
+    def inline(self) -> bool:
+        return self._inline
+
 
 class SfgKernelNamespace(SfgNamespace):
     """A namespace grouping together a number of kernels."""
diff --git a/tests/generator/test_config.py b/tests/generator/test_config.py
index 250c158c633d6f8fc2f11f0d4b3b2cbd13a13128..9d542cd358d8b0195d578788cc38a79ef8f26426 100644
--- a/tests/generator/test_config.py
+++ b/tests/generator/test_config.py
@@ -3,7 +3,6 @@ from pathlib import Path
 
 from pystencilssfg.config import (
     SfgConfig,
-    OutputMode,
     GLOBAL_NAMESPACE,
     CommandLineParameters,
     SfgConfigException
@@ -13,7 +12,7 @@ from pystencilssfg.config import (
 def test_defaults():
     cfg = SfgConfig()
 
-    assert cfg.get_option("output_mode") == OutputMode.STANDALONE
+    assert cfg.get_option("header_only") is False
     assert cfg.extensions.get_option("header") == "hpp"
     assert cfg.codestyle.get_option("indent_width") == 2
     assert cfg.clang_format.get_option("binary") == "clang-format"
@@ -90,6 +89,23 @@ def test_from_commandline(sample_config_module):
     assert cfg.output_directory == Path(".out")
     assert cfg.extensions.header == "h++"
     assert cfg.extensions.impl == "c++"
+    assert cfg.header_only is None
+
+    args = parser.parse_args(
+        ["--sfg-header-only"]
+    )
+    cli_args = CommandLineParameters(args)
+    cfg = cli_args.get_config()
+
+    assert cfg.header_only is True
+
+    args = parser.parse_args(
+        ["--no-sfg-header-only"]
+    )
+    cli_args = CommandLineParameters(args)
+    cfg = cli_args.get_config()
+
+    assert cfg.header_only is False
 
     args = parser.parse_args(
         ["--sfg-output-dir", "gen_sources", "--sfg-config-module", sample_config_module]
diff --git a/tests/generator_scripts/README.md b/tests/generator_scripts/README.md
index 185e2703e2206a0c1d6377effbf6c9961cae83a4..5dfc474f582cb3093c7fa8941aac692cd1e1bbbb 100644
--- a/tests/generator_scripts/README.md
+++ b/tests/generator_scripts/README.md
@@ -85,12 +85,12 @@ The test suite parses the following (groups of) parameters:
 
 SFG-related command-line parameters passed to the generator script.
 These may be:
-- `output-mode`: Define the output mode, can be either `standalone`, `inline` or `header-only`.
-If `header-only` is specified, the set of expected output files is reduced to `{".hpp"}`.
+- `header-only` (`true` or `false`): Enable or disable header-only code generation.
+  If `true`, the set of expected output files is reduced to `{".hpp"}`.
 - `file-extensions`: List of file extensions for the output files of the generator script.
-If specified, these are taken as the expected output files by the test suite.
+  If specified, these are taken as the expected output files by the test suite.
 - `config-module`: Path to a config module, relative to `source/`.
-The Python file referred to by this option will be passed as a configuration module to the generator script.
+  The Python file referred to by this option will be passed as a configuration module to the generator script.
 
 #### `extra-args`
 List of additional command line parameters passed to the script.
diff --git a/tests/generator_scripts/index.yaml b/tests/generator_scripts/index.yaml
index 68352fe2c2904c11e551955eeb29a6bf9424e126..1c97aaf6a34b0171f4829c56da0f345934c50176 100644
--- a/tests/generator_scripts/index.yaml
+++ b/tests/generator_scripts/index.yaml
@@ -19,7 +19,7 @@ TestIllegalArgs:
 
 TestIncludeSorting:
   sfg-args:
-    output-mode: header-only
+    header-only: true
   expect-code:
     hpp:
       - regex: >-
@@ -32,7 +32,7 @@ TestIncludeSorting:
 
 BasicDefinitions:
   sfg-args:
-    output-mode: header-only
+    header-only: true
   expect-code:
     hpp:
       - regex: >-
@@ -45,7 +45,7 @@ BasicDefinitions:
 
 SimpleClasses:
   sfg-args:
-    output-mode: header-only
+    header-only: true
 
 ComposerFeatures:
   expect-code:
@@ -53,6 +53,16 @@ ComposerFeatures:
       - regex: >-
           \[\[nodiscard\]\]\s*static\s*double\s*geometric\(\s*double\s*q,\s*uint64_t\s*k\)
 
+ComposerHeaderOnly:
+  sfg-args:
+    header-only: true
+  expect-code:
+    hpp:
+      - regex: >-
+          inline\s+int32_t\s+twice\s*\(
+      - regex: >-
+          inline\s+void\s+kernel\s*\(
+
 Conditionals:
   expect-code:
     cpp:
@@ -67,7 +77,7 @@ Conditionals:
 
 NestedNamespaces:
   sfg-args:
-    output-mode: header-only
+    header-only: true
 
 # Kernel Generation
 
@@ -84,10 +94,11 @@ MdSpanLbStreaming:
 
 SyclKernels:
   sfg-args:
-    output-mode: inline
-    file-extensions: [hpp, ipp]
+    header-only: true
   expect-code:
-    ipp:
+    hpp:
+      - regex: >-
+          inline\s+void\s+kernel\s*\(
       - regex: >-
           cgh\.parallel_for\(range,\s*\[=\]\s*\(const\s+sycl::item<\s*2\s*>\s+sycl_item\s*\)\s*\{\s*kernels::kernel\(.*\);\s*\}\);
 
diff --git a/tests/generator_scripts/source/ComposerHeaderOnly.harness.cpp b/tests/generator_scripts/source/ComposerHeaderOnly.harness.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..76f2de4c99da5bb7bb968a404f4c43b4dcfb7482
--- /dev/null
+++ b/tests/generator_scripts/source/ComposerHeaderOnly.harness.cpp
@@ -0,0 +1,30 @@
+#include "ComposerHeaderOnly.hpp"
+
+#include <vector>
+
+#undef NDEBUG
+#include <cassert>
+
+int main(void) {
+    assert( twice(13) == 26 );
+
+    {
+        std::vector< int64_t > arr { 1, 2, 3, 4, 5, 6 };
+        twiceKernel(arr);
+
+        std::vector< int64_t > expected { 2, 4, 6, 8, 10, 12 };
+        assert ( arr == expected );
+    }
+    
+    {
+        std::vector< int64_t > arr { 1, 2, 3, 4, 5, 6 };
+        ScaleKernel ker { 3 };
+
+        ker( arr );
+
+        std::vector< int64_t > expected { 3, 6, 9, 12, 15, 18 };
+        assert ( arr == expected );
+    }
+
+    return 0;
+}
diff --git a/tests/generator_scripts/source/ComposerHeaderOnly.py b/tests/generator_scripts/source/ComposerHeaderOnly.py
new file mode 100644
index 0000000000000000000000000000000000000000..3881457634e8e5182ce0922700e7ad1541199cca
--- /dev/null
+++ b/tests/generator_scripts/source/ComposerHeaderOnly.py
@@ -0,0 +1,45 @@
+from pystencilssfg import SourceFileGenerator, SfgConfig
+from pystencilssfg.lang.cpp import std
+import pystencils as ps
+
+cfg = SfgConfig(header_only=True)
+
+with SourceFileGenerator(cfg) as sfg:
+    n = sfg.var("n", "int32")
+
+    #   Should be automatically marked inline
+    sfg.function("twice").returns("int32")(
+        sfg.expr("return 2 * {};", n)
+    )
+
+    #   Inline kernel
+
+    arr = ps.fields("arr: int64[1D]")
+    vec = std.vector.from_field(arr)
+
+    c = ps.TypedSymbol("c", "int64")
+
+    asm = ps.Assignment(arr(0), c * arr(0))
+    khandle = sfg.kernels.create(asm)
+
+    sfg.function("twiceKernel")(
+        sfg.map_field(arr, vec),
+        sfg.set_param(c, "2"),
+        sfg.call(khandle)
+    )
+
+    #   Inline class members
+
+    sfg.klass("ScaleKernel")(
+        sfg.private(
+            c
+        ),
+        sfg.public(
+            sfg.constructor(c).init(c)(c),
+            sfg.method("operator()")(
+                sfg.map_field(arr, vec),
+                sfg.set_param(c, "this->c"),
+                sfg.call(khandle)
+            )
+        )
+    )
diff --git a/tests/generator_scripts/source/SyclKernels.py b/tests/generator_scripts/source/SyclKernels.py
index 841774383de6c11f7fcc893d694a8ff7d0f33205..f181a3df343156801d7958c2eb2b7200045cf249 100644
--- a/tests/generator_scripts/source/SyclKernels.py
+++ b/tests/generator_scripts/source/SyclKernels.py
@@ -1,12 +1,11 @@
 import sympy as sp
 import pystencils as ps
 
-from pystencilssfg import SourceFileGenerator, SfgConfig, OutputMode
+from pystencilssfg import SourceFileGenerator, SfgConfig
 from pystencilssfg.extensions.sycl import SyclComposer
 
 cfg = SfgConfig()
-cfg.output_mode = OutputMode.INLINE
-cfg.extensions.impl = "ipp"
+cfg.header_only = True
 
 with SourceFileGenerator(cfg) as sfg:
     sfg = SyclComposer(sfg)
diff --git a/tests/generator_scripts/test_generator_scripts.py b/tests/generator_scripts/test_generator_scripts.py
index bba12af2374d9f0177b7ec76bc8777627da366fe..6f2ff160e8b9ec2367020a4a3f91d4a071a71e39 100644
--- a/tests/generator_scripts/test_generator_scripts.py
+++ b/tests/generator_scripts/test_generator_scripts.py
@@ -72,11 +72,12 @@ class GenScriptTest:
 
         sfg_args: dict = test_description.get("sfg-args", dict())
 
-        if (output_mode := sfg_args.get("output-mode", None)) is not None:
-            if output_mode == "header-only":
+        if (header_only := sfg_args.get("header-only", None)) is not None:
+            if header_only:
                 expected_extensions = ["hpp"]
-
-            self._script_args += ["--sfg-output-mode", output_mode]
+                self._script_args += ["--sfg-header-only"]
+            else:
+                self._script_args += ["--no--sfg-header-only"]
 
         if (file_exts := sfg_args.get("file-extensions", None)) is not None:
             expected_extensions = file_exts
diff --git a/tests/integration/cmake_project/CMakeLists.txt b/tests/integration/cmake_project/CMakeLists.txt
index ee7afae6d5781df607246813f47328bc1d45cfd3..f93b090e2e5de0a6f32e391286c33644194b17ce 100644
--- a/tests/integration/cmake_project/CMakeLists.txt
+++ b/tests/integration/cmake_project/CMakeLists.txt
@@ -35,12 +35,12 @@ pystencilssfg_generate_target_sources(
     TestApp
     SCRIPTS CliTest.py
     SCRIPT_ARGS apples bananas unicorns
-    OUTPUT_MODE header-only
+    HEADER_ONLY
 )
 
 pystencilssfg_generate_target_sources(
     TestApp
     SCRIPTS CustomDirTest.py
     OUTPUT_DIRECTORY my-output
-    OUTPUT_MODE header-only
+    HEADER_ONLY
 )
diff --git a/tests/integration/test_cli.py b/tests/integration/test_cli.py
index d3c2585453627e7dc706083f4b1508160ea2f09c..41cdda849e0cb6d35ccb1e78656aee69a697478d 100644
--- a/tests/integration/test_cli.py
+++ b/tests/integration/test_cli.py
@@ -29,8 +29,7 @@ def test_list_files_headeronly():
         "list-files",
         "--sfg-output-dir",
         output_dir,
-        "--sfg-output-mode",
-        "header-only",
+        "--sfg-header-only",
         "genscript.py",
     ]