Help us shape the future of Go! Take the 2026 Go Developer Survey

launcher

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 1, 2026 License: GPL-3.0 Imports: 17 Imported by: 0

README

sysc-launch

sysc-launch is a Go launcher engine and diagnostic CLI for Niri. It is a presentation-neutral library consumed by sysc-shell.

The module discovers desktop applications, ranks queries, and activates entries through Niri. It does not provide a standalone Wayland UI or daemon; sysc-shell owns the launcher panel and all presentation.

Requirements

  • Go 1.26.4
  • Niri in PATH for activation

Desktop scanning and query work without Niri.

Build and install

From a clone of this repository:

go build -o ./bin/sysc-launch ./cmd/sysc-launch
go install ./cmd/sysc-launch

go install writes the command to GOBIN, or to Go's default binary directory when GOBIN is unset.

CLI

sysc-launch query [QUERY]
sysc-launch launch DESKTOP_ID [ACTION_ID]

query writes one JSON array of results to standard output. Each result has an Entry containing the desktop ID, display metadata, expanded argument vector, terminal flag, and desktop actions, plus its numeric Score. With no query it returns the current application list. A query beginning with / uses the provider-prefix routing; /apps selects installed applications.

launch activates the identified application or optional desktop action via:

niri msg action spawn -- PROGRAM [ARG...]

Arguments come from the desktop entry and are passed without a shell.

Library

Import the module as:

import launcher "github.com/Nomadcxx/sysc-launch"

A service scans immediately. Wait for that initial result before submitting a query so the response is based on the discovered entries:

package main

import (
	"fmt"
	"log"
	"time"

	launcher "github.com/Nomadcxx/sysc-launch"
)

func main() {
	service := launcher.NewService(launcher.ServiceConfig{
		History: launcher.DefaultHistory(log.Printf),
		Logf:    log.Printf,
	})
	defer service.Close()

	wait := func() ([]launcher.Result, error) {
		select {
		case results := <-service.Results():
			return results, nil
		case <-time.After(5 * time.Second):
			return nil, fmt.Errorf("timed out waiting for launcher results")
		}
	}

	if _, err := wait(); err != nil { // initial XDG scan
		log.Print(err)
		return
	}
	service.Query("terminal")
	results, err := wait()
	if err != nil {
		log.Print(err)
		return
	}
	fmt.Println(results)
}

Query and Open are asynchronous. Activate is synchronous and records usage only after Niri reports a successful spawn. Call Close when the service is no longer needed.

Discovery and ranking

The scanner reads .desktop files from $XDG_DATA_HOME/applications and each applications directory under $XDG_DATA_DIRS; the standard HOME and system fallbacks apply when those variables are unset. User entries take precedence. It excludes entries marked Hidden or NoDisplay, entries rejected by OnlyShowIn or NotShowIn, and entries whose TryExec is unavailable.

Terminal=true entries use $TERMINAL when configured, then try kitty, foot, alacritty, wezterm, and ghostty. Such an entry is excluded when no terminal can be resolved. Valid desktop actions are exposed separately and can be selected by action ID.

Application names, generic names, keywords, commands, and comments are fuzzy matched with fzf's ranking algorithm. Recent and repeated successful launches add a usage boost capped at 25 points, so history influences ranking without overwhelming a clearly better text match.

History and privacy

The default history file is:

$XDG_STATE_HOME/sysc-launch/history.gob

If XDG_STATE_HOME is unset, it falls back to:

$HOME/.local/state/sysc-launch/history.gob

History is local gob data written with owner-only file permissions. Successful launches persist the associated query prefixes and desktop IDs, so the file can reveal application-launch habits. Delete it to reset ranking history.

sysc-shell deliberately opens its legacy independent path, $XDG_STATE_HOME/sysc-shell/launcher/history.gob (with the corresponding $HOME/.local/state fallback), instead of this module's default. The two applications therefore do not merge history.

Checks

go test -count=1 ./...
go test -race -count=1 ./...
go vet ./...
go build ./...

License

GPL-3.0-only. See LICENSE.

Documentation

Index

Constants

View Source
const PlaceholderGlyph = "□"

Variables

View Source
var ErrNoTerminal = errors.New("launcher: no terminal found")
View Source
var ErrServiceClosed = errors.New("launcher: service closed")

Functions

This section is empty.

Types

type Action

type Action struct {
	ID, Name, IconName string
	Argv               []string
}

type Entry

type Entry struct {
	ID, Name, GenericName string
	Keywords              []string
	Argv                  []string
	Comment, IconName     string
	Terminal              bool
	Actions               []Action
}

type History

type History struct {
	// contains filtered or unexported fields
}

History stores launcher usage for ranking and persists successful activations.

func DefaultHistory

func DefaultHistory(logf func(string, ...any)) *History

DefaultHistory loads usage history from $XDG_STATE_HOME/sysc-launch/history.gob, falling back to $HOME/.local/state/sysc-launch/history.gob. The logf argument receives history load and save diagnostics; nil suppresses those diagnostics.

func OpenHistory

func OpenHistory(path string, logf func(string, ...any)) *History

OpenHistory loads the on-disk usage history at path. The logf argument receives history load and save diagnostics; nil suppresses those diagnostics.

type Provider

type Provider struct {
	Name        string
	Prefix      string
	Glyph       string
	Description string
	Query       func(query string) []Result
}

Provider is one launcher source behind a "/" prefix. The registry is an ordered slice; the first entry is the default provider for bare queries. Later providers append without any layout or routing change.

type Result

type Result struct {
	Entry Entry
	Score int
}

type Service

type Service struct {
	// contains filtered or unexported fields
}

Service owns the collector and query goroutines (D12). All state crosses goroutine boundaries as immutable snapshots through channels; no Wayland types appear in this package.

func NewService

func NewService(cfg ServiceConfig) *Service

func (*Service) Activate

func (s *Service) Activate(id, action string) error

Activate spawns the entry (or one of its desktop actions) through `niri msg action spawn` on the service goroutine and records usage only when the spawn succeeds (D6/D9).

func (*Service) Close

func (s *Service) Close()

func (*Service) Open

func (s *Service) Open()

Open triggers a rescan when the entry snapshot is stale.

func (*Service) Query

func (s *Service) Query(text string)

Query submits a new query; it supersedes any queued or in-flight older one.

func (*Service) Results

func (s *Service) Results() <-chan []Result

Results publishes ranked results as immutable slices, latest wins.

type ServiceConfig

type ServiceConfig struct {
	Scan            func() []Entry
	History         *History
	Rank            func(entries []Entry, query string, boost func(query, identifier string) int) []Result
	Run             func(ctx context.Context, argv []string) error
	Getenv          func(string) string
	LookPath        func(string) (string, error)
	Now             func() time.Time
	Logf            func(string, ...any)
	StaleAfter      time.Duration
	ActivateTimeout time.Duration
}

ServiceConfig wires the launcher service. Nil Scan, Rank, Run, Getenv, LookPath, and Now use the XDG desktop scanner, built-in ranker, Niri spawn, os.Getenv, exec.LookPath, and time.Now. Non-positive StaleAfter and ActivateTimeout use one minute and five seconds. Nil History disables usage persistence and boosting; nil Logf suppresses scanner diagnostics.

Directories

Path Synopsis
cmd
sysc-launch command

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL