@jals1212/pi-spaces-cli 0.7.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +79 -0
- package/README.md +116 -87
- package/dist/cli.js +431 -309
- package/dist/picker.js +102 -18
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,85 @@ commands and options and a patch version fixes.
|
|
|
6
6
|
|
|
7
7
|
## Unreleased
|
|
8
8
|
|
|
9
|
+
## 0.8.0
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
|
|
13
|
+
- **Breaking:** every space is named `<profile>/<name>`, `base` included
|
|
14
|
+
(`pi-space pi/work`, `pi-space new my/work`, `pi-space rename pi/work client`,
|
|
15
|
+
`pi-space update pi/base`): launch, `new`, `setup`, `rename`, `remove`,
|
|
16
|
+
`list`, `update`, `install` and `uninstall`. A bare name exits 2 and names
|
|
17
|
+
the form: `pi-space: Name the space with its profile, as <profile>/work
|
|
18
|
+
(profiles: my, pi).` `rename` takes the new name bare or with the same
|
|
19
|
+
profile; a space never changes profile.
|
|
20
|
+
- **Breaking:** `--profile` is removed, replaced by the profile in the name:
|
|
21
|
+
`pi-space: --profile was replaced by: pi-space <profile>/<name>` (exit 2).
|
|
22
|
+
`--command`, `--dir`, `--setup` and `--config` stay, and `--command`,
|
|
23
|
+
`--dir` and `--setup` now override the named profile for one call.
|
|
24
|
+
- **Breaking:** the config file's `default` is ignored, with a warning on
|
|
25
|
+
stderr (the file still works, `spaceEnv` included): `pi-space: <file>:
|
|
26
|
+
"default" is no longer used; name each space with its profile
|
|
27
|
+
(<profile>/<name>) and remove "default" from the file.`
|
|
28
|
+
- **Breaking:** `PI_SPACES_COMMAND`, `PI_SPACES_DIR` and `PI_SPACES_SETUP` are
|
|
29
|
+
no longer read as settings. They are what `pi-space` hands to the Pi it
|
|
30
|
+
starts (the profile's command, spaces folder and setup, or the call
|
|
31
|
+
options; unset when there is none, so a caller's value never leaks), and
|
|
32
|
+
what the extension reads. `PI_SPACES_CONFIG` is still read.
|
|
33
|
+
- **Breaking:** `pi-space list` alone lists every profile with its base and
|
|
34
|
+
spaces, grouped, as `profile/space`.
|
|
35
|
+
- **Breaking:** `--every` is two targets: `<profile>/--every` runs in that
|
|
36
|
+
profile's base and spaces (for `setup`, only its spaces), and `--every`
|
|
37
|
+
alone runs in every profile (`setup --every` skips profiles with no setup
|
|
38
|
+
command). Each run's header and the failure list use `profile/space`.
|
|
39
|
+
- **Breaking:** `--command` and `--dir` with something that spans profiles
|
|
40
|
+
(the picker, `list` alone, `--every` alone) exit 2: `pi-space: --command and
|
|
41
|
+
--dir apply to one profile; name it: <profile>/<name> or <profile>/--every.`
|
|
42
|
+
`--setup` applies to each profile.
|
|
43
|
+
- The picker lists the spaces of every profile as `<profile>/<name>` (with a
|
|
44
|
+
group header when there is more than one profile), and a profile that shares
|
|
45
|
+
a folder with another is listed too, each with its own command.
|
|
46
|
+
- Completion lists `<profile>/<name>` for every profile after `pi-space` and
|
|
47
|
+
after a command, plus `--every` and `<profile>/--every` where a target goes,
|
|
48
|
+
so `pi-space <TAB>` shows what the picker does. `--profile` is no longer
|
|
49
|
+
completed; `--config` makes it read that file and `--dir` lists that folder's
|
|
50
|
+
spaces under each profile's prefix.
|
|
51
|
+
- The README and the help describe the new names. The advice to export
|
|
52
|
+
`PI_SPACES_COMMAND` and `PI_SPACES_DIR` is gone: a profile in the config
|
|
53
|
+
file names the program instead.
|
|
54
|
+
|
|
55
|
+
### Fixed
|
|
56
|
+
|
|
57
|
+
- The Pi that `pi-space` starts now runs in the named profile's home even when
|
|
58
|
+
you run `pi-space` from the shell of another Pi: `pi-space pi/base` inside a
|
|
59
|
+
gentle-shell Pi used to start Pi in the gentle home, and `pi-space pi/work`
|
|
60
|
+
looked for the space relative to it. The started Pi gets
|
|
61
|
+
`PI_CODING_AGENT_DIR` set to the profile's home, and when you run it from
|
|
62
|
+
inside a space, that space is unwound first (its `spaceEnv` values go back to
|
|
63
|
+
the base values, paths inside its folder move to the base home, and
|
|
64
|
+
`PI_SPACE`, `PI_SPACE_HOME`, `PI_SPACES_BASE_HOME` and `PI_SPACES_BASE_ENV`
|
|
65
|
+
are removed). The setup command is built on the same unwound base.
|
|
66
|
+
|
|
67
|
+
## 0.7.1
|
|
68
|
+
|
|
69
|
+
### Fixed
|
|
70
|
+
|
|
71
|
+
- A bare `pi-space` with `--setup`: a space of another profile now starts with
|
|
72
|
+
that `--setup` (as `PI_SPACES_SETUP`), as the spaces of the current profile
|
|
73
|
+
already did.
|
|
74
|
+
- A failure starting a space of another profile (a command with an unclosed
|
|
75
|
+
quote, a program that cannot start) is reported with the profile's command
|
|
76
|
+
and exits 2 or 1, with a test for each.
|
|
77
|
+
- The picker puts the terminal back (raw mode off, cursor shown, picker
|
|
78
|
+
erased) on SIGTERM, SIGHUP and SIGINT, then ends the process with that
|
|
79
|
+
signal, instead of leaving the terminal raw.
|
|
80
|
+
- An escape sequence a terminal splits after its start (`ESC [`, `ESC O`, or
|
|
81
|
+
`ESC [` with parameters) is joined with its rest instead of being read as Esc
|
|
82
|
+
and text. If the rest never comes, a lone Esc still cancels and any other
|
|
83
|
+
half sequence is ignored.
|
|
84
|
+
- Lines with wide characters (Chinese, Japanese, Korean, fullwidth, emoji)
|
|
85
|
+
are cut by the columns they take, so they no longer wrap and break the
|
|
86
|
+
redraw; combining marks take none.
|
|
87
|
+
|
|
9
88
|
## 0.7.0
|
|
10
89
|
|
|
11
90
|
### Changed
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# pi-space
|
|
2
2
|
|
|
3
|
-
The `pi-space` command: pick a [Pi](https://pi.dev) space and start Pi in it, create, set up, rename and remove spaces, and install, update and list the packages of a space, from your shell.
|
|
3
|
+
The `pi-space` command: pick a [Pi](https://pi.dev) space and start Pi in it, create, set up, rename and remove spaces, and install, update and list the packages of a space, from your shell. Every space is named `<profile>/<name>`: a [profile](#profiles) of a config file says which program to run and where its spaces live, so one short command is enough for each program, and [shell completion](#shell-completion) completes the commands and the spaces of every profile. It is the optional companion of the Pi extension [`@jals1212/pi-spaces`](https://github.com/jals1212/pi-spaces#readme), which holds the spaces themselves.
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
@@ -8,118 +8,149 @@ The `pi-space` command: pick a [Pi](https://pi.dev) space and start Pi in it, cr
|
|
|
8
8
|
npm install -g @jals1212/pi-spaces-cli
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
Node 20 or later. The Pi extension `@jals1212/pi-spaces` must be installed in the home the command opens: `pi-space` only runs `pi --space <name> [command]`, and the extension does the switch. For the package commands (`list <name>`, `update`, `install`, `uninstall`) the extension in the base home must be **0.4.0 or later**: an older one starts Pi in the space instead of running the command.
|
|
11
|
+
Node 20 or later. The Pi extension `@jals1212/pi-spaces` must be installed in the home the command opens: `pi-space` only runs `pi --space <name> [command]`, and the extension does the switch. For the package commands (`list <profile>/<name>`, `update`, `install`, `uninstall`) the extension in the base home must be **0.4.0 or later**: an older one starts Pi in the space instead of running the command.
|
|
12
|
+
|
|
13
|
+
## Naming a space
|
|
14
|
+
|
|
15
|
+
Every space the command takes is `<profile>/<name>`, `base` included: `pi/work`, `pi/base`, `my/work`. The profile is the first word, up to the first `/`; it names an entry of the [config file](#profiles), and `pi` is always there (plain Pi). The name is the space as `/space` knows it, and `<profile>/base` is the home that profile's Pi starts with.
|
|
16
|
+
|
|
17
|
+
A bare name is refused, with the forms to use, and nothing is started:
|
|
18
|
+
|
|
19
|
+
```text
|
|
20
|
+
$ pi-space work
|
|
21
|
+
pi-space: Name the space with its profile, as <profile>/work (profiles: my, pi).
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
The exit status is 2. There is no default profile: the file's `default` is not used (see [Profiles](#profiles)).
|
|
12
25
|
|
|
13
26
|
## Commands
|
|
14
27
|
|
|
15
|
-
The command words are reserved: a space can never be named `list`, `new`, `remove`, `rename`, `switch`, `update`, `install`, `uninstall`, `setup` or `completion`, so any other first word is a space name
|
|
28
|
+
The command words are reserved: a space can never be named `list`, `new`, `remove`, `rename`, `switch`, `update`, `install`, `uninstall`, `setup` or `completion`, so any other first word is a space (`<profile>/<name>`; the reservation of `completion` is in `@jals1212/pi-spaces` 0.6.0).
|
|
16
29
|
|
|
17
30
|
| Command | What it does |
|
|
18
31
|
| --- | --- |
|
|
19
|
-
| `pi-space` | Opens a picker of the spaces and starts Pi in the one you choose: ↑/↓ (or Ctrl-P/Ctrl-N, Tab) move, Enter starts Pi, Esc cancels, typing filters by
|
|
20
|
-
| `pi-space <name> [pi args...]` | Starts Pi in that space (
|
|
21
|
-
| `pi-space list` | Lists the spaces
|
|
22
|
-
| `pi-space list <name
|
|
23
|
-
| `pi-space
|
|
24
|
-
| `pi-space
|
|
25
|
-
| `pi-space
|
|
26
|
-
| `pi-space
|
|
27
|
-
| `pi-space
|
|
28
|
-
| `pi-space
|
|
29
|
-
| `pi-space
|
|
32
|
+
| `pi-space` | Opens a picker of the spaces of every profile and starts Pi in the one you choose: ↑/↓ (or Ctrl-P/Ctrl-N, Tab) move, Enter starts Pi, Esc cancels, typing filters by `profile/name`. Each profile's `<profile>/base` comes first in its group (with more than one profile, a header names the group), and the cursor starts on the space this Pi runs in, marked `(active)`. The space starts with the profile it was listed under. Profiles that share a folder are all listed: each one means a different command. |
|
|
33
|
+
| `pi-space <profile>/<name> [pi args...]` | Starts Pi in that space, with that profile's command (`<profile>/base` for the home that profile's Pi starts with). |
|
|
34
|
+
| `pi-space list` | Lists the spaces of every profile, grouped by profile: each profile's folder, then its `base` and spaces as `profile/space`. |
|
|
35
|
+
| `pi-space list <profile>/<name>` | Lists the packages of a space (Pi's `list`). |
|
|
36
|
+
| `pi-space list <profile>/--every` or `--every` | The packages of a profile's base and spaces, or of every profile's (see below). |
|
|
37
|
+
| `pi-space new <profile>/<name>` | Creates an empty space in that profile's folder, as `/space new <name>` does in Pi, then runs the profile's setup command in it when there is one (see [Preparing a new space](#preparing-a-new-space)). It does not start Pi. |
|
|
38
|
+
| `pi-space setup <profile>/<name>` | Runs the setup command in a space. Never in `base`. |
|
|
39
|
+
| `pi-space setup <profile>/--every` or `--every` | Runs it in every space of the profile, or of every profile that has a setup command. |
|
|
40
|
+
| `pi-space rename <profile>/<old> <new>` | Renames a space, as `/space rename` does in Pi. The new name is bare or keeps the profile (`pi/work client`, `pi/work pi/client`); a space never changes profile. It refuses what `remove` refuses (see below). |
|
|
41
|
+
| `pi-space remove <profile>/<name> [--yes] [--no-backup]` | Deletes a space, as `/space remove <name>` does in Pi. It asks first (`[y/N]`), then whether to keep a backup in `<spaces folder>/.backups` (`[Y/n]`: Enter keeps one). `--yes` skips the questions and keeps a backup, and is required without a terminal; `--no-backup` deletes without one. |
|
|
42
|
+
| `pi-space update <profile>/<name>` | Runs Pi's `update` in a space; `<profile>/--every` and `--every` run it in many (see below). What follows is Pi's: `--extensions`, `--all`, a source. With nothing after the space it is Pi's default. |
|
|
43
|
+
| `pi-space install <profile>/<name> <source> [pi install options...]` | Runs Pi's `install` in a space (or `<profile>/--every`, `--every`). The source is required. |
|
|
44
|
+
| `pi-space uninstall <profile>/<name> <source> [pi options...]` | Runs Pi's `uninstall` (its alias of `remove`) in a space (or `<profile>/--every`, `--every`). The source is required. |
|
|
30
45
|
| `pi-space completion zsh` | Prints the zsh completion script (see [Shell completion](#shell-completion)). Any other shell, or none, exits with status 2. |
|
|
31
46
|
| `pi-space <command> --help` | Shows the help of one command: what it does, its arguments and options, the call options that apply, and examples (`pi-space --help <command>` and `-h` work too). |
|
|
32
47
|
| `pi-space --help` | Shows the usage. |
|
|
33
48
|
| `pi-space --version` | Prints the version. |
|
|
34
49
|
|
|
35
|
-
`--help` (or `-h`) anywhere after a command word shows that command's help and does nothing else: `pi-space remove work --help` removes nothing, and it reads no config file. After a space
|
|
50
|
+
`--help` (or `-h`) anywhere after a command word shows that command's help and does nothing else: `pi-space remove pi/work --help` removes nothing, and it reads no config file. After a space every argument belongs to Pi, so `pi-space pi/work --help` starts Pi with `--help`. An unknown command (`pi-space --help ghost`) exits with status 2 and lists the commands.
|
|
36
51
|
|
|
37
|
-
`--new
|
|
52
|
+
`--new`, `--remove` (the options of 0.3) and `--profile` (0.6 and later) were replaced; they exit with status 2 and name what to use: `pi-space: --profile was replaced by: pi-space <profile>/<name>`. The profile is now the first word of the space instead of an option before the command.
|
|
38
53
|
|
|
39
|
-
### Packages in a space, or in
|
|
54
|
+
### Packages in a space, or in many
|
|
40
55
|
|
|
41
56
|
```sh
|
|
42
|
-
pi-space list work
|
|
43
|
-
pi-space install work npm:some-package
|
|
44
|
-
pi-space update base --extensions
|
|
45
|
-
pi-space update
|
|
57
|
+
pi-space list pi/work # the packages of "work", in plain Pi
|
|
58
|
+
pi-space install my/work npm:some-package # install in "work" of the profile "my" only
|
|
59
|
+
pi-space update pi/base --extensions # update the extensions of plain Pi's base home
|
|
60
|
+
pi-space update my/--every # my's base, then every space of "my"
|
|
61
|
+
pi-space update --every # every profile: its base, then its spaces
|
|
46
62
|
```
|
|
47
63
|
|
|
48
|
-
A package command runs `pi --space <name> <command> [args...]` with Pi's stdio, through
|
|
64
|
+
A package command runs `pi --space <name> <command> [args...]` with Pi's stdio, through the profile's command (or `--command`), and ends with the exit status of that Pi. The extension relaunches Pi in the space's home, so the command works on that home's `settings.json` and packages; the Pi starts with the profile's home as `PI_CODING_AGENT_DIR` (see "What the started Pi is told"). `<profile>/<name>` is `<profile>/base` or an existing space of that profile; anything else exits with status 1 before Pi starts.
|
|
65
|
+
|
|
66
|
+
`--every` takes the place of the space, and there are two:
|
|
49
67
|
|
|
50
|
-
|
|
68
|
+
- `<profile>/--every` runs in that profile's `base` first, then in every one of its spaces in order.
|
|
69
|
+
- `--every` alone runs in every profile, in the order of the profiles (the file's, then `pi` unless the file defines it), each in the order above.
|
|
51
70
|
|
|
52
|
-
|
|
71
|
+
The runs go one after the other, each after a `== <profile>/<name>` line on stdout. A failure does not stop the rest. The exit status is 0 if every run succeeded, otherwise 1, and the last line on stderr names the spaces that failed: `pi-space: update failed in: my/base, my/work`.
|
|
53
72
|
|
|
54
|
-
|
|
73
|
+
A new space gets a `settings.json` that declares the extension, so `/space` works inside it: the same declaration as in the base home's `settings.json` (the profile's `home`; for `pi` that is `PI_SPACES_BASE_HOME`, else `PI_CODING_AGENT_DIR`, else `~/.pi/agent`), or `npm:@jals1212/pi-spaces` when the base home does not declare it. A local path counts when it is a copy of the extension: a folder whose `package.json` is named `@jals1212/pi-spaces`.
|
|
74
|
+
|
|
75
|
+
`remove` and `rename` refuse `base`, the space you are in, a space that holds the base home, and anything that is not a real folder inside the spaces folder, before they ask. A backup is the whole space folder, moved to `.backups/<name>-<UTC time>`; move it back to restore it. See [what it leaves on your machine](https://github.com/jals1212/pi-spaces#what-it-leaves-on-your-machine).
|
|
55
76
|
|
|
56
77
|
## Another program that runs Pi
|
|
57
78
|
|
|
58
|
-
To start Pi through another program for one call, give `--command` and `--dir` before the rest
|
|
79
|
+
The usual way is a [profile](#profiles) that holds the program's `command`, `dir` and `setup`: `pi-space my/work`. To start Pi through another program for one call without a profile, give `--command` and `--dir` before the rest, with the profile they override (`pi` is always there); the words of `--command` come before `--space`. The words are split on spaces; double or single quotes keep a path with spaces in one word. Such a program usually has its own home, so `--dir` points at its spaces folder, and the Pi it starts gets that folder as `PI_SPACES_DIR` too. Nothing is exported, so a plain `pi` in the same shell is not affected. Every command accepts these options and uses the ones it needs (`list <space>` ignores `--setup`, `rename` ignores `--command` and `--setup`), so one alias can give them all:
|
|
59
80
|
|
|
60
81
|
```sh
|
|
61
|
-
pi-space --command "my-launcher --" --dir ~/.my-launcher/spaces work # → my-launcher -- --space work
|
|
62
|
-
pi-space --dir ~/.my-launcher/spaces new work
|
|
63
|
-
pi-space --command '"/opt/my launcher/run" --' work
|
|
82
|
+
pi-space --command "my-launcher --" --dir ~/.my-launcher/spaces pi/work # → my-launcher -- --space work
|
|
83
|
+
pi-space --dir ~/.my-launcher/spaces new pi/work # create one in that folder
|
|
84
|
+
pi-space --command '"/opt/my launcher/run" --' pi/work # a path with spaces, in quotes
|
|
64
85
|
```
|
|
65
86
|
|
|
66
87
|
Inside quotes a backslash is a plain character, so `"C:\Program Files\my-launcher\run.cmd"` works as written. A quote that is never closed is an error (exit status 2), and nothing is started.
|
|
67
88
|
|
|
68
|
-
|
|
89
|
+
`--command`, `--dir` and `--setup` override the profile you name, for that one call: they belong to one profile. So they cannot go with something that spans profiles (the picker, `list` alone, or a global `--every`); that exits with status 2 and nothing runs:
|
|
69
90
|
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
export PI_SPACES_DIR=~/.my-launcher/spaces # the spaces next to that program's home
|
|
91
|
+
```text
|
|
92
|
+
pi-space: --command and --dir apply to one profile; name it: <profile>/<name> or <profile>/--every.
|
|
73
93
|
```
|
|
74
94
|
|
|
95
|
+
`--setup` is the exception: it applies to each profile a global `--every` or `setup --every` runs in.
|
|
96
|
+
|
|
97
|
+
A call has no other settings. `pi-space` does **not** read `PI_SPACES_COMMAND`, `PI_SPACES_DIR` or `PI_SPACES_SETUP` from your shell: the command, the spaces folder and the setup command come from the profile, or from the call options above. A shell that still exports them is harmless to `pi-space` but changes nothing in it. They are what `pi-space` hands to the Pi it starts, and what the extension reads there:
|
|
98
|
+
|
|
75
99
|
| Variable | Meaning |
|
|
76
100
|
| --- | --- |
|
|
77
|
-
| `PI_SPACES_COMMAND` |
|
|
78
|
-
| `PI_SPACES_DIR` |
|
|
79
|
-
| `PI_SPACES_SETUP` |
|
|
80
|
-
| `PI_SPACES_CONFIG` | The [config file](#profiles) with the profiles. A leading `~` is your home folder and a relative value is taken from it. Default: `~/.pi-spaces/config.json`. `--config` wins for one call; a relative `--config` is taken from the current folder. |
|
|
81
|
-
| `PI_CODING_AGENT_DIR` | Pi's agent home; its parent holds the default spaces folder. Default: `~/.pi/agent`. |
|
|
101
|
+
| `PI_SPACES_COMMAND` | For the started Pi, the profile's command (or `--command`); unset when there is none, so a caller's value never leaks. The extension reads it to tell the model and the tools how Pi was started. |
|
|
102
|
+
| `PI_SPACES_DIR` | For the started Pi, the profile's spaces folder (or `--dir`), always. The extension reads it as its spaces folder. |
|
|
103
|
+
| `PI_SPACES_SETUP` | For the started Pi, the profile's setup command (or `--setup`); unset when there is none. `/space new` there names `pi-space setup <profile>/<name>` when it is set. |
|
|
104
|
+
| `PI_SPACES_CONFIG` | The [config file](#profiles) with the profiles. A leading `~` is your home folder and a relative value is taken from it. Default: `~/.pi-spaces/config.json`. `--config` wins for one call; a relative `--config` is taken from the current folder. This one `pi-space` still reads. |
|
|
105
|
+
| `PI_CODING_AGENT_DIR` | Pi's agent home; the built-in `pi` profile's `home` (its parent holds the default spaces folder). Default: `~/.pi/agent`. |
|
|
82
106
|
|
|
83
107
|
## Profiles
|
|
84
108
|
|
|
85
|
-
Profiles are named in an optional JSON config file, so you do not have to repeat `--command`, `--dir` and `--setup`, or write shell variables and functions, for each program that runs Pi. This section is the command's side of it; the file format (every key, the schema version, `spaceEnv`, what happens when the file is wrong) is in the [main README](https://github.com/jals1212/pi-spaces#profiles).
|
|
109
|
+
Profiles are named in an optional JSON config file: each says which program to run, its home, where its spaces live and how to set one up, so you do not have to repeat `--command`, `--dir` and `--setup`, or write shell variables and functions, for each program that runs Pi. The profile is the first word of every space you name. This section is the command's side of it; the file format (every key, the schema version, `spaceEnv`, what happens when the file is wrong) is in the [main README](https://github.com/jals1212/pi-spaces#profiles).
|
|
86
110
|
|
|
87
111
|
```sh
|
|
88
|
-
pi-space
|
|
89
|
-
pi-space
|
|
90
|
-
pi-space
|
|
91
|
-
pi-space --config ./other.json
|
|
112
|
+
pi-space list # every profile with its base and spaces
|
|
113
|
+
pi-space ml/work # start the profile's program in its space "work"
|
|
114
|
+
pi-space new ml/work # create it, then run the profile's setup in it
|
|
115
|
+
pi-space --config ./other.json ml/work # the same profile from another file, for this call
|
|
92
116
|
```
|
|
93
117
|
|
|
94
|
-
`--
|
|
118
|
+
`--config <path>` comes before the command, like `--command`, `--dir` and `--setup`: each needs a value (not blank) and may be given once, and after a space they belong to Pi. An unknown profile exits with status 2 and lists the known ones: `pi-space: Unknown profile "ghost"; known profiles: ml, pi.`
|
|
95
119
|
|
|
96
|
-
- **The file** is `--config`, else `PI_SPACES_CONFIG`, else `~/.pi-spaces/config.json`. A missing file is not an error: with no file the
|
|
97
|
-
- **`default
|
|
98
|
-
|
|
120
|
+
- **The file** is `--config`, else `PI_SPACES_CONFIG`, else `~/.pi-spaces/config.json`. A missing file is not an error: with no file the only profile is `pi`. A file that is wrong exits with status 2 and prints its message (`pi-space: <file>: <problem>`), never a stack. `--help`, `--version` and `completion` never read it.
|
|
121
|
+
- **`default`** is ignored. The file is still valid with it (the schema accepts it, and `spaceEnv` and the rest work), but `pi-space` names every space with its profile and never falls back to one. Each call that reads such a file says so on stderr, then goes on:
|
|
122
|
+
|
|
123
|
+
```text
|
|
124
|
+
pi-space: ~/.pi-spaces/config.json: "default" is no longer used; name each space with its profile (<profile>/<name>) and remove "default" from the file.
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Remove the key to silence it.
|
|
128
|
+
- **`pi`** is built in: command `pi`, home `PI_CODING_AGENT_DIR` (else `~/.pi/agent`), unless another profile of the file names that home: then `~/.pi/agent`, so `pi/` means plain Pi even from inside another program's Pi. It always exists, so `pi/work` is plain Pi from the same shell, and a `pi` in the file's `profiles` replaces it. `--profile`, which used to pick a profile, is gone: the profile is the first word of the space.
|
|
99
129
|
|
|
100
130
|
### Which value wins
|
|
101
131
|
|
|
102
132
|
For each of the command, the spaces folder and the setup command, the first of these that has a value is used:
|
|
103
133
|
|
|
104
|
-
1. the call option (`--command`, `--dir`, `--setup`);
|
|
105
|
-
2.
|
|
106
|
-
3. the
|
|
107
|
-
4. the file's `default` profile;
|
|
108
|
-
5. the built-in: `pi`, the `spaces` folder next to the base home, no setup command.
|
|
134
|
+
1. the call option (`--command`, `--dir`, `--setup`), which overrides the profile you named;
|
|
135
|
+
2. that profile's own `command`, `dir` or `setup`;
|
|
136
|
+
3. the built-in: `pi`, the `spaces` folder next to the profile's `home`, no setup command.
|
|
109
137
|
|
|
110
|
-
A profile's spaces folder is its `dir`, which is `spaces` next to its `home` when it leaves `dir` out. A profile's `home` is also the base home a new space's `settings.json` takes the extension's declaration from
|
|
138
|
+
`PI_SPACES_COMMAND`, `PI_SPACES_DIR` and `PI_SPACES_SETUP` are not on the list: `pi-space` does not read them (see above). A profile never borrows from another. A profile's spaces folder is its `dir`, which is `spaces` next to its `home` when it leaves `dir` out. A profile's `home` is also the base home a new space's `settings.json` takes the extension's declaration from, and `remove` and `rename` refuse the space that holds it.
|
|
111
139
|
|
|
112
140
|
### What the started Pi is told
|
|
113
141
|
|
|
114
142
|
The Pi that `pi-space` starts (a space, or a package command) reads the same file and the same folders, so `pi-space` hands over what it settled, as environment variables for that child only:
|
|
115
143
|
|
|
116
|
-
-
|
|
117
|
-
-
|
|
118
|
-
-
|
|
144
|
+
- `PI_SPACES_DIR` is always the profile's spaces folder (or `--dir`), absolute.
|
|
145
|
+
- `PI_SPACES_COMMAND` and `PI_SPACES_SETUP` are the profile's command and setup (or `--command` and `--setup`); a profile without one leaves the variable unset, even if your shell has it.
|
|
146
|
+
- `--config <path>` becomes `PI_SPACES_CONFIG` (absolute).
|
|
147
|
+
- `PI_CODING_AGENT_DIR` is the profile's `home`, so the started Pi runs as if you had started it from a plain terminal for that profile, even when you run `pi-space` from the shell of another Pi (a gentle-shell Pi, say): `pi-space pi/base` starts plain Pi in `~/.pi/agent`, not in the home of the Pi you are in.
|
|
148
|
+
- Run from inside a space, `pi-space` first unwinds that space: the caller profile's `spaceEnv` variables get back their base values (from `PI_SPACES_BASE_ENV`, or are removed when it has none), every variable that is the space's folder or a path inside it (each entry of a list on its own) moves to the base home, and `PI_SPACE`, `PI_SPACE_HOME`, `PI_SPACES_BASE_HOME` and `PI_SPACES_BASE_ENV` are removed. The extension then enters the named space from a clean base. `remove` and `rename` still refuse the space you are in.
|
|
149
|
+
- Nothing else is added or removed. `--command` and the rest are never read back from them.
|
|
119
150
|
|
|
120
151
|
### `spaceEnv` and the setup command
|
|
121
152
|
|
|
122
|
-
|
|
153
|
+
A space always belongs to a profile, so that profile's `spaceEnv` is added to the environment of the setup command, with `{home}` and `{name}` filled in for the space being set up, next to `PI_CODING_AGENT_DIR`, `PI_SPACE` and `PI_SPACE_HOME`; the rest of its environment is the same unwound base as for Pi, so the space you run `pi-space` from never leaks into it. It applies whichever setup command runs: the profile's own `setup`, or one from `--setup`, because the space is that profile's.
|
|
123
154
|
|
|
124
155
|
### A complete example
|
|
125
156
|
|
|
@@ -142,73 +173,71 @@ A program called `my-launcher` keeps its agent home in `~/.my-launcher/agent` an
|
|
|
142
173
|
Then, without a variable, an alias or a function:
|
|
143
174
|
|
|
144
175
|
```sh
|
|
145
|
-
pi-space
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
pi-space
|
|
149
|
-
pi-space
|
|
150
|
-
pi-space
|
|
176
|
+
pi-space new my/work # creates ~/.my-launcher/spaces/work, then runs:
|
|
177
|
+
# my-launcher --home ~/.my-launcher/spaces/work setup
|
|
178
|
+
# with MY_LAUNCHER_CONFIG_HOME=~/.my-launcher/spaces/work/config
|
|
179
|
+
pi-space my/work -c # my-launcher -- --space work -c
|
|
180
|
+
pi-space setup my/--every # run the setup again in every space of "my"
|
|
181
|
+
pi-space list # my and pi, each with its base and spaces
|
|
182
|
+
pi-space pi/work # a space of plain Pi, from the same shell
|
|
151
183
|
```
|
|
152
184
|
|
|
153
|
-
Add `"default": "my"` to the file and `pi-space work` alone does the second line; `pi-space --profile pi work` is then plain Pi.
|
|
154
|
-
|
|
155
185
|
### Shortening it (optional)
|
|
156
186
|
|
|
157
|
-
The command needs no help, but a shell
|
|
187
|
+
The command needs no help, but a shell alias or abbreviation can shorten a space you open often to one word. It is only sugar: no logic lives in it, and the profile stays in the config file.
|
|
158
188
|
|
|
159
189
|
```sh
|
|
160
|
-
|
|
161
|
-
|
|
190
|
+
alias myw='pi-space my/work' # any POSIX shell: `myw -c` is `pi-space my/work -c`
|
|
191
|
+
abbr myw="pi-space my/work" # zsh-abbr: typing `myw` expands to the command
|
|
162
192
|
```
|
|
163
193
|
|
|
164
194
|
## Shell completion
|
|
165
195
|
|
|
166
|
-
`pi-space` completes its commands (each with a one-line summary), the profile
|
|
196
|
+
`pi-space` completes its commands (each with a one-line summary), the spaces of every profile as `<profile>/<name>`, `--every` and `<profile>/--every`, and files after `--config` and `--dir`. For zsh, add to `~/.zshrc` (after `compinit`):
|
|
167
197
|
|
|
168
198
|
```sh
|
|
169
199
|
source <(pi-space completion zsh)
|
|
170
200
|
```
|
|
171
201
|
|
|
172
|
-
It asks the command itself for the candidates each time, through the hidden `pi-space __complete`, so it always sees your current config and spaces. Options already typed are honored:
|
|
202
|
+
It asks the command itself for the candidates each time, through the hidden `pi-space __complete`, so it always sees your current config and spaces. `pi-space <TAB>` gives the same spaces as the picker, with each profile's `base` included. Options already typed are honored: `--config` makes it read that file, and `--dir` makes it list the spaces of that folder under each profile's prefix. It lists:
|
|
173
203
|
|
|
174
204
|
| After | Candidates |
|
|
175
205
|
| --- | --- |
|
|
176
|
-
| `pi-space` (and the call options) | the commands, then
|
|
177
|
-
| `--profile` | the profile names, `pi` included, each with its command |
|
|
206
|
+
| `pi-space` (and the call options) | the commands, then `<profile>/base` and the spaces of every profile (`completion` is not offered, but works typed in full) |
|
|
178
207
|
| `--config`, `--dir` | files (the shell's own completion) |
|
|
179
|
-
| `remove`, `rename` | the spaces |
|
|
180
|
-
| `setup` | the spaces and
|
|
181
|
-
| `list`, `update`, `install`, `uninstall` |
|
|
208
|
+
| `remove`, `rename` | the spaces of every profile (never `base`) |
|
|
209
|
+
| `setup` | the spaces, `--every` ("every profile") and `<profile>/--every` |
|
|
210
|
+
| `list`, `update`, `install`, `uninstall` | `<profile>/base`, the spaces, `--every` and `<profile>/--every` |
|
|
182
211
|
| `completion` | `zsh` |
|
|
183
212
|
|
|
184
|
-
In first place the call options not typed yet come too, and `--help` and `--version` when nothing comes before. After a command word the options come too: `--help` for every command, and `--yes` and `--no-backup` after `remove`. zsh shows them once the word starts with `-`, so `pi-space new <TAB>` never fills in a lone `--help`.
|
|
213
|
+
There is no `--profile` to complete: the profile is the first word of the space. In first place the call options not typed yet come too, and `--help` and `--version` when nothing comes before. After a command word the options come too: `--help` for every command, and `--yes` and `--no-backup` after `remove`. zsh shows them once the word starts with `-`, so `pi-space new <TAB>` never fills in a lone `--help`.
|
|
185
214
|
|
|
186
|
-
The candidates come in groups, each with a description, and zsh lists each group apart: commands, spaces (`
|
|
215
|
+
The candidates come in groups, each with a description, and zsh lists each group apart: commands, spaces, targets (`--every`), shells and options. The hidden `pi-space __complete` prints one `<group>\t<value>\t<description>` line per candidate (or the single line `__files__` when the shell should complete a file), so a script for another shell can use it.
|
|
187
216
|
|
|
188
|
-
Completion also works through an abbreviation or alias
|
|
217
|
+
Completion also works through an abbreviation or alias: they expand first, so what the alias stands for is what completes. A config file that is wrong just gives no candidates; completion never prints an error.
|
|
189
218
|
|
|
190
219
|
## Preparing a new space
|
|
191
220
|
|
|
192
|
-
A new space starts clean: only a `settings.json` that declares the extension. A program that runs Pi may need its own packages in every home it opens. Give
|
|
221
|
+
A new space starts clean: only a `settings.json` that declares the extension. A program that runs Pi may need its own packages in every home it opens. Give it as the profile's `setup`, or with `--setup` for one call, and `pi-space new` runs it right after it creates the space. The words are split as for `--command`, and in each word `{home}` becomes the space's folder and `{name}` its name. The command runs with your stdio, and with `PI_CODING_AGENT_DIR` and `PI_SPACE_HOME` set to the space's folder and `PI_SPACE` to its name:
|
|
193
222
|
|
|
194
223
|
```sh
|
|
195
|
-
pi-space --setup 'my-launcher --home {home} setup' new work # create "work", then: my-launcher --home ~/.pi/spaces/work setup
|
|
196
|
-
pi-space --setup 'pi install npm:some-package' new work # plain Pi: install a package in the new space
|
|
197
|
-
pi-space --setup 'my-launcher --home {home} setup' setup
|
|
224
|
+
pi-space --setup 'my-launcher --home {home} setup' new pi/work # create "work", then: my-launcher --home ~/.pi/spaces/work setup
|
|
225
|
+
pi-space --setup 'pi install npm:some-package' new pi/work # plain Pi: install a package in the new space
|
|
226
|
+
pi-space --setup 'my-launcher --home {home} setup' setup pi/--every # run it again in every space of "pi", for example after an update
|
|
198
227
|
```
|
|
199
228
|
|
|
200
|
-
When the setup fails, the space is kept and `pi-space` exits with the setup's status, naming `pi-space setup <name>` to run it again. `pi-space setup <name>` ends with the setup's status. With
|
|
229
|
+
When the setup fails, the space is kept and `pi-space` exits with the setup's status, naming `pi-space setup <profile>/<name>` to run it again. `pi-space setup <profile>/<name>` ends with the setup's status. With `<profile>/--every` it runs in every space of that profile in order, never in `base`; with `--every` alone, in every space of every profile that has a setup command (a profile without one is skipped; none at all exits with status 2). Each run comes after a `== <profile>/<name>` line, and the exit is as the package commands'. `base` is the home the program prepares itself. A profile without a setup command (and no `--setup`) exits with status 2: `pi-space: Profile "pi" has no setup command; give it a "setup" in the config file, or give --setup <cmd>.`
|
|
201
230
|
|
|
202
|
-
Only those three variables change. A variable that points into the base home stays as it is, so a setup that needs one per space sets it itself, for example `env MY_CONFIG={home}/config my-launcher --home {home} setup`.
|
|
231
|
+
Only those three variables change. A variable that points into the base home stays as it is, so a setup that needs one per space sets it itself, for example `env MY_CONFIG={home}/config my-launcher --home {home} setup`. The setup reaches the Pi that `pi-space` starts as `PI_SPACES_SETUP`, so `/space new` there names `pi-space setup <profile>/<name>`.
|
|
203
232
|
|
|
204
233
|
## Exit status
|
|
205
234
|
|
|
206
235
|
| Status | Meaning |
|
|
207
236
|
| --- | --- |
|
|
208
|
-
| 0 … | Pi's own exit status, for a space and for a package command in one space; the setup's exit status for `setup <name>` and for a `new` whose setup failed. |
|
|
209
|
-
| 1 | An unknown or invalid space, a name `new` or `rename` cannot use (taken, reserved or invalid), a space `remove` or `rename` cannot touch, `remove` without `--yes` and no terminal, the program could not start, or `--every` and at least one run failed (the failed spaces are on the last line of stderr), or `setup base`, since setup runs only in spaces. |
|
|
237
|
+
| 0 … | Pi's own exit status, for a space and for a package command in one space; the setup's exit status for `setup <profile>/<name>` and for a `new` whose setup failed. |
|
|
238
|
+
| 1 | An unknown or invalid space (or one missing from its profile), a name `new` or `rename` cannot use (taken, reserved or invalid), a space `remove` or `rename` cannot touch, `remove` without `--yes` and no terminal, the program could not start, or `--every` and at least one run failed (the failed spaces are on the last line of stderr), or `setup <profile>/base`, since setup runs only in spaces. |
|
|
210
239
|
| 130 | Ctrl-C in the picker. |
|
|
211
|
-
| 2 | A config file that is wrong or an unknown
|
|
240
|
+
| 2 | A config file that is wrong or an unknown profile (the problem is printed), a space named without its profile (the forms to use are printed), a `rename` to another profile, `completion` with another shell or none, no arguments and no terminal to pick in, a command with the wrong number of names (`new`, `remove`, `rename`), `install` or `uninstall` without a source, a package command without a space or `--every`, `--command` or `--dir` with the picker, `list` alone or a global `--every` (they apply to one profile), or `--command`, `--dir`, `--setup` or `--config` without a value (or a blank one) or given twice: the usage is printed. `setup` without a setup command (`Profile "pi" has no setup command`) or with no profile having one: the problem is printed. The old `--new`, `--remove` and `--profile`: the replacing command is printed. A `--command`, `--setup` or a profile's `command` or `setup` with an unclosed quote: the problem is printed, and nothing is created or started. |
|
|
212
241
|
|
|
213
242
|
## More
|
|
214
243
|
|