Skip to content

fix(daemon): set XDG_RUNTIME_DIR for systemctl --user commands on Linux#171

Merged
AnnatarHe merged 1 commit intomainfrom
fix/linux-daemon-install-systemd-session
Dec 27, 2025
Merged

fix(daemon): set XDG_RUNTIME_DIR for systemctl --user commands on Linux#171
AnnatarHe merged 1 commit intomainfrom
fix/linux-daemon-install-systemd-session

Conversation

@AnnatarHe
Copy link
Copy Markdown
Contributor

Summary

  • Fixes daemon install failing in SSH sessions and other environments where XDG_RUNTIME_DIR is not set
  • Adds helper method systemctlUserCmd() that properly sets XDG_RUNTIME_DIR environment variable for all systemctl --user commands
  • Automatically enables linger via loginctl enable-linger when the user's systemd session isn't running
  • Waits for the runtime directory to be created before proceeding with systemctl commands

Problem

When running shelltime daemon install in an SSH session or other non-interactive environment, the command would fail with:

failed to reload systemd: exit status 1

This was because systemctl --user requires XDG_RUNTIME_DIR to be set (typically /run/user/<uid>), which isn't available in certain session types.

Test plan

  • Tested by disabling linger and removing runtime directory, then running go run cmd/cli/main.go daemon install
  • Verified the fix automatically enables linger and creates the user systemd session
  • Confirmed the daemon service starts and runs correctly after installation
  • Build passes with go build ./...

🤖 Generated with Claude Code

The daemon install command was failing in SSH sessions and other
environments where XDG_RUNTIME_DIR is not set, causing systemctl --user
commands to fail with "Failed to connect to bus".

This fix:
- Adds a helper method to create systemctl commands with proper
  XDG_RUNTIME_DIR environment variable
- Automatically detects when the user's systemd session isn't running
  and enables linger via loginctl
- Waits for the runtime directory to be created before proceeding
- Provides clear error messages if the session cannot be started

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello @AnnatarHe, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request provides a critical fix for the daemon installation process on Linux, specifically addressing issues encountered in non-interactive sessions like SSH. By standardizing the handling of XDG_RUNTIME_DIR for systemctl --user commands, automatically enabling user session linger, and incorporating a wait for the runtime directory, the changes significantly improve the robustness and reliability of daemon installation across various user environments.

Highlights

  • XDG_RUNTIME_DIR Fix: Resolves daemon installation failures in SSH and other non-interactive environments by correctly setting the XDG_RUNTIME_DIR for systemctl --user commands.
  • systemctlUserCmd Helper: Introduces a new helper function systemctlUserCmd() to encapsulate systemctl --user calls and ensure the XDG_RUNTIME_DIR environment variable is always properly configured.
  • Linger Enablement: Automatically enables loginctl enable-linger to ensure user systemd session persistence when it's not already running.
  • Runtime Directory Wait: Implements a waiting mechanism to ensure the XDG_RUNTIME_DIR is created and available before proceeding with systemctl operations.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@codecov
Copy link
Copy Markdown

codecov Bot commented Dec 27, 2025

Codecov Report

❌ Patch coverage is 0% with 33 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
model/daemon-installer.linux.go 0.00% 33 Missing ⚠️
Flag Coverage Δ
unittests 19.91% <0.00%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
model/daemon-installer.linux.go 0.00% <0.00%> (ø)

... and 1 file with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request effectively addresses the issue of systemctl --user commands failing in non-interactive environments like SSH by ensuring XDG_RUNTIME_DIR is properly set. The introduction of the systemctlUserCmd helper is a clean way to centralize this logic and has been applied consistently across the Linux daemon installer. The addition of ensureUserSystemdSession to automatically enable linger and wait for the user session is a robust solution to the underlying problem. The code is well-structured, and the changes are logical. I have one minor suggestion to improve maintainability regarding the use of named constants.

Comment on lines +58 to +59
for i := 0; i < 10; i++ {
time.Sleep(500 * time.Millisecond)
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.

medium

The retry count (10) and sleep interval (500ms) are hardcoded. It's a best practice to define such 'magic numbers' as named constants. This improves readability by giving them a meaningful name and makes them easier to find and modify in the future.

I'd recommend defining them at the package level, for example:

const (
	runtimeDirCreationRetries = 10
	runtimeDirCreationInterval = 500 * time.Millisecond
)

Then, you can use these constants within your loop.

@AnnatarHe AnnatarHe merged commit 5cba371 into main Dec 27, 2025
4 of 5 checks passed
@AnnatarHe AnnatarHe deleted the fix/linux-daemon-install-systemd-session branch December 27, 2025 01:55
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