/ opens a filter box under the guest table, and the table filters as you type.
The filter is a list of space-separated terms. A guest is shown only if it matches every term, and case is ignored:
a plain term matches part of the name, the VMID or a tag
is:running / is:stopped match the status
type:lxc / type:ct and type:vm / type:qemu match the guest type
Enter keeps the filter and returns focus to the table. Escape clears the filter, both from the box and from the table. The frame shows "· filter: <text> · N of M". Actions only ever see the visible rows, and the filter survives reloads and context switches.
Review fixes
Crash on markup: typing [/b] or [/] crashed the app. The filter text went into the border subtitle, which Textual parses as markup. The subtitle is now plain text, so [red] is also shown literally.
Escape on the table: it now clears a filter that was applied with Enter.
Missing values:guest_matches no longer fails when the status or type is None.
Verification
491 tests pass, including a hypothesis property: an empty query matches everything, and adding a term never widens the result.
ruff check and ruff format --check report no issues.
## What
`/` opens a filter box under the guest table, and the table filters as you type.
The filter is a list of space-separated terms. A guest is shown only if it matches every term, and case is ignored:
- a plain term matches part of the name, the VMID or a tag
- `is:running` / `is:stopped` match the status
- `type:lxc` / `type:ct` and `type:vm` / `type:qemu` match the guest type
Enter keeps the filter and returns focus to the table. Escape clears the filter, both from the box and from the table. The frame shows "· filter: <text> · N of M". Actions only ever see the visible rows, and the filter survives reloads and context switches.
## Review fixes
- **Crash on markup:** typing `[/b]` or `[/]` crashed the app. The filter text went into the border subtitle, which Textual parses as markup. The subtitle is now plain text, so `[red]` is also shown literally.
- **Escape on the table:** it now clears a filter that was applied with Enter.
- **Missing values:** `guest_matches` no longer fails when the status or type is `None`.
## Verification
- 491 tests pass, including a hypothesis property: an empty query matches everything, and adding a term never widens the result.
- `ruff check` and `ruff format --check` report no issues.
- `betterleaks` found no secrets.
- Read-only live check on mainframe:
| Filter | Result |
|---|---|
| `debian` | 104 |
| `type:vm` | 108 |
| `community-script is:running` | 14 of 19 |
| `is:stopped` | 0 of 19 |
This PR is stacked on #28 → #27.
Closes #16
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
At startup the app runs `cv4pve-cli --version`. If it differs from
cli.TESTED_VERSION (2.4.0), a warning says which version was found
and which one was tested. The app parses output formats that are not
a stable API: the config list text, prune-backups as a JSON string,
the CT ip-addresses JSON string and the exit codes with --wait. A
newer cv4pve-cli could break them in confusing ways.
If cv4pve-cli cannot be run at all, an error says so once, instead of
every later call failing without explanation. The README notes the
tested version.
Closes#14
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The README gets an "Install" section: install with uv tool from the
Gitea repo or from a local checkout, then upgrade and uninstall. The
"Run" section says to use `cv4pve-tui` when installed and
`uv run cv4pve-tui` from a checkout.
Verified by installing into throwaway tool dirs (UV_TOOL_DIR and
UV_TOOL_BIN_DIR under /tmp): `uv tool install .` gave a cv4pve-tui
binary. Started from /tmp in a pseudo-terminal, it drew the guest
frame and ran until it was stopped. The pyproject metadata (entry
point, readme, requires-python) was already enough.
Closes#17
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
/ opens a filter box under the guest table, and the table filters as
you type. Terms are separated by spaces, all must match, and case is
ignored:
- a plain term matches part of the name, the VMID or a tag
- is:running and is:stopped match the status
- type:lxc/ct and type:vm/qemu match the guest type
Enter keeps the filter and goes back to the table. Escape clears it,
from the box or from the table. The frame shows
"· filter: <text> · N of M". Actions only ever see the visible rows,
and the filter survives reloads and context switches.
Review fixes:
- Typing "[/b]" or "[/]" crashed the app, because the filter text went
into the border subtitle, which Textual parses as markup. The
subtitle is now plain text, so "[red]" is also shown literally.
- Escape on the table now clears a filter that was applied with Enter.
- guest_matches tolerates a None status or type.
Read-only live check on mainframe: "debian" gives 104, "type:vm" gives
108, "community-script is:running" gives 14 of 19, and "is:stopped"
gives 0 of 19.
Closes#16
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
What
/opens a filter box under the guest table, and the table filters as you type.The filter is a list of space-separated terms. A guest is shown only if it matches every term, and case is ignored:
is:running/is:stoppedmatch the statustype:lxc/type:ctandtype:vm/type:qemumatch the guest typeEnter keeps the filter and returns focus to the table. Escape clears the filter, both from the box and from the table. The frame shows "· filter: <text> · N of M". Actions only ever see the visible rows, and the filter survives reloads and context switches.
Review fixes
[/b]or[/]crashed the app. The filter text went into the border subtitle, which Textual parses as markup. The subtitle is now plain text, so[red]is also shown literally.guest_matchesno longer fails when the status or type isNone.Verification
ruff checkandruff format --checkreport no issues.betterleaksfound no secrets.debiantype:vmcommunity-script is:runningis:stoppedThis PR is stacked on #28 → #27.
Closes #16
Co-Authored-By: Claude Opus 5.5 noreply@anthropic.com