Skip to content

Feature/container logs - #20

Merged
hard-rox merged 13 commits into
mainfrom
feature/container-logs
Aug 1, 2026
Merged

Feature/container logs#20
hard-rox merged 13 commits into
mainfrom
feature/container-logs

Conversation

@hard-rox

@hard-rox hard-rox commented Jul 29, 2026

Copy link
Copy Markdown
Owner

Summary by CodeRabbit

  • New Features
    • Added live container log viewing with follow mode, timestamps, boot logs, tail limits, cancellation, and filtering.
    • Added styled terminal output and “Copy all” support.
    • Improved dialog handling across container, image, and run-container workflows.
  • Refactor
    • Centralized background refresh and dialog management.
  • Documentation
    • Added capabilities, release guidance, and coding standards documentation.
  • Tests
    • Expanded coverage for log streaming, cancellation, refresh, dialogs, and command generation.

hard-rox added 5 commits July 28, 2026 17:40
- Implemented ContainerLogsDialog and ContainerLogsDialogViewModel for displaying logs of a selected container.
- Added functionality to stream logs with options for following, timestamps, and limiting output.
- Introduced ContainerLogsOptions to encapsulate log streaming parameters.
- Updated IContainerCliProvider to support log streaming commands.
- Enhanced existing ContainersViewModel to trigger the logs dialog.
- Added tests for ContainerLogsDialogViewModel and command argument building for logs.
- Updated .gitignore to exclude publish directories and added Inlines to VSCode settings.
…methods

- Removed summary comments from EnvironmentVariableEntry, PortMappingEntry, RunContainerDialogViewModel, VolumeMountEntry, MainWindowViewModel, SidebarViewModel, ContainerItem, ImageItem, NavigationItem, Program, ServiceCollectionExtensions, IThemeService, ThemeService, ViewLocator, AppleContainerCliProvider, AppleContainerSystemService, ContainerCliProviderBase, AggregateCliCommandException, CliCommandException, IContainerCliProvider, CliOutputLine, Container, ContainerImage, ContainerLogsOptions, ContainerSystemStatus, PlatformInfo, RunContainerOptions, ServiceCollectionExtensions, WslcCliProvider, and SidebarViewModelTests.
@coderabbitai

coderabbitai Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds container log streaming, reusable dialog and refresh services, terminal output copying, and feature integration. It also updates C# conventions, removes or shortens XML documentation, reformats UI markup, changes logging configuration, and adds repository release documentation.

Changes

Container logs, dialogs, refresh, and UI integration

Layer / File(s) Summary
Container log contract and CLI implementation
src/Knarr.Service/Models/ContainerLogsOptions.cs, src/Knarr.Service/IContainerCliProvider.cs, src/Knarr.Service/ContainerCliProviderBase.cs, src/Knarr.Service/*Cli/*Provider.cs, tests/Knarr.Service.Tests/ContainerLogsCommandTests.cs
Adds typed log options, provider capability flags, streaming, provider-specific commands, and command argument tests.
Dialog and refresh services
src/Knarr.App/Common/*, src/Knarr.App/Services/*Refresh*, src/Knarr.App/Services/*Dialog*, tests/Knarr.App.Tests/Services/*
Adds dialog close contracts, owner-aware dialog display, and a shared timer-based refresh service with subscription disposal.
Container logs dialog and terminal output
src/Knarr.App/Features/Containers/ContainerLogs/*, src/Knarr.App/Controls/TerminalOutputView.*, tests/Knarr.App.Tests/Features/Containers/ContainerLogs/*
Adds cancellable log streaming, filter-driven restarts, terminal state handling, styled inline output, clipboard copying, and tests.
Feature wiring and dialog conversion
src/Knarr.App/Features/Containers/*, src/Knarr.App/Features/Images/*, src/Knarr.App/Features/RunContainer/*, src/Knarr.App/Features/Sidebar/*, src/Knarr.App/ServiceCollectionExtensions.cs, tests/Knarr.App.Tests/Features/*
Replaces local dialog events, factories, and timers with injected services. Existing dialogs use DialogWindow, and new services and view models are registered.
Code conventions, cleanup, and documentation
Layer / File(s) Summary
Formatting and documentation guidance
.editorconfig, .github/copilot-instructions.md, .github/skills/better-code/SKILL.md
Updates formatting, naming, modifier, and expression rules. Adds contributor guidance for comments and XML documentation.
Source and UI cleanup
src/Knarr.App/**/*.cs, src/Knarr.Service/**/*.cs, src/Knarr.App/**/*.axaml, tests/**/*.cs
Removes or shortens XML documentation, makes selected local types explicit, simplifies declarations, reformats XAML, and changes selected layout wrappers.
Project and logging configuration
src/Knarr.App/Program.cs, src/Knarr.App/Knarr.App.csproj, Directory.Packages.props, .gitignore, .vscode/settings.json
Removes the console sink, uses the file sink, adds publish-directory and spelling configuration, and applies small project cleanup changes.
Repository and release documentation
README.md, docs/RELEASING.md
Documents current capabilities, naming, release policy, signing, notarization, quality gates, and current release implementation gaps.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Operator
  participant ContainersViewModel
  participant IDialogService
  participant ContainerLogsDialogViewModel
  participant IContainerCliProvider
  Operator->>ContainersViewModel: Execute LogsCommand
  ContainersViewModel->>IDialogService: Show ContainerLogsDialogViewModel
  IDialogService->>ContainerLogsDialogViewModel: Resolve and configure
  IDialogService-->>Operator: Display ContainerLogsDialog
  ContainerLogsDialogViewModel->>IContainerCliProvider: StreamContainerLogsAsync
  IContainerCliProvider-->>ContainerLogsDialogViewModel: Return CliOutputLine values
  ContainerLogsDialogViewModel->>ContainerLogsDialogViewModel: Update OutputLines and TerminalState
  Operator->>ContainerLogsDialogViewModel: Execute StopCommand or CloseCommand
Loading

Possibly related PRs

  • hard-rox/knarr#12: Adds the container CLI infrastructure extended by the log streaming contract.
  • hard-rox/knarr#13: Adds terminal output infrastructure modified for inline rendering and copying.
  • hard-rox/knarr#14: Provides dialog, CLI provider, and view-model code directly refactored by this change.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 19.25% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the main change: adding container log functionality.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 2
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🛠️ Fix failing CI checks 💡
  • Fix failing CI checks
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/container-logs

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 13

🧹 Nitpick comments (6)
src/Knarr.App/Features/Images/ImagesViewModel.cs (1)

242-243: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Remove the comment added above private LoadAsync.

This PR adds a private-member comment, but repository guidance says to avoid comments/XML documentation on private or internal members. Remove it or encode the behavior through clearer naming/structure.

As per coding guidelines, avoid comments/XML docs on private or internal members.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Knarr.App/Features/Images/ImagesViewModel.cs` around lines 242 - 243,
Remove the two-line comment immediately above the private LoadAsync method,
leaving the method implementation and behavior unchanged.

Source: Coding guidelines

src/Knarr.App/Controls/TerminalOutputView.axaml.cs (1)

209-210: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Remove the private-method comment.

As per coding guidelines, “avoid comments/XML documentation on private or internal members.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Knarr.App/Controls/TerminalOutputView.axaml.cs` around lines 209 - 210,
Remove the private-method comment shown in the diff, leaving the surrounding
implementation unchanged.

Source: Coding guidelines

src/Knarr.Service/AppleContainerCli/AppleContainerSystemService.cs (1)

56-56: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Remove the internal-member comment.

As per coding guidelines, “avoid comments/XML documentation on private or internal members.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Knarr.Service/AppleContainerCli/AppleContainerSystemService.cs` at line
56, Remove the internal-member comment in AppleContainerSystemService, leaving
the surrounding implementation unchanged.

Source: Coding guidelines

tests/Knarr.Service.Tests/ContainerLogsCommandTests.cs (1)

6-10: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Remove XML documentation from the test class.

As per coding guidelines, “add /// XML documentation only to public interfaces and shared abstract base classes.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/Knarr.Service.Tests/ContainerLogsCommandTests.cs` around lines 6 - 10,
Remove the XML documentation comment from the test class surrounding
ContainerCliProviderBase.BuildLogsArgs and ContainerLogsOptions references,
leaving the test implementation unchanged.

Source: Coding guidelines

src/Knarr.Service/ContainerCliProviderBase.cs (1)

47-48: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Remove comments from internal/private members.

ContainerCliProviderBase is internal, and BuildRunArgs is private. As per coding guidelines, “avoid comments/XML documentation on private or internal members” and “add /// XML documentation only to public interfaces and shared abstract base classes.”

Also applies to: 106-106

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Knarr.Service/ContainerCliProviderBase.cs` around lines 47 - 48, Remove
the XML documentation comment from the internal ContainerCliProviderBase member
LogsCommand and the private BuildRunArgs member, while leaving their
declarations and behavior unchanged.

Source: Coding guidelines

src/Knarr.App/Features/Containers/ContainerLogs/ContainerLogsDialog.axaml (1)

8-9: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Avoid fixed dialog dimensions.

Hard-coded dimensions do not adapt to text scaling or constrained displays; use content/star sizing and only necessary bounds.

As per coding guidelines, **/*.axaml should “avoid fixed pixel sizing.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Knarr.App/Features/Containers/ContainerLogs/ContainerLogsDialog.axaml`
around lines 8 - 9, Replace the fixed Width, Height, MinWidth, and MinHeight
values in the ContainerLogsDialog layout with content- or star-based sizing,
retaining only bounds that are necessary for usability and ensuring the dialog
adapts to text scaling and constrained displays.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.editorconfig:
- Around line 14-18: Apply two-space AXAML formatting consistently: update
.editorconfig lines 14-18 to include axaml and xaml in the two-space override;
reindent the changed wrapper block in
src/Knarr.App/Features/Settings/SettingsView.axaml lines 11-16 and the changed
template block in src/Knarr.App/Features/Sidebar/Sidebar.axaml lines 170-198 to
two spaces.

In @.gitignore:
- Line 12: Update the Publish ignore pattern in .gitignore to use a fully
case-insensitive matching form, so every casing variant of the Publish directory
is ignored.

In `@src/Knarr.App/Controls/TerminalOutputView.axaml`:
- Around line 40-48: Update the icon-only PART_CopyButton by adding
AutomationProperties.Name with the accessible name “Copy all output”; leave its
existing visibility, tooltip, and icon configuration unchanged.

In `@src/Knarr.App/Controls/TerminalOutputView.axaml.cs`:
- Around line 211-247: Update TerminalOutputView’s RebuildInlines and streaming
output flow so OutputLines remains bounded to the selected tail limit, removing
oldest entries as new lines arrive. Reuse and append existing Inline elements
for newly added lines, removing only the corresponding leading inlines when the
tail evicts entries, instead of clearing and rebuilding the entire collection on
every CollectionChanged event.

In
`@src/Knarr.App/Features/Containers/ContainerLogs/ContainerLogsDialog.axaml.cs`:
- Around line 9-34: Move dialog lifecycle and event orchestration out of
code-behind: in
src/Knarr.App/Features/Containers/ContainerLogs/ContainerLogsDialog.axaml.cs#L9-L34,
replace OnDataContextChanged, OnCloseRequested, and OnClosed wiring with an
AXAML-bound behavior or framework-agnostic presentation abstraction, leaving
only InitializeComponent(). In
src/Knarr.App/Features/Containers/ContainersView.axaml.cs#L17-L60, replace the
logs-dialog event subscription and Show/ShowDialog handling with that same
presentation mechanism, leaving only InitializeComponent() in the feature
code-behind.
- Around line 27-33: Update ContainerLogsDialog.OnClosed to invoke the view
model’s existing close/cancellation behavior before unsubscribing CloseRequested
and clearing _viewModel. Ensure title-bar and command-driven closures both
cancel any active follow stream, then preserve the existing event-handler
cleanup.

In
`@src/Knarr.App/Features/Containers/ContainerLogs/ContainerLogsDialogViewModel.cs`:
- Around line 119-121: Update the restart flow around RequestCancellation and
StreamAsync so a canceled stream cannot mutate shared output, TerminalState, or
IsStreaming after a replacement begins. Serialize stream restarts or associate
each run with its current cancellation source/generation, and guard every stream
mutation so only the active run can apply state changes.
- Around line 31-32: Add [NotifyPropertyChangedFor(nameof(ShortId))] to the
ContainerId observable property declaration so changing ContainerId also raises
the ShortId notification and refreshes the bound computed value during
Reset(...).

In `@src/Knarr.App/Features/Dashboard/DashboardView.axaml`:
- Around line 11-16: Reindent the new Panel block in DashboardView, including
its TextBlock and attributes, from four-space indentation to the
repository-standard two-space AXAML indentation without changing its content or
behavior.

In `@src/Knarr.App/Features/RunContainer/RunContainerDialog.axaml.cs`:
- Line 32: Update the clipboard lookup in RunContainerDialog to call the fully
qualified Avalonia.Controls.TopLevel.GetTopLevel(this) method, preserving the
existing clipboard pattern and behavior.

In `@src/Knarr.App/Features/RunContainer/RunContainerDialogViewModel.cs`:
- Around line 177-179: Condense the cancellation rationale comment in the
RunContainerDialogViewModel cancellation flow to one concise line explaining
that CancellationTokenSource.Cancel can block the UI thread on Windows, so
cancellation is offloaded to a background thread.

In `@src/Knarr.Service/ContainerCliProviderBase.cs`:
- Around line 172-205: The shared BuildLogsArgs flow currently emits flags
unsupported by Apple’s container CLI. Update
src/Knarr.Service/ContainerCliProviderBase.cs lines 172-205 to support
provider-specific log arguments or reject unsupported options, update
src/Knarr.Service/AppleContainerCli/AppleContainerCliProvider.cs line 23 to map
TailLines to -n and expose unsupported timestamp/time-filter capabilities, and
update tests/Knarr.Service.Tests/ContainerLogsCommandTests.cs lines 95-102 to
verify Apple’s -n output and unsupported-option behavior.
- Around line 208-209: Update FormatTimestamp to use a round-trip timestamp
format that preserves fractional seconds while retaining UTC and
invariant-culture output for --since/--until values. Extend the existing
log-arguments test to verify fractional DateTimeOffset boundaries are emitted
with their fractional precision.

---

Nitpick comments:
In `@src/Knarr.App/Controls/TerminalOutputView.axaml.cs`:
- Around line 209-210: Remove the private-method comment shown in the diff,
leaving the surrounding implementation unchanged.

In `@src/Knarr.App/Features/Containers/ContainerLogs/ContainerLogsDialog.axaml`:
- Around line 8-9: Replace the fixed Width, Height, MinWidth, and MinHeight
values in the ContainerLogsDialog layout with content- or star-based sizing,
retaining only bounds that are necessary for usability and ensuring the dialog
adapts to text scaling and constrained displays.

In `@src/Knarr.App/Features/Images/ImagesViewModel.cs`:
- Around line 242-243: Remove the two-line comment immediately above the private
LoadAsync method, leaving the method implementation and behavior unchanged.

In `@src/Knarr.Service/AppleContainerCli/AppleContainerSystemService.cs`:
- Line 56: Remove the internal-member comment in AppleContainerSystemService,
leaving the surrounding implementation unchanged.

In `@src/Knarr.Service/ContainerCliProviderBase.cs`:
- Around line 47-48: Remove the XML documentation comment from the internal
ContainerCliProviderBase member LogsCommand and the private BuildRunArgs member,
while leaving their declarations and behavior unchanged.

In `@tests/Knarr.Service.Tests/ContainerLogsCommandTests.cs`:
- Around line 6-10: Remove the XML documentation comment from the test class
surrounding ContainerCliProviderBase.BuildLogsArgs and ContainerLogsOptions
references, leaving the test implementation unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 99de30b6-4555-4416-95fd-c581a65f21c0

📥 Commits

Reviewing files that changed from the base of the PR and between da29ca6 and 36e98b5.

📒 Files selected for processing (63)
  • .editorconfig
  • .github/copilot-instructions.md
  • .github/skills/better-code/SKILL.md
  • .gitignore
  • .vscode/settings.json
  • Directory.Packages.props
  • src/Knarr.App/Controls/Pill.axaml.cs
  • src/Knarr.App/Controls/TerminalOutputView.axaml
  • src/Knarr.App/Controls/TerminalOutputView.axaml.cs
  • src/Knarr.App/Controls/Tile.axaml.cs
  • src/Knarr.App/Converters/CliOutputKindToBrushConverter.cs
  • src/Knarr.App/Converters/IconKeyToGeometryConverter.cs
  • src/Knarr.App/Features/Containers/ContainerLogs/ContainerLogsDialog.axaml
  • src/Knarr.App/Features/Containers/ContainerLogs/ContainerLogsDialog.axaml.cs
  • src/Knarr.App/Features/Containers/ContainerLogs/ContainerLogsDialogViewModel.cs
  • src/Knarr.App/Features/Containers/ContainersView.axaml
  • src/Knarr.App/Features/Containers/ContainersView.axaml.cs
  • src/Knarr.App/Features/Containers/ContainersViewModel.cs
  • src/Knarr.App/Features/Dashboard/DashboardView.axaml
  • src/Knarr.App/Features/Images/ImagesView.axaml
  • src/Knarr.App/Features/Images/ImagesViewModel.cs
  • src/Knarr.App/Features/Images/PullImageDialogViewModel.cs
  • src/Knarr.App/Features/RunContainer/EnvironmentVariableEntry.cs
  • src/Knarr.App/Features/RunContainer/PortMappingEntry.cs
  • src/Knarr.App/Features/RunContainer/RunContainerDialog.axaml.cs
  • src/Knarr.App/Features/RunContainer/RunContainerDialogViewModel.cs
  • src/Knarr.App/Features/RunContainer/VolumeMountEntry.cs
  • src/Knarr.App/Features/Settings/SettingsView.axaml
  • src/Knarr.App/Features/Shell/MainWindowViewModel.cs
  • src/Knarr.App/Features/Sidebar/Sidebar.axaml
  • src/Knarr.App/Features/Sidebar/SidebarViewModel.cs
  • src/Knarr.App/Knarr.App.csproj
  • src/Knarr.App/Models/ContainerItem.cs
  • src/Knarr.App/Models/ImageItem.cs
  • src/Knarr.App/Models/NavigationItem.cs
  • src/Knarr.App/Program.cs
  • src/Knarr.App/ServiceCollectionExtensions.cs
  • src/Knarr.App/Services/IThemeService.cs
  • src/Knarr.App/Services/ThemeService.cs
  • src/Knarr.App/ViewLocator.cs
  • src/Knarr.Service/AppleContainerCli/AppleContainerCliProvider.cs
  • src/Knarr.Service/AppleContainerCli/AppleContainerSystemService.cs
  • src/Knarr.Service/ContainerCliProviderBase.cs
  • src/Knarr.Service/Exceptions/AggregateCliCommandException.cs
  • src/Knarr.Service/Exceptions/CliCommandException.cs
  • src/Knarr.Service/IContainerCliProvider.cs
  • src/Knarr.Service/Models/CliOutputLine.cs
  • src/Knarr.Service/Models/Container.cs
  • src/Knarr.Service/Models/ContainerImage.cs
  • src/Knarr.Service/Models/ContainerLogsOptions.cs
  • src/Knarr.Service/Models/ContainerSystemStatus.cs
  • src/Knarr.Service/Models/PlatformInfo.cs
  • src/Knarr.Service/Models/RunContainerOptions.cs
  • src/Knarr.Service/ServiceCollectionExtensions.cs
  • src/Knarr.Service/WslcCli/WslcCliProvider.cs
  • tests/Knarr.App.Tests/Features/Containers/ContainerLogs/ContainerLogsDialogViewModelTests.cs
  • tests/Knarr.App.Tests/Features/Containers/ContainersViewModelTests.cs
  • tests/Knarr.App.Tests/Features/Images/PullImageDialogViewModelTests.cs
  • tests/Knarr.App.Tests/Features/RunContainer/RunContainerDialogViewModelTests.cs
  • tests/Knarr.App.Tests/Features/Sidebar/SidebarViewModelTests.cs
  • tests/Knarr.Service.Tests/AppleContainerSystemServiceTests.cs
  • tests/Knarr.Service.Tests/ContainerLogsCommandTests.cs
  • tests/Knarr.Service.Tests/RunContainerCommandTests.cs
💤 Files with no reviewable changes (21)
  • src/Knarr.Service/ServiceCollectionExtensions.cs
  • src/Knarr.Service/Models/PlatformInfo.cs
  • src/Knarr.App/Features/RunContainer/VolumeMountEntry.cs
  • src/Knarr.App/Controls/Tile.axaml.cs
  • src/Knarr.App/Knarr.App.csproj
  • tests/Knarr.App.Tests/Features/Sidebar/SidebarViewModelTests.cs
  • src/Knarr.Service/Models/ContainerImage.cs
  • src/Knarr.App/Features/RunContainer/PortMappingEntry.cs
  • src/Knarr.App/Models/NavigationItem.cs
  • src/Knarr.App/Features/RunContainer/EnvironmentVariableEntry.cs
  • src/Knarr.App/Services/IThemeService.cs
  • src/Knarr.App/Features/Shell/MainWindowViewModel.cs
  • src/Knarr.App/Services/ThemeService.cs
  • src/Knarr.App/Models/ContainerItem.cs
  • src/Knarr.App/Controls/Pill.axaml.cs
  • src/Knarr.Service/Models/ContainerSystemStatus.cs
  • src/Knarr.Service/Exceptions/AggregateCliCommandException.cs
  • src/Knarr.Service/Models/Container.cs
  • src/Knarr.Service/Models/CliOutputLine.cs
  • src/Knarr.Service/Models/RunContainerOptions.cs
  • Directory.Packages.props

Comment thread .editorconfig
Comment on lines +14 to 18
# JSON, XML, YAML and web-related overrides
[*.{json,xml,yml,yaml,html,css}]
indent_size = 2
tab_width = 2

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Apply the required two-space AXAML formatting consistently.

The .editorconfig override excludes AXAML, and both changed AXAML blocks remain four-space indented.

  • .editorconfig#L14-L18: include axaml and xaml in the two-space override.
  • src/Knarr.App/Features/Settings/SettingsView.axaml#L11-L16: reindent the changed wrapper block to two spaces.
  • src/Knarr.App/Features/Sidebar/Sidebar.axaml#L170-L198: reindent the changed template block to two spaces.

As per coding guidelines, AXAML files must use two-space indentation.

📍 Affects 3 files
  • .editorconfig#L14-L18 (this comment)
  • src/Knarr.App/Features/Settings/SettingsView.axaml#L11-L16
  • src/Knarr.App/Features/Sidebar/Sidebar.axaml#L170-L198
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.editorconfig around lines 14 - 18, Apply two-space AXAML formatting
consistently: update .editorconfig lines 14-18 to include axaml and xaml in the
two-space override; reindent the changed wrapper block in
src/Knarr.App/Features/Settings/SettingsView.axaml lines 11-16 and the changed
template block in src/Knarr.App/Features/Sidebar/Sidebar.axaml lines 170-198 to
two spaces.

Source: Coding guidelines

Comment thread .gitignore
*.suo
artifacts/
/packages/
[Pp]ublish/

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Make the Publish ignore pattern fully case-insensitive.

[Pp]ublish/ matches only Publish/ and publish/; it does not cover other casing variants despite the stated intent.

Proposed fix
-[Pp]ublish/
+[Pp][Uu][Bb][Ll][Ii][Ss][Hh]/
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
[Pp]ublish/
[Pp][Uu][Bb][Ll][Ii][Ss][Hh]/
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.gitignore at line 12, Update the Publish ignore pattern in .gitignore to
use a fully case-insensitive matching form, so every casing variant of the
Publish directory is ignored.

Comment on lines +40 to +48
<Button Name="PART_CopyButton"
Classes="icon"
HorizontalAlignment="Right"
VerticalAlignment="Top"
Margin="6"
IsVisible="{Binding HasOutput, RelativeSource={RelativeSource TemplatedParent}}"
ToolTip.Tip="Copy all">
<PathIcon Data="{StaticResource CopyRegular}" Width="14" Height="14" />
</Button>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Repository files matching TerminalOutputView.axaml:"
fd -a 'TerminalOutputView\.axaml$' . || true

file="$(fd 'TerminalOutputView\.axaml$' . | head -n1 || true)"
if [ -n "${file:-}" ]; then
  echo "---- $file ----"
  wc -l "$file"
  sed -n '1,120p' "$file"
fi

echo "---- Avalonia Button docs references / dependencies ----"
rg -n "Avalonia|Avalonia\.Controls|Button|AutomationProperties\.Name" -S --glob "*.csproj" --glob "*.axaml" --glob "*.props" --glob "*.targets" . | head -n 80 || true

Repository: hard-rox/knarr

Length of output: 11941


🌐 Web query:

Avalonia UI button accessibility AutomationProperties.Name icon-only button documentation

💡 Result:

In Avalonia UI, icon-only buttons are not automatically descriptive to assistive technologies because they lack text content [1][2]. To ensure accessibility for these controls, you must explicitly provide an accessible name using the AutomationProperties.Name attached property [1][2]. When a button contains only an icon, screen readers will not be able to identify its purpose without this metadata [1][2]. By setting AutomationProperties.Name, you provide the descriptive text that a screen reader announces when the button receives focus [1][2]. Implementation example: Key Accessibility Guidelines: - Use AutomationProperties.Name: This is the primary mechanism to label controls that do not have visible text or where the visible text is insufficient [1][2]. - When to set it explicitly: You should explicitly set the Name property when the button content is an icon or image, when the text is ambiguous, or when the control has no visible content [2][3]. - Do not affect visual UI: AutomationProperties are designed to supply metadata for assistive technologies and do not change the visual appearance of your controls [2][3]. - Consistency: Ensure that the string provided in AutomationProperties.Name is concise, meaningful, and clearly describes the action of the button [1][2].

Citations:


Give the icon-only copy button an accessible name.

The button’s contents are only a PathIcon, and the tooltip is not exposed to assistive technologies. Set AutomationProperties.Name="Copy all output" to make it accessible.

Proposed fix
 <Button Name="PART_CopyButton"
         Classes="icon"
+        AutomationProperties.Name="Copy all output"
         HorizontalAlignment="Right"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<Button Name="PART_CopyButton"
Classes="icon"
HorizontalAlignment="Right"
VerticalAlignment="Top"
Margin="6"
IsVisible="{Binding HasOutput, RelativeSource={RelativeSource TemplatedParent}}"
ToolTip.Tip="Copy all">
<PathIcon Data="{StaticResource CopyRegular}" Width="14" Height="14" />
</Button>
<Button Name="PART_CopyButton"
Classes="icon"
AutomationProperties.Name="Copy all output"
HorizontalAlignment="Right"
VerticalAlignment="Top"
Margin="6"
IsVisible="{Binding HasOutput, RelativeSource={RelativeSource TemplatedParent}}"
ToolTip.Tip="Copy all">
<PathIcon Data="{StaticResource CopyRegular}" Width="14" Height="14" />
</Button>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Knarr.App/Controls/TerminalOutputView.axaml` around lines 40 - 48, Update
the icon-only PART_CopyButton by adding AutomationProperties.Name with the
accessible name “Copy all output”; leave its existing visibility, tooltip, and
icon configuration unchanged.

Comment on lines +211 to +247
private void RebuildInlines()
{
if (_outputText is null)
{
return;
}

_outputText.Inlines ??= new InlineCollection();
_outputText.Inlines.Clear();

if (Lines is not IEnumerable lines)
{
return;
}

List<CliOutputLine> outputLines = [];
foreach (object? item in lines)
{
if (item is CliOutputLine line)
{
outputLines.Add(line);
}
}

for (int i = 0; i < outputLines.Count; i++)
{
CliOutputLine line = outputLines[i];
IBrush? brush = CliOutputKindToBrushConverter.Instance.Convert(
line.Kind, typeof(IBrush), null, CultureInfo.InvariantCulture) as IBrush;

_outputText.Inlines.Add(new Run(line.Text) { Foreground = brush });

if (i < outputLines.Count - 1)
{
_outputText.Inlines.Add(new LineBreak());
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚀 Performance & Scalability | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
ast-grep outline src/Knarr.App/Features/Containers/ContainerLogs/ContainerLogsDialogViewModel.cs --items all
rg -n --type cs -C 4 'ObservableCollection<.*CliOutputLine>|Lines\s*\{|RemoveAt\(|Max.*Lines|Limit' \
  src/Knarr.App/Features/Containers/ContainerLogs/ContainerLogsDialogViewModel.cs

Repository: hard-rox/knarr

Length of output: 2574


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== ContainerLogsDialogViewModel relevant sections ==="
nl -ba src/Knarr.App/Features/Containers/ContainerLogs/ContainerLogsDialogViewModel.cs | sed -n '55,190p'

echo
echo "=== Search CliOutputLine and collection usages ==="
rg -n --type cs -C 3 'CliOutputLine|OutputLines|Add\(|Remove|Capacity|Max.*Line|Keep|Trim|Limit|TailLines' src/Knarr.App/Features/Containers src/Knarr.App/Controls TerminalOutputView.axaml.cs 2>/dev/null || true

echo
echo "=== TerminalOutputView relevant section ==="
nl -ba src/Knarr.App/Controls/TerminalOutputView.axaml.cs | sed -n '1,280p'

Repository: hard-rox/knarr

Length of output: 247


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== ContainerLogsDialogViewModel relevant sections ==="
awk '{printf "%5d\t%s\n", NR, $0}' src/Knarr.App/Features/Containers/ContainerLogs/ContainerLogsDialogViewModel.cs | sed -n '55,190p'

echo
echo "=== Search collection usages in ContainerLogs and TerminalOutputView ==="
rg -n -C 3 'CliOutputLine|OutputLines|\.Add\(|Remove|RemoveAt|Clear|Capacity|Max.*Line|Keep|Trim|Limit|TailLines' \
  src/Knarr.App/Features/Containers \
  src/Knarr.App/Controls/TerminalOutputView.axaml.cs \
  || true

echo
echo "=== TerminalOutputView relevant section ==="
awk '{printf "%5d\t%s\n", NR, $0}' src/Knarr.App/Controls/TerminalOutputView.axaml.cs | sed -n '1,280p'

Repository: hard-rox/knarr

Length of output: 32609


Bound and append container log output incrementally.

StreamAsync() clears OutputLines once, then adds every streamed line forever while TerminalOutputView rebuilds the whole inlined text on each CollectionChanged. A continuous follow stream can become quadratic; keep the lines collection bounded by the selected tail limit and reuse existing inlines instead of rebuilding everything.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Knarr.App/Controls/TerminalOutputView.axaml.cs` around lines 211 - 247,
Update TerminalOutputView’s RebuildInlines and streaming output flow so
OutputLines remains bounded to the selected tail limit, removing oldest entries
as new lines arrive. Reuse and append existing Inline elements for newly added
lines, removing only the corresponding leading inlines when the tail evicts
entries, instead of clearing and rebuilding the entire collection on every
CollectionChanged event.

Comment thread src/Knarr.App/Features/Containers/ContainerLogs/ContainerLogsDialog.axaml.cs Outdated
Comment thread src/Knarr.App/Features/Dashboard/DashboardView.axaml
{
if (_viewModel is { CommandPreview: { Length: > 0 } command } &&
TopLevel.GetTopLevel(this)?.Clipboard is { } clipboard)
GetTopLevel(this)?.Clipboard is { } clipboard)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

file="src/Knarr.App/Features/RunContainer/RunContainerDialog.axaml.cs"
rg -n 'using static Avalonia\.Controls\.TopLevel|GetTopLevel\(' "$file"

Repository: hard-rox/knarr

Length of output: 214


🏁 Script executed:

#!/bin/bash
set -euo pipefail

file="src/Knarr.App/Features/RunContainer/RunContainerDialog.axaml.cs"
echo "== file imports and relevant code =="
sed -n '1,80p' "$file"

echo "== repo usages of GetTopLevel =="
rg -n 'GetTopLevel\(' .

Repository: hard-rox/knarr

Length of output: 2344


Use the fully qualified TopLevel.GetTopLevel(this) call here.

RunContainerDialog.axaml.cs only imports Avalonia.Controls; it does not declare using static Avalonia.Controls.TopLevel;, so the unqualified GetTopLevel(...) won’t compile.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Knarr.App/Features/RunContainer/RunContainerDialog.axaml.cs` at line 32,
Update the clipboard lookup in RunContainerDialog to call the fully qualified
Avalonia.Controls.TopLevel.GetTopLevel(this) method, preserving the existing
clipboard pattern and behavior.

Comment on lines +177 to +179
// CliWrap runs its graceful (Ctrl+C) cancellation handler synchronously inside
// CancellationTokenSource.Cancel(); on Windows that console signalling is blocking, so cancelling
// on the UI thread would freeze the app. Offload to a background thread instead.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Condense the cancellation rationale to one line.

The rationale is valid, but the repository’s comment discipline requires a single concise why-comment rather than a three-line explanation.

As per coding guidelines, use the better-code discipline for comments and keep exceptional rationale concise and one-line.

Proposed fix
-    // CliWrap runs its graceful (Ctrl+C) cancellation handler synchronously inside
-    // CancellationTokenSource.Cancel(); on Windows that console signalling is blocking, so cancelling
-    // on the UI thread would freeze the app. Offload to a background thread instead.
+    // Cancel off the UI thread because CLI cancellation can block on Windows.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// CliWrap runs its graceful (Ctrl+C) cancellation handler synchronously inside
// CancellationTokenSource.Cancel(); on Windows that console signalling is blocking, so cancelling
// on the UI thread would freeze the app. Offload to a background thread instead.
// Cancel off the UI thread because CLI cancellation can block on Windows.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Knarr.App/Features/RunContainer/RunContainerDialogViewModel.cs` around
lines 177 - 179, Condense the cancellation rationale comment in the
RunContainerDialogViewModel cancellation flow to one concise line explaining
that CancellationTokenSource.Cancel can block the UI thread on Windows, so
cancellation is offloaded to a background thread.

Source: Coding guidelines

Comment thread src/Knarr.Service/ContainerCliProviderBase.cs
Comment on lines +208 to +209
private static string FormatTimestamp(DateTimeOffset timestamp)
=> timestamp.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ", CultureInfo.InvariantCulture);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== File outline =="
ast-grep outline src/Knarr.Service/ContainerCliProviderBase.cs --view expanded || true

echo "== Relevant lines =="
sed -n '1,260p' src/Knarr.Service/ContainerCliProviderBase.cs | cat -n

echo "== Search timestamp/usages =="
rg -n "FormatTimestamp|--since|--until|DateTimeOffset|Log" src/Knarr.Service src -g '*.cs' || true

echo "== Tests around timestamp/filtering =="
fd -i 'test|container|cli|log' . -t f -d 5 | rg '\.(cs)$' | head -50

Repository: hard-rox/knarr

Length of output: 42529


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== ContainerLogsTests =="
sed -n '1,260p' tests/Knarr.Service.Tests/ContainerLogsCommandTests.cs | cat -n

echo "== Service model files =="
cat -n src/Knarr.Service/Models/ContainerLogsOptions.cs

Repository: hard-rox/knarr

Length of output: 4741


🌐 Web query:

Apple container logs --since --until timestamp format fractional seconds

💡 Result:

The support for fractional seconds and timestamp formats when filtering container logs depends on the container engine being used (e.g., Docker, Podman, or Kubernetes). Docker and Podman For both Docker and Podman, the --since and --until options accept several formats, including support for nanosecond precision [1][2][3]. Supported formats include: - RFC3339 and RFC3339Nano (e.g., 2014-09-16T06:17:46.000000000Z) [1][4][3] - Specific date formats: 2006-01-02T15:04:05, 2006-01-02T15:04:05.999999999, 2006-01-02Z07:00, and 2006-01-02 [1][2][3] - Unix timestamps in the format seconds[.nanoseconds], where the fractional part can have up to nine digits [1][5][3] - Go duration strings (e.g., 10m, 1h30s) [1][2][3] Kubernetes (kubectl) Kubernetes uses the --since-time flag for filtering logs by an exact timestamp [6][7]. This flag requires the timestamp to be in RFC3339 format [6][7]. While the underlying parser for RFC3339 typically supports fractional seconds, the documentation emphasizes the use of RFC3339 specifically [6][7]. Unlike Docker and Podman, kubectl does not natively support providing a raw Unix timestamp with fractional seconds for the --since-time flag [6][8][7]. Instead, for relative time windows, it uses the --since flag, which accepts duration strings (e.g., 5s, 2m, 3h) [6][8][7].

Citations:


🌐 Web query:

Apple container logs since until RFC3339 format

💡 Result:

The native Apple macOS log command does not use RFC3339 for its --start and --end time filtering [1][2]. Instead, it supports the following specific date/time formats [1][3]: - YYYY-MM-DD - YYYY-MM-DD HH:MM:SS - YYYY-MM-DD HH:MM:SSZZZZZ You can use these formats with the log show command, for example: log show --start "2026-07-29 09:00:00" --end "2026-07-29 10:00:00" [1][2] If you are working with container runtimes on macOS (such as Podman or Kubernetes-based tools), those specific tools often support RFC3339 for their own log filtering flags (e.g., --since or --since-time) [4][5][6], but this is a feature of the container engine's CLI, not the underlying macOS system log utility [1][3].

Citations:


Keep fractional seconds on container log timestamps.

ContainerLogsOptions.Since/Until are DateTimeOffset?, but FormatTimestamp drops the fractional ticks before passing values to --since/--until, so boundaries like 10:30:00.500Z become 10:30:00Z. Use a format that preserves fractional seconds and cover this in the log args test.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Knarr.Service/ContainerCliProviderBase.cs` around lines 208 - 209, Update
FormatTimestamp to use a round-trip timestamp format that preserves fractional
seconds while retaining UTC and invariant-culture output for --since/--until
values. Extend the existing log-arguments test to verify fractional
DateTimeOffset boundaries are emitted with their fractional precision.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/Knarr.App/Features/Sidebar/SidebarViewModel.cs`:
- Around line 15-38: Make SidebarViewModel implement IDisposable and add Dispose
to release _badgeSubscription. Ensure the subscription created by
InitializeAsync is disposed and cleared, matching the cleanup behavior of
ImagesViewModel and ContainersViewModel.

In `@src/Knarr.App/Services/AutoRefreshService.cs`:
- Line 43: Remove the leftover Console.WriteLine debug statements, including the
“Subscribing” call and the corresponding call near the second affected location,
from AutoRefreshService methods. Use the existing _logger only where structured
logging is needed, without adding replacement console output.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: ec537c5a-47b9-42c7-b82b-498614847c5c

📥 Commits

Reviewing files that changed from the base of the PR and between 36e98b5 and 2214555.

📒 Files selected for processing (12)
  • README.md
  • docs/RELEASING.md
  • src/Knarr.App/Features/Containers/ContainersViewModel.cs
  • src/Knarr.App/Features/Images/ImagesView.axaml
  • src/Knarr.App/Features/Images/ImagesViewModel.cs
  • src/Knarr.App/Features/Images/PullImageDialog.axaml
  • src/Knarr.App/Features/Shell/MainWindow.axaml.cs
  • src/Knarr.App/Features/Sidebar/SidebarViewModel.cs
  • src/Knarr.App/ServiceCollectionExtensions.cs
  • src/Knarr.App/Services/AutoRefreshService.cs
  • src/Knarr.App/Services/IAutoRefreshService.cs
  • tests/Knarr.App.Tests/Services/AutoRefreshServiceTests.cs

Comment thread src/Knarr.App/Features/Sidebar/SidebarViewModel.cs
Comment thread src/Knarr.App/Services/AutoRefreshService.cs Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
src/Knarr.App/Common/DialogWindow.cs (1)

9-9: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider marking DialogWindow abstract.

DialogWindow is designed only to be inherited (constructor is protected), matching the "shared abstract base class" pattern that justifies the /// XML doc above it. Marking the class abstract makes that intent explicit in the type signature, not only in the constructor accessibility.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Knarr.App/Common/DialogWindow.cs` at line 9, Mark the DialogWindow class
abstract to explicitly enforce its role as an inheritance-only base class, while
preserving its existing protected constructor and Window inheritance.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/Knarr.App/Common/DialogWindow.cs`:
- Around line 33-39: Update DialogWindow.OnClosed to notify the associated view
model when the window closes through any path, not just VM-initiated closure.
Extend IDialogViewModel with an appropriate close/disposal contract or detect
IDisposable, invoke it before detaching handlers, and ensure
ContainerLogsDialogViewModel and other dialog view models with cancellable work
release resources by calling RequestCancellation() from Dispose().

In `@src/Knarr.App/Features/RunContainer/RunContainerDialog.axaml.cs`:
- Around line 10-17: Move the copy behavior out of
RunContainerDialog.OnCopyCommand, leaving the code-behind limited to view
initialization. Add an ICommandProvider-based CopyCommand binding in the dialog
AXAML, and have the view-model command delegate clipboard writes to a
framework-agnostic clipboard service rather than GetTopLevel(this).Clipboard,
preserving the existing non-empty CommandPreview guard and unit-testability.

---

Nitpick comments:
In `@src/Knarr.App/Common/DialogWindow.cs`:
- Line 9: Mark the DialogWindow class abstract to explicitly enforce its role as
an inheritance-only base class, while preserving its existing protected
constructor and Window inheritance.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: a5a40e7c-cb00-4621-ab0a-b0c4fffc53b5

📥 Commits

Reviewing files that changed from the base of the PR and between d58e6c8 and 9bfb816.

📒 Files selected for processing (20)
  • src/Knarr.App/Common/DialogWindow.cs
  • src/Knarr.App/Common/IDialogViewModel.cs
  • src/Knarr.App/Features/Containers/ContainerLogs/ContainerLogsDialog.axaml
  • src/Knarr.App/Features/Containers/ContainerLogs/ContainerLogsDialog.axaml.cs
  • src/Knarr.App/Features/Containers/ContainerLogs/ContainerLogsDialogViewModel.cs
  • src/Knarr.App/Features/Containers/ContainersView.axaml.cs
  • src/Knarr.App/Features/Containers/ContainersViewModel.cs
  • src/Knarr.App/Features/Images/ImagesView.axaml.cs
  • src/Knarr.App/Features/Images/ImagesViewModel.cs
  • src/Knarr.App/Features/Images/PullImageDialog.axaml
  • src/Knarr.App/Features/Images/PullImageDialog.axaml.cs
  • src/Knarr.App/Features/Images/PullImageDialogViewModel.cs
  • src/Knarr.App/Features/RunContainer/RunContainerDialog.axaml
  • src/Knarr.App/Features/RunContainer/RunContainerDialog.axaml.cs
  • src/Knarr.App/Features/RunContainer/RunContainerDialogViewModel.cs
  • src/Knarr.App/ServiceCollectionExtensions.cs
  • src/Knarr.App/Services/DialogService.cs
  • src/Knarr.App/Services/IDialogService.cs
  • tests/Knarr.App.Tests/Features/Containers/ContainersViewModelTests.cs
  • tests/Knarr.App.Tests/Features/Images/ImagesViewModelTests.cs
🚧 Files skipped from review as they are similar to previous changes (5)
  • tests/Knarr.App.Tests/Features/Containers/ContainersViewModelTests.cs
  • src/Knarr.App/Features/Containers/ContainerLogs/ContainerLogsDialog.axaml
  • src/Knarr.App/Features/RunContainer/RunContainerDialogViewModel.cs
  • src/Knarr.App/Features/Images/PullImageDialogViewModel.cs
  • src/Knarr.App/Features/Containers/ContainerLogs/ContainerLogsDialogViewModel.cs

Comment on lines +33 to +39
private void OnClosed(object? sender, EventArgs e)
{
DetachViewModel();

DataContextChanged -= OnDataContextChanged;
Closed -= OnClosed;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Notify the view model on every close path, not only the VM-initiated one.

OnClosed runs for both the title-bar close and the VM's Close() command, because Avalonia raises the same Closed event either way. Only the VM-initiated path (Close()RequestCancellation()CloseRequested) performs cleanup. OnClosed here only detaches handlers; it never tells the view model that the window is gone.

For ContainerLogsDialogViewModel, closing the window through the title bar bypasses RequestCancellation(), so an active log-follow stream can keep running after the window disappears. This generalizes the earlier feedback on ContainerLogsDialog.axaml.cs's removed OnClosed override: the responsibility now lives here, and it affects every DialogWindow-derived dialog.

Extend IDialogViewModel (or check for IDisposable) so OnClosed can release view-model resources regardless of which path triggered the close.

🔧 Proposed fix
 private void OnClosed(object? sender, EventArgs e)
 {
+    (_viewModel as IDisposable)?.Dispose();
     DetachViewModel();

     DataContextChanged -= OnDataContextChanged;
     Closed -= OnClosed;
 }
 public interface IDialogViewModel
 {
     event EventHandler? CloseRequested;
 }

Have ContainerLogsDialogViewModel (and other dialog view models with cancellable work) implement IDisposable and call RequestCancellation() from Dispose().

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Knarr.App/Common/DialogWindow.cs` around lines 33 - 39, Update
DialogWindow.OnClosed to notify the associated view model when the window closes
through any path, not just VM-initiated closure. Extend IDialogViewModel with an
appropriate close/disposal contract or detect IDisposable, invoke it before
detaching handlers, and ensure ContainerLogsDialogViewModel and other dialog
view models with cancellable work release resources by calling
RequestCancellation() from Dispose().

Comment on lines 10 to 17
private async void OnCopyCommand(object? sender, RoutedEventArgs e)
{
if (_viewModel is { CommandPreview: { Length: > 0 } command } &&
TopLevel.GetTopLevel(this)?.Clipboard is { } clipboard)
if (DataContext is RunContainerDialogViewModel { CommandPreview: { Length: > 0 } command } &&
GetTopLevel(this)?.Clipboard is { } clipboard)
{
await clipboard.SetTextAsync(command);
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

ast-grep outline src/Knarr.App --items all --type class,interface --match 'Clipboard|Dialog|Service'

rg -n -C 4 \
  'Clipboard|SetTextAsync|OnCopyCommand|OnCopyImageName|CopyCommand' \
  src/Knarr.App

Repository: hard-rox/knarr

Length of output: 7181


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '--- RunContainer files ---\n'
for f in \
  src/Knarr.App/Features/RunContainer/RunContainerDialog.axaml.cs \
  src/Knarr.App/Features/RunContainer/RunContainerDialog.axaml \
  src/Knarr.App/Features/RunContainer/RunContainerDialogViewModel.cs
do
  if [ -f "$f" ]; then
    echo "### $f"
    wc -l "$f"
    sed -n '1,220p' "$f"
  fi
done

printf '\n--- Service registrations ---\n'
sed -n '1,240p' src/Knarr.App/ServiceCollectionExtensions.cs

printf '\n--- Related services around UI clipboard candidates ---\n'
rg -n -C 3 'interface|abstract class|class .*Service|SetTextAs|Clipboard|GetTopLevel|TopLevel.Get' \
  src/Knarr.App/Services src/Knarr.App/Common src/Knarr.App/Features src/Knarr.App/Controls

Repository: hard-rox/knarr

Length of output: 243


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- RunContainer files ---'
for f in \
  src/Knarr.App/Features/RunContainer/RunContainerDialog.axaml.cs \
  src/Knarr.App/Features/RunContainer/RunContainerDialog.axaml \
  src/Knarr.App/Features/RunContainer/RunContainerDialogViewModel.cs
do
  if [ -f "$f" ]; then
    echo "### $f"
    wc -l "$f"
    sed -n '1,220p' "$f"
  fi
done

printf '%s\n' ''
printf '%s\n' '--- Service registrations ---'
sed -n '1,240p' src/Knarr.App/ServiceCollectionExtensions.cs

printf '%s\n' ''
printf '%s\n' '--- Related services around UI clipboard candidates ---'
rg -n -C 3 'interface|abstract class|class .*Service|SetTextAs|Clipboard|GetTopLevel|TopLevel.Get' \
  src/Knarr.App/Services src/Knarr.App/Common src/Knarr.App/Features src/Knarr.App/Controls

Repository: hard-rox/knarr

Length of output: 28065


Move clipboard handling out of code-behind.

RunContainerDialog.OnCopyCommand contains user-action logic instead of only InitializeComponent(). Add ICommandProvider/CopyCommand binding from AXAML and move the Avalonia clipboard call into a framework-agnostic clipboard service so the view model remains UI-frame work-agnostic and unit-testable.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Knarr.App/Features/RunContainer/RunContainerDialog.axaml.cs` around lines
10 - 17, Move the copy behavior out of RunContainerDialog.OnCopyCommand, leaving
the code-behind limited to view initialization. Add an ICommandProvider-based
CopyCommand binding in the dialog AXAML, and have the view-model command
delegate clipboard writes to a framework-agnostic clipboard service rather than
GetTopLevel(this).Clipboard, preserving the existing non-empty CommandPreview
guard and unit-testability.

Source: Coding guidelines

hard-rox added 3 commits July 31, 2026 19:05
- Introduced `SupportsBootLogs`, `SupportsLogTimestamps`, and `SupportsLogTimeRange` to `IContainerCliProvider` for CLI feature compatibility.
- Updated `ContainerLogsDialogViewModel` and dialog to include boot log option.
- Adjusted command builders to conditionally include new flags.
- Enhanced tests to verify CLI compatibility and command generation.
…nce `ContainerLogsDialogViewModel`

- Refactored XAML resource dictionaries to improve readability and indentation consistency.
- Simplified `App` class by removing `partial`.
- Improved logging and property initialization in `ContainerLogsDialogViewModel`, consolidating constructors and refining error handling.
- Combined similar CLI output cases in `CliOutputKindToBrushConverter`.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/Knarr.App/Features/Containers/ContainersViewModel.cs (1)

151-152: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Remove the comment on the private method.

Lines 151-152 document private LoadAsync. The C# guideline prohibits comments and XML documentation on private or internal members.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Knarr.App/Features/Containers/ContainersViewModel.cs` around lines 151 -
152, Remove the two-line comment immediately preceding the private LoadAsync
method in ContainersViewModel, leaving the method implementation unchanged.

Source: Coding guidelines

🧹 Nitpick comments (2)
src/Knarr.App/App.axaml (1)

7-27: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use two-space indentation throughout the changed AXAML.

The same indentation violation appears in all six AXAML files. Reformat the changed ranges with two-space indentation.

  • src/Knarr.App/App.axaml#L7-L27: reindent the application resources and style includes.
  • src/Knarr.App/Controls/Pill.axaml#L4-L45: reindent the preview, template, setters, and status styles.
  • src/Knarr.App/Controls/Tile.axaml#L4-L37: reindent the preview, template, setters, and status styles.
  • src/Knarr.App/Features/Shell/MainWindow.axaml#L20-L20: reindent the design data element.
  • src/Knarr.App/Features/Shell/MainWindow.axaml#L42-L48: reindent the theme menu items.
  • src/Knarr.App/Features/Shell/MainWindow.axaml#L68-L73: reindent the menu bar and sidebar elements.
  • src/Knarr.App/Features/Shell/MainWindow.axaml#L84-L89: reindent the page title and transition elements.
  • src/Knarr.App/Features/Shell/MainWindow.axaml#L98-L98: reindent the fallback visibility binding.
  • src/Knarr.App/Themes/Styles.axaml#L2-L112: reindent the styles and selectors.
  • src/Knarr.App/Themes/Glass.axaml#L4-L74: reindent the theme dictionaries and palette.
  • src/Knarr.App/Themes/Glass.axaml#L86-L122: reindent the table resources and theme.

As per coding guidelines, **/*.axaml files must use 2-space indentation for AXAML/XML.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Knarr.App/App.axaml` around lines 7 - 27, Reindent all specified changed
AXAML ranges using consistent two-space indentation, preserving the existing
elements and attributes. Apply this to src/Knarr.App/App.axaml (7-27),
src/Knarr.App/Controls/Pill.axaml (4-45), src/Knarr.App/Controls/Tile.axaml
(4-37), the listed ranges in src/Knarr.App/Features/Shell/MainWindow.axaml (20,
42-48, 68-73, 84-89, 98), src/Knarr.App/Themes/Styles.axaml (2-112), and
src/Knarr.App/Themes/Glass.axaml (4-74, 86-122).

Source: Coding guidelines

src/Knarr.App/Features/Sidebar/SidebarViewModel.cs (1)

34-34: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Rename services1 to a meaningful name.

Use services directly or rename the local variable to serviceProvider. services1 does not identify the dependency.

Proposed rename
-IServiceProvider services1 = services;
...
-() => services1.GetRequiredService<ContainersViewModel>()
+() => services.GetRequiredService<ContainersViewModel>()

Apply the same rename to the other navigation factories.

As per coding guidelines: “Keep names self-explanatory.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Knarr.App/Features/Sidebar/SidebarViewModel.cs` at line 34, Rename the
local variable services1 in the SidebarViewModel navigation-factory setup to
serviceProvider, or use the existing services parameter directly; apply the same
meaningful naming consistently across the other navigation factories.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/Knarr.App/App.axaml.cs`:
- Line 9: Restore the partial modifier on the App class declaration in
App.axaml.cs so it matches the XAML-generated companion class for
x:Class="Knarr.App.App" and allows Avalonia generated code to compile.

In `@src/Knarr.App/Features/Sidebar/SidebarViewModel.cs`:
- Around line 79-83: Apply the formatter’s attribute layout in both affected
files: in src/Knarr.App/Features/Sidebar/SidebarViewModel.cs lines 79-83, place
each attribute for _cliName and _cliVersion on its own four-space-indented line;
in src/Knarr.App/Models/NavigationItem.cs line 14, split the attributes for
_badge the same way.
- Around line 38-55: Fix the parameterless SidebarViewModel fallback so it no
longer passes a null service provider into the constructor or page factories.
Update SidebarViewModel() and the related MainWindowViewModel() fallback to
create or reuse a valid service graph, including the dependencies required by
InitializeAsync and each GetRequiredService-based NavigationItem factory;
alternatively remove or replace those parameterless constructors while
preserving page creation.

---

Outside diff comments:
In `@src/Knarr.App/Features/Containers/ContainersViewModel.cs`:
- Around line 151-152: Remove the two-line comment immediately preceding the
private LoadAsync method in ContainersViewModel, leaving the method
implementation unchanged.

---

Nitpick comments:
In `@src/Knarr.App/App.axaml`:
- Around line 7-27: Reindent all specified changed AXAML ranges using consistent
two-space indentation, preserving the existing elements and attributes. Apply
this to src/Knarr.App/App.axaml (7-27), src/Knarr.App/Controls/Pill.axaml
(4-45), src/Knarr.App/Controls/Tile.axaml (4-37), the listed ranges in
src/Knarr.App/Features/Shell/MainWindow.axaml (20, 42-48, 68-73, 84-89, 98),
src/Knarr.App/Themes/Styles.axaml (2-112), and src/Knarr.App/Themes/Glass.axaml
(4-74, 86-122).

In `@src/Knarr.App/Features/Sidebar/SidebarViewModel.cs`:
- Line 34: Rename the local variable services1 in the SidebarViewModel
navigation-factory setup to serviceProvider, or use the existing services
parameter directly; apply the same meaningful naming consistently across the
other navigation factories.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 2376d047-f91c-447d-9698-a060f7a78e6c

📥 Commits

Reviewing files that changed from the base of the PR and between 9bfb816 and 2030aec.

📒 Files selected for processing (45)
  • .idea/.idea.Knarr/.idea/avalonia.xml
  • Directory.Packages.props
  • src/Knarr.App/App.axaml
  • src/Knarr.App/App.axaml.cs
  • src/Knarr.App/Common/IDialogViewModel.cs
  • src/Knarr.App/Controls/Pill.axaml
  • src/Knarr.App/Controls/TerminalOutputView.axaml
  • src/Knarr.App/Controls/Tile.axaml
  • src/Knarr.App/Converters/CliOutputKindToBrushConverter.cs
  • src/Knarr.App/Features/Containers/ContainerLogs/ContainerLogsDialog.axaml
  • src/Knarr.App/Features/Containers/ContainerLogs/ContainerLogsDialogViewModel.cs
  • src/Knarr.App/Features/Containers/ContainersView.axaml
  • src/Knarr.App/Features/Containers/ContainersViewModel.cs
  • src/Knarr.App/Features/Dashboard/DashboardView.axaml
  • src/Knarr.App/Features/Dashboard/DashboardViewModel.cs
  • src/Knarr.App/Features/Images/ImagesViewModel.cs
  • src/Knarr.App/Features/Images/PullImageDialog.axaml
  • src/Knarr.App/Features/Images/PullImageDialogViewModel.cs
  • src/Knarr.App/Features/RunContainer/EnvironmentVariableEntry.cs
  • src/Knarr.App/Features/RunContainer/PortMappingEntry.cs
  • src/Knarr.App/Features/RunContainer/RunContainerDialog.axaml
  • src/Knarr.App/Features/RunContainer/RunContainerDialogViewModel.cs
  • src/Knarr.App/Features/RunContainer/VolumeMountEntry.cs
  • src/Knarr.App/Features/Settings/SettingsView.axaml
  • src/Knarr.App/Features/Settings/SettingsViewModel.cs
  • src/Knarr.App/Features/Shell/MainWindow.axaml
  • src/Knarr.App/Features/Shell/MainWindowViewModel.cs
  • src/Knarr.App/Features/Sidebar/Sidebar.axaml
  • src/Knarr.App/Features/Sidebar/SidebarViewModel.cs
  • src/Knarr.App/Models/ContainerItem.cs
  • src/Knarr.App/Models/ImageItem.cs
  • src/Knarr.App/Models/NavigationItem.cs
  • src/Knarr.App/Program.cs
  • src/Knarr.App/Services/AutoRefreshService.cs
  • src/Knarr.App/Services/DialogService.cs
  • src/Knarr.App/Services/IDialogService.cs
  • src/Knarr.App/Themes/Glass.axaml
  • src/Knarr.App/Themes/Icons.axaml
  • src/Knarr.App/Themes/Styles.axaml
  • src/Knarr.Service/AppleContainerCli/AppleContainerCliProvider.cs
  • src/Knarr.Service/ContainerCliProviderBase.cs
  • src/Knarr.Service/IContainerCliProvider.cs
  • src/Knarr.Service/Models/ContainerLogsOptions.cs
  • tests/Knarr.App.Tests/Features/RunContainer/RunContainerDialogViewModelTests.cs
  • tests/Knarr.Service.Tests/ContainerLogsCommandTests.cs
💤 Files with no reviewable changes (1)
  • src/Knarr.App/Themes/Icons.axaml
🚧 Files skipped from review as they are similar to previous changes (29)
  • Directory.Packages.props
  • src/Knarr.Service/Models/ContainerLogsOptions.cs
  • src/Knarr.App/Services/IDialogService.cs
  • src/Knarr.App/Common/IDialogViewModel.cs
  • src/Knarr.App/Converters/CliOutputKindToBrushConverter.cs
  • src/Knarr.App/Features/RunContainer/EnvironmentVariableEntry.cs
  • src/Knarr.App/Services/DialogService.cs
  • tests/Knarr.App.Tests/Features/RunContainer/RunContainerDialogViewModelTests.cs
  • src/Knarr.App/Features/Dashboard/DashboardView.axaml
  • src/Knarr.App/Features/Images/PullImageDialogViewModel.cs
  • src/Knarr.App/Features/RunContainer/VolumeMountEntry.cs
  • src/Knarr.App/Features/Containers/ContainerLogs/ContainerLogsDialog.axaml
  • src/Knarr.App/Features/Images/PullImageDialog.axaml
  • src/Knarr.App/Features/RunContainer/PortMappingEntry.cs
  • src/Knarr.App/Features/Settings/SettingsView.axaml
  • src/Knarr.App/Models/ImageItem.cs
  • src/Knarr.Service/AppleContainerCli/AppleContainerCliProvider.cs
  • src/Knarr.App/Features/Shell/MainWindowViewModel.cs
  • src/Knarr.App/Features/Containers/ContainersView.axaml
  • src/Knarr.App/Program.cs
  • src/Knarr.App/Features/RunContainer/RunContainerDialogViewModel.cs
  • src/Knarr.App/Features/Containers/ContainerLogs/ContainerLogsDialogViewModel.cs
  • src/Knarr.App/Models/ContainerItem.cs
  • src/Knarr.App/Controls/TerminalOutputView.axaml
  • src/Knarr.App/Services/AutoRefreshService.cs
  • src/Knarr.App/Features/RunContainer/RunContainerDialog.axaml
  • src/Knarr.App/Features/Images/ImagesViewModel.cs
  • src/Knarr.Service/ContainerCliProviderBase.cs
  • src/Knarr.App/Features/Sidebar/Sidebar.axaml

namespace Knarr.App;

public partial class App : Application
public class App : Application

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

if ! rg -q 'x:Class="Knarr\.App\.App"' src/Knarr.App/App.axaml; then
  echo "Expected App.axaml x:Class declaration was not found." >&2
  exit 1
fi

if ! rg -q 'public\s+partial\s+class\s+App\s*:\s*Application' src/Knarr.App/App.axaml.cs; then
  echo "App.axaml.cs must declare App as partial." >&2
  exit 1
fi

Repository: hard-rox/knarr

Length of output: 194


Restore partial on App.

src/Knarr.App/App.axaml declares x:Class="Knarr.App.App". Avalonia requires that XAML code-target class to remain partial so generated companion code can compile with App.axaml.cs.

Proposed fix
-public class App : Application
+public partial class App : Application
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public class App : Application
public partial class App : Application
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Knarr.App/App.axaml.cs` at line 9, Restore the partial modifier on the
App class declaration in App.axaml.cs so it matches the XAML-generated companion
class for x:Class="Knarr.App.App" and allows Avalonia generated code to compile.

Comment on lines +38 to +55
_systemService = services.GetService<IContainerSystemService>();

_containersItem = new NavigationItem(
"Containers", "CubeRegular", createPage: () => _services.GetRequiredService<ContainersViewModel>());
"Containers", "CubeRegular", createPage: () => services1.GetRequiredService<ContainersViewModel>());
_imagesItem = new NavigationItem(
"Images", "CloudRegular", createPage: () => _services.GetRequiredService<ImagesViewModel>());
"Images", "CloudRegular", createPage: () => services1.GetRequiredService<ImagesViewModel>());

NavigationItems =
[
new NavigationItem("Dashboard", "BoardRegular", createPage: () => _services.GetRequiredService<DashboardViewModel>()),
new NavigationItem("Dashboard", "BoardRegular",
createPage: () => services1.GetRequiredService<DashboardViewModel>()),
_containersItem,
_imagesItem,
new NavigationItem("Networks", "GlobeRegular", "3"),
new NavigationItem("Volumes", "StorageRegular", "5"),
new NavigationItem("Registries", "LibraryRegular"),
new NavigationItem("Settings", "SettingsRegular", createPage: () => _services.GetRequiredService<SettingsViewModel>()),
new NavigationItem("Settings", "SettingsRegular",
createPage: () => services1.GetRequiredService<SettingsViewModel>()),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift

Fix the null service-provider path used by the fallback constructors.

SidebarViewModel() passes null! for services, but this constructor calls services.GetService<IContainerSystemService>() and creates factories that call services1.GetRequiredService(...). MainWindowViewModel() uses that fallback and invokes the selected page factory, so the fallback path throws NullReferenceException. InitializeAsync also has a null _cliProvider.

Provide a real service graph for the parameterless constructors, or remove or replace those constructors. A null check around _systemService alone will not fix the page factories.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Knarr.App/Features/Sidebar/SidebarViewModel.cs` around lines 38 - 55, Fix
the parameterless SidebarViewModel fallback so it no longer passes a null
service provider into the constructor or page factories. Update
SidebarViewModel() and the related MainWindowViewModel() fallback to create or
reuse a valid service graph, including the dependencies required by
InitializeAsync and each GetRequiredService-based NavigationItem factory;
alternatively remove or replace those parameterless constructors while
preserving page creation.

Comment on lines 79 to 83
[ObservableProperty] [NotifyPropertyChangedFor(nameof(CliDisplay))]
private string _cliName = "wslc";

[ObservableProperty]
[NotifyPropertyChangedFor(nameof(CliDisplay))]
[ObservableProperty] [NotifyPropertyChangedFor(nameof(CliDisplay))]
private string _cliVersion = "detecting\u2026";

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Apply the formatter’s attribute layout in both files.

The same inline attribute pattern triggers the CI whitespace check. Split each attribute into its own four-space-indented line.

  • src/Knarr.App/Features/Sidebar/SidebarViewModel.cs#L79-L83: split the attributes for _cliName and _cliVersion.
  • src/Knarr.App/Models/NavigationItem.cs#L14-L14: split the attributes for _badge.
🧰 Tools
🪛 GitHub Actions: CI / 0_Lint, Build & Test (ubuntu-latest).txt

[error] 79-79: dotnet format --verify-no-changes failed: whitespace formatting error. Replace 1 character with a CRLF newline followed by four spaces.

🪛 GitHub Actions: CI / Lint, Build & Test (ubuntu-latest)

[error] 79-79: dotnet format verification failed: WHITESPACE formatting issue. Replace 1 character with a newline and indentation.

🪛 GitHub Check: Lint, Build & Test (ubuntu-latest)

[failure] 82-82:
Fix whitespace formatting. Replace 1 characters with '\r\n\s\s\s\s'.


[failure] 79-79:
Fix whitespace formatting. Replace 1 characters with '\r\n\s\s\s\s'.

📍 Affects 2 files
  • src/Knarr.App/Features/Sidebar/SidebarViewModel.cs#L79-L83 (this comment)
  • src/Knarr.App/Models/NavigationItem.cs#L14-L14
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Knarr.App/Features/Sidebar/SidebarViewModel.cs` around lines 79 - 83,
Apply the formatter’s attribute layout in both affected files: in
src/Knarr.App/Features/Sidebar/SidebarViewModel.cs lines 79-83, place each
attribute for _cliName and _cliVersion on its own four-space-indented line; in
src/Knarr.App/Models/NavigationItem.cs line 14, split the attributes for _badge
the same way.

Source: Linters/SAST tools

…matting consistency

- Changed `end_of_line` to `lf` in `.editorconfig`.
- Adjusted attribute formatting in `SidebarViewModel`, `NavigationItem`, and other classes for clarity.
- Renamed constant `Executable` to `_executable` in `AppleContainerSystemService` for naming consistency.
@hard-rox
hard-rox merged commit a3ac2fd into main Aug 1, 2026
4 checks passed
@hard-rox
hard-rox deleted the feature/container-logs branch August 1, 2026 03:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant