* Add Live Activities as configurable bar items * Fix activity owner monitoring and Morph list interactions * Keep activity rows stable during updates and tighten their layout * Use subtle theme tint for activity cards * Tighten activity title and progress spacing * Use theme accent for active progress rings * Fit compact activities to measured titles and badge * Expose Live Activities display controls in Settings * Open activity terminals and streamline the Morph header * Give Morph continuous icons and prioritize workspace navigation * Show activity progress inside its ring * Inset activity progress rings and strengthen their stroke * Fix activity lifecycle, command output handling and list navigation * Reduce activity update work and harden publisher lifetimes * Set up Live Activities for the detected user shell during installation * Document Activities setup, daily use and troubleshooting * Preserve Morph idle width across empty activity updates * Fix dimming flicker, hide inactive music tab and consolidate Activities docs * Fix panel clearance across styles and match previews to theme settings * Prevent panel blur from repainting neighboring islands --------- Co-authored-by: Samuel Onoja <[email protected]>
18 KiB
Live Activities
Live Activities shows running commands and other tasks in your panel. A build can stay visible while you work in another window; click its activity to return to the terminal when Ferese can identify that window. The panel supplies the appearance, so tasks use your theme and animation settings.
Start using it
After installing with ./scripts/install.sh, open a new terminal and run a
command as usual:
cargo build
The installer detects Fish, Bash or Zsh, installs its shell hook, enables shell activities and adds an Activities item to your panel. A Cargo build appears once it has run for 1.5 seconds. A cached build that finishes sooner stays hidden, including its completion message.
These command rules are included:
| Command | Delay before appearing |
|---|---|
cargo build, check, test, run, clippy |
1.5 seconds |
npm or pnpm followed by install, build, test, run |
1.5 seconds |
make |
300 ms |
git push |
300 ms |
docker build |
1.5 seconds |
Rules match the command text at the start of the line. Commands such as
cargo +nightly build, npm ci, or env RUSTFLAGS=... cargo build need a custom
rule or an explicit wrapper. Commands that don't match a rule are discarded
without being logged.
To check the display without waiting for a build, run:
feresectl run --title "Activity check" -- sleep 5
This publishes directly and doesn't need a shell hook, but the panel still needs an Activities item. The check appears after 300 ms and finishes after five seconds.
Existing installations
From an updated Ferese checkout, rerun user setup as your normal user:
python3 scripts/installer/install.py user-setup
This needs the updated feresectl installed. Setup backs up changed config and
shell startup files. It preserves an explicit shell-hook #false setting and
an existing Activities item, including one you've hidden. After the first
successful setup, later installs update the hook files without restoring panel
items you've removed or changing your activity settings.
Open a new terminal to load the hook. In an existing Fish terminal, you can load it immediately with:
source ~/.config/fish/conf.d/ferese-activities.fish
The paths above use the default configuration directory. If you set
XDG_CONFIG_HOME, use that directory in place of ~/.config.
Add Activities to your panel
Open Settings → Panel & Shell → Edit panel, select a group in Arrange, and choose Add item → Activities. Keep its visibility enabled. This is also how to restore the item after removing it.
Activities can live in Start, Center or End. Regular panels use that position and open the activity list in a popup. Morph presents tasks inside its existing island and adds an Activities tab. Changing a group's position doesn't create another Morph island. See Panel configuration for item placement and overflow controls.
For manual panel configuration, add an activities item to an existing group.
This complete panel example places it at the end of a floating panel; don't add
a second panel block if your config already has one:
panel "main" {
style "floating"
end {
group "tasks" {
item "activities" kind="activities" priority=20
}
}
}
Manual shell setup
Without installer setup, hooks and process watching are off by default. Add an
Activities item to the panel and enable activities.sources.shell-hook before
loading a hook. From a checkout, source contrib/activities/ferese.fish in Fish,
contrib/activities/ferese.zsh in Zsh, or the following in Bash:
source contrib/activities/bash-preexec/bash-preexec.sh
source contrib/activities/ferese.bash
Use absolute paths when adding these lines to shell startup files. Zsh uses
add-zsh-hook, Fish uses named pre/postexec events, and Bash composes with
bash-preexec's hook arrays. Load
bash-preexec before the Bash hook; the hook does not replace an existing DEBUG
trap. Hook files never execute captured command text and preserve command status.
The installer copies hooks into $XDG_CONFIG_HOME/ferese/activities, defaulting
to ~/.config/ferese/activities. Fish loads through its conf.d directory; Bash
and Zsh get a marked block in .bashrc or .zshrc. Zsh setup honors an exported
ZDOTDIR. Bash shells started in login mode must also load .bashrc from their
login profile for the installed hook to run.
Process watching is an opt-in alternative when hooks are unavailable. It performs
bounded sampling on one worker, and disappearance means expiry, never inferred
success or failure. Shell hooks observe interactive commands; they do not
automatically wrap them or parse their output. The
Cargo adapter requires feresectl run.
Run a command explicitly
Use feresectl run for commands outside the built-in rules, unsupported shells,
or scripts where an interactive hook doesn't run:
feresectl run --title "Backup" -- ./backup.sh
feresectl run --title "Tests" -- npm test
Arguments after -- are passed to the command. It keeps its terminal input,
output, working directory, environment, terminal process group and exit/signal
status, and still runs if activity publishing fails. Completion follows the command's exit. A background descendant holding
stdout open does not keep the wrapper alive indefinitely.
Cargo progress
A normal cargo build shows that the command is running and whether it finishes
successfully. It doesn't report a percentage. To show the number of compilation
units completed, use the Cargo adapter:
feresectl run --cargo-json -- cargo build
The adapter reads Cargo's JSON output while keeping diagnostics readable in the
terminal. It reports completed units as text because Cargo doesn't supply a
reliable total for a percentage. Setting progress "cargo-json" in a rule enables
this adapter for matching feresectl run commands; it does not wrap plain
cargo build automatically. A build-finished message never completes the
activity; completion follows the actual child exit. The adapter also preserves
non-JSON output. See the
Cargo JSON contract.
Use the activity list
Morph shows up to two activities in its collapsed and peek states, with a +n
badge for additional tasks. Higher-priority tasks appear first, with temporary
boosts for new tasks and completion results. Hovering holds the current selection
in place while its values continue updating. Recording and low battery take
priority over ordinary activities.
Click the activity strip or open the Activities tab to see the list. Arrow keys select a row and Enter activates it. Selecting a linked task focuses its terminal and closes the list. If the terminal has closed, or one terminal process owns several possible windows, Ferese leaves the list open. It cannot select a particular tmux pane.
Tasks with reported progress show a percentage inside a ring. Tasks without a percentage show an animated arc around their icon. Reduced motion makes progress changes immediate and uses a static track. Activities do not automatically open the expanded panel.
A visible task's result stays for 1.5 seconds by default. Do not disturb limits ordinary running activities to one, hides the badge and suppresses result flashes. When there are no eligible tasks, the regular Activities item has no content and Morph returns to its other content.
Configure Activities
In Settings → Panel & Shell → Appearance, Visible activities chooses one
or two slots in Morph's collapsed and peek states. Show activity count controls
the +n badge; hiding it still lets you open the full list.
For source and timing settings, edit the top-level activities block in
~/.config/ferese/config.kdl. Merge these fields into an existing block rather
than adding a second one:
activities {
max-visible 2
show-badge #true
start-delay-ms 300
result-flash-ms 1500
sources {
shell-hook #true
process-watch #false
notification-bridge #false
}
}
| Setting | Effect |
|---|---|
max-visible |
One or two compact activity slots. |
show-badge |
Show +n for tasks beyond those slots. |
start-delay-ms |
Minimum delay for a new task; a rule can require a longer delay. |
result-flash-ms |
How long an eligible completion result remains visible. |
shell-hook |
Accept command start/end events from an installed shell hook. |
process-watch |
Opt-in process sampling when hooks aren't available; process disappearance removes the task without inferring success or failure. |
notification-bridge |
Present notifications as activities instead of duplicate toasts, respecting Do not disturb and notification popup settings. |
The process watcher and notification bridge stay off unless you enable them. Media comes from MPRIS; downloads and call statuses need an integration that publishes them. Microphone or camera use alone does not create a call activity.
Changes reload live. Invalid edits leave the last valid configuration in use;
check an edit with ferese --check-config ~/.config/ferese/config.kdl.
For command patterns, custom titles, per-rule delays and completion messages,
see Command rules.
Turn off automatic command detection
Set shell-hook #false inside activities.sources. Leave process-watch off
as well if you don't want process detection. You can still use feresectl run
and direct publishers.
To skip shell and Activities setup during installation, pass
./scripts/install.sh --no-activities. This skips setup for that installation;
it doesn't remove an existing hook or disable an already configured source.
Command rules
activities {
max-visible 2
show-badge #true
start-delay-ms 300
result-flash-ms 1500
sources {
shell-hook #true
process-watch #false
notification-bridge #false
}
rule "cargo" {
match #"^cargo (build|check|test|run|clippy)\b"#
title "cargo {1}"
icon "hammer"
priority 100
progress "indeterminate"
min-duration-ms 1500
ignore-parents "rust-analyzer"
dedupe-by "cwd"
flash-on-fail #true
result ok="Finished" fail="Command failed"
}
}
User rules run in declaration order, then unreplaced built-ins in Cargo,
npm/pnpm, make, git-push, docker-build order. A user rule replaces the entire
built-in with the same name. One command selects one rule, pinned for its lifetime.
ignore-parents accepts multiple names. Regex input/pattern/program sizes are
bounded. Command and cwd metadata are used only during matching; nonmatches are
discarded and never logged. Grouping hashes cwd within owner/rule. Invocations
retain independent lifetimes and progress is never averaged.
The global/rule visibility delay is their maximum. Completion before that delay,
including failure, never flashes. Eligible results last 1500 ms by default;
flash-on-fail #false removes failures directly. Configuration is validated
before application; an invalid reload preserves the last valid configuration.
Diagnostics include source offsets for activity configuration errors.
If nothing appears
-
Try the five-second check above. If it appears, the display and broker work; check shell setup and command matching next.
-
Check the panel item. In Arrange, confirm that Activities exists and is visible. On a regular panel, also check its overflow and available space.
-
Open a new terminal. Installing a hook doesn't load it into terminals that are already open. Confirm
shell-hook #truein your config too. -
Check the command and duration. Cargo and npm tasks must last at least 1.5 seconds under the built-in rules. A custom rule can increase that delay. Prefixes and different subcommands may not match the built-in patterns.
-
Inspect the broker while the task runs:
feresectl -j activity listAn empty
activitiesarray means no task is registered in that session. A registered task can still be waiting for its delay, ranked below another task, or hidden by panel settings. In Morph, also check for recording or a low-battery state taking priority. -
Check the session and build. A nested preview has its own broker; use the same session socket for publishing and listing. If
activityorrunis an unknown command, update the installed binaries. Log out and back in after upgrading the compositor and shell.
Shell hooks suppress publishing errors so they don't interrupt your commands. For an ownership or permission error, use a direct publication from the same terminal to see the response:
feresectl activity start diagnostic --title "Activity check" --lease-ms 10000
feresectl activity cancel diagnostic
The lease removes this diagnostic after ten seconds if you omit the cancel. Ownership verification needs Linux 6.5 or newer. See Publisher ownership and lifecycle for ownership, limits and expiry behavior.
Publish your own status
Run these commands from the same shell. The ID download belongs to that shell,
so another terminal cannot update it:
feresectl activity start download --source download --icon download \
--title "Downloading update" --progress 0.2
sleep 2
feresectl activity update download --progress 0.7
feresectl activity end download --result ok --message "Downloaded"
This example publishes status only; it doesn't perform a download. Your program supplies real progress and completion results.
Publisher ownership and lifecycle
Use the same socket selection as every other control command: --socket, then
FERESE_SOCKET, then the session runtime default. Separate nested sessions keep
separate brokers. One-shot commands use their verified immediate parent (normally
the shell), not the CLI connection, as lifetime owner. IDs are local to that owner.
A direct publisher and run use the publishing process itself. The host obtains
kernel peer credentials and a socket-bound pidfd, checks the parent relationship,
process birth and UID, and monitors owner exit. This requires Linux 6.5 or newer;
an unverifiable owner is rejected instead of trusting a JSON PID.
feresectl activity start build --icon hammer --title "Build"
feresectl activity update build --progress 0.6
feresectl activity end build --result ok --message "Built"
feresectl activity start tea --icon timer --title "Tea" --remaining-ms 180000
feresectl run --title "cargo test" -- cargo test
start prints a JSON handle containing owner, session and generation. The
--handle option on update/end/cancel checks that exact invocation. Omitting it
resolves the local ID only within the same verified owner. Duplicate starts are
rejected. Repeated identical accepted results keep the original result deadline;
a removed or superseded generation is stale. Register again after broker restart.
The compositor assigns a terminal window at activity creation using the publisher's process ancestry. List selection follows the activity ID across reordering. Recording and low battery keep their protected priority, including the combined recording/low-battery presentation.
Each owner may hold three records, including delayed and terminal entries. The session defaults to 128 records, a priority ceiling of 160 and two compact slots. New publications are limited to ten per owner per second. Replaceable updates are limited to 30 per owner per second; rejected updates get an explicit error. The bar coalesces snapshots through a bounded latest-value subscription while the broker retains accepted results. Terminal/cancel dispatch waits for bounded dispatcher capacity on the socket worker. A CLI disconnect does not remove an owner's records. Running owner death and expired leases remove entries without assigning a result. Results survive owner exit until their original deadline. Leases are positive and at most five minutes; valid refreshes renew only the lease.
Activities stay on their creation output, initially the focused output. On output
removal they move to the first surviving output, or become unpresented until an
output is available. Host timestamps use CLOCK_BOOTTIME, including suspend.
Countdown wire timestamps are ignored and replaced with host sample time.
Extensions and templates
The version-1 activity schema is carried inside the existing versioned,
length-prefixed JSON activity-publish command. activity-get and long-poll
activity-watch provide snapshots. See ferese_ipc::activities and
ferese_activities::Data; there is no second socket or JSON-lines protocol.
Extensions publish typed Progress, Timer, Media, or List data. The bar controls
rendering. Values are indeterminate, finite progress in [0,1], bounded text, or
countdown durations. Titles/text are limited to 256 UTF-8 bytes; lists to eight
rows. Icons are symbolic names; unknown names use the Ferese symbol, and paths
are rejected. No extension widgets, markup, colors, shaders or drawing programs
are accepted.
Use --template with a typed JSON template, e.g.
'{"kind":"list","data":{"rows":["Indexing files","Waiting for server"]}}'.
Capture/call integrations use --source capture and describe the state they
actually observe. Process names, microphone use, or camera use do not infer calls
or downloads. Existing MPRIS state supplies Media rows and transport controls;
recording/battery reuse the shell's existing protected state and watchers.
The optional notification bridge uses existing notification state, ranks below all other ordinary sources, and respects DND and popup privacy. When enabled, a notice becomes an activity rather than a duplicate toast. It is off by default.