spacr.qt.ai.cli_install

Run a vendor command-line tool’s own installer, and say how it went.

Qt-free. spacr.qt.widgets.cli_setup_panel calls run_install() on a worker thread and shows what it reports; nothing here touches a widget.

THE COMMANDS ARE NOT HERE. Each tool’s install_methods in spacr.qt.ai.providers are the rows its install_hint is built from, and plan_install() picks the first of those rows whose programs are on PATH. The command the Install button runs and the command the screen shows are therefore one definition.

What a run reports is a kind (INSTALLED, NO_NETWORK, …) rather than a sentence, so the screen can say something the user can act on, in the user’s language, for each way an install goes wrong.

Classes

InstallOutcome

How one run of an installer ended.

InstallPlan

What pressing Install would run for one tool on this computer.

Functions

classify(→ str)

Name what went wrong with an installer that exited non-zero.

clean_line(→ str)

One line of installer output, decoded and without terminal codes.

launch_command(→ Union[List[str], str])

The command line that starts method's installer.

likely_folders(→ List[str])

Folders installers put a CLI in that may not be on PATH.

locate(→ str)

Find tool's CLI on PATH or in a folder installers use.

plan_install(→ InstallPlan)

Choose the row of tool's install methods that can run here.

put_on_path(→ bool)

Make the folder holding location part of this process's PATH.

quote_tail(→ str)

The installer's last lines, short enough for a message.

run_install(→ InstallOutcome)

Run plan's installer to the end and say how it went.

split_command(→ List[str])

Split a command as typed into a program and its arguments.

stop_process(→ None)

End an installer and everything it started.

Module Contents

class spacr.qt.ai.cli_install.InstallOutcome[source]

How one run of an installer ended.

Variables:
  • kind – one of the module’s kinds, such as INSTALLED.

  • exit_status – the installer’s exit status, or None when it did not run or was stopped before it exited on its own.

  • tail – the installer’s last output, quoted for a failure message.

  • location – where the CLI was found afterwards, or "".

property ok: bool[source]

Whether the tool is now installed and findable.

class spacr.qt.ai.cli_install.InstallPlan[source]

What pressing Install would run for one tool on this computer.

Variables:
  • tool – the tool, a spacr.qt.ai.providers.CommandLineTool.

  • method – the row that would run, or None when none of the tool’s rows can run here.

  • platform – the sys.platform value the plan was made for.

property automatic: bool[source]

Whether a row was found that spaCR can run.

property command: str[source]

the row that would run, else the hint.

Type:

The command to show

property needs: str[source]

The programs that would make an install possible, for a message.

Returns:

the first program each row needs, named for a reader and joined with “ or “, such as "npm (Node.js) or Homebrew".

spacr.qt.ai.cli_install.classify(exit_status: int, lines: Sequence[str], method: spacr.qt.ai.providers.InstallMethod) → str[source]

Name what went wrong with an installer that exited non-zero.

Parameters:
  • exit_status – its exit status.

  • lines – its last output lines.

  • method – the row that ran, whose command says whether a curl exit status can be read as curl’s.

Returns:

NO_NETWORK, REFUSED, PERMISSION or FAILED.

spacr.qt.ai.cli_install.clean_line(raw: bytes) → str[source]

One line of installer output, decoded and without terminal codes.

Parameters:

raw – the bytes between two line breaks.

Returns:

the text with colour codes and control characters removed and the ends stripped.

spacr.qt.ai.cli_install.launch_command(method: spacr.qt.ai.providers.InstallMethod, platform: str) → List[str] | str[source]

The command line that starts method’s installer.

Parameters:
  • method – the row to run.

  • platform – a sys.platform value.

Returns:

for "cmd" on Windows, the shown line itself as one string, which Windows hands to cmd unchanged; for "shell", bash -o pipefail -c and the command, so a failed download in curl ... | bash is a failed install rather than an empty script run successfully; otherwise the command split into a program, looked up on PATH, and its arguments (split_command()).

spacr.qt.ai.cli_install.likely_folders(platform: str | None = None) → List[str][source]

Folders installers put a CLI in that may not be on PATH.

A program started from a desktop icon often has a shorter PATH than a terminal, and Claude’s own installer puts claude in ~/.local/bin, which is exactly the folder such a PATH leaves out.

Parameters:

platform – a sys.platform value; the running one by default.

Returns:

candidate folders, most likely first, without duplicates.

spacr.qt.ai.cli_install.locate(tool: Any, platform: str | None = None) → str[source]

Find tool’s CLI on PATH or in a folder installers use.

Parameters:
Returns:

the executable’s path, or "" when it is nowhere.

spacr.qt.ai.cli_install.plan_install(tool: Any, platform: str | None = None) → InstallPlan[source]

Choose the row of tool’s install methods that can run here.

Parameters:
  • tool – a spacr.qt.ai.providers.CommandLineTool, or any object with the same attributes; one with no install_methods gets a plan with no method.

  • platform – a sys.platform value; the running one by default.

Returns:

the plan, whose method is the first row whose needs are all on PATH, or None when there is no such row.

spacr.qt.ai.cli_install.put_on_path(location: str) → bool[source]

Make the folder holding location part of this process’s PATH.

So a CLI installed into a folder the desktop’s PATH leaves out works in spaCR at once, without a restart. Changes this process’s environment, so call it on the GUI thread.

Parameters:

location – the path of an executable, from locate().

Returns:

True when PATH was changed.

spacr.qt.ai.cli_install.quote_tail(lines: Sequence[str]) → str[source]

The installer’s last lines, short enough for a message.

Parameters:

lines – its output lines, oldest first.

Returns:

the last QUOTED_LINES joined by a space and cut to QUOTED_CHARS.

spacr.qt.ai.cli_install.run_install(plan: InstallPlan, on_output: Callable[[str], None] | None = None, stop: threading.Event | None = None, *, timeout_s: float = INSTALL_TIMEOUT_S) → InstallOutcome[source]

Run plan’s installer to the end and say how it went.

Blocks until the installer exits, so run it off the GUI thread. The installer gets no input – a prompt reads end-of-file rather than waiting forever – and runs in a scratch folder that is removed afterwards, because the Windows command downloads install.cmd into the folder it runs in.

Parameters:
  • plan – from plan_install().

  • on_output – called with each non-blank line of output, on the calling thread, as it arrives.

  • stop – set it to stop the installer.

  • timeout_s – seconds after which the installer is stopped as hung.

Returns:

the outcome; INSTALLED only when the CLI is found afterwards, with location saying where. An installer that exited 0 as Cancel or the time limit reached it is INSTALLED when the CLI is there, because the install finished; otherwise it is CANCELLED or TIMED_OUT.

spacr.qt.ai.cli_install.split_command(command: str, platform: str) → List[str][source]

Split a command as typed into a program and its arguments.

Parameters:
Returns:

the words. On Windows a backslash is part of a path, not an escape, and a double-quoted word loses its quotes.

spacr.qt.ai.cli_install.stop_process(proc: Any, platform: str) → None[source]

End an installer and everything it started.

On POSIX the installer’s group is signalled even when the installer itself has already exited: a program it started can still hold its output open, and the install does not end until that program does. The installer’s own process is left alone once it has exited.

Parameters:
  • proc – the installer, running or exited.

  • platform – a sys.platform value.