@jals1212/pi-spaces-cli 0.7.1 → 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.
Files changed (4) hide show
  1. package/CHANGELOG.md +58 -0
  2. package/README.md +116 -87
  3. package/dist/cli.js +431 -309
  4. package/package.json +2 -2
package/CHANGELOG.md CHANGED
@@ -6,6 +6,64 @@ 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
+
9
67
  ## 0.7.1
10
68
 
11
69
  ### Fixed
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. Named [profiles](#profiles) in a config file say 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, the profiles and the spaces. It is the optional companion of the Pi extension [`@jals1212/pi-spaces`](https://github.com/jals1212/pi-spaces#readme), which holds the spaces themselves.
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 (the reservation of `completion` is in `@jals1212/pi-spaces` 0.6.0).
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 space or profile name. `base` comes first, and the cursor starts on the space this Pi runs in, marked `(active)`. With a config file and no `--profile`, `--dir` or `--command`, the spaces of every profile are listed under its name, the current one first; a space of another profile starts with that profile. |
20
- | `pi-space <name> [pi args...]` | Starts Pi in that space (`base` for the home Pi starts with). |
21
- | `pi-space list` | Lists the spaces. |
22
- | `pi-space list <name\|--every>` | Lists the packages of a space (Pi's `list`). |
23
- | `pi-space new <name>` | Creates an empty space, as `/space new <name>` does in Pi, then runs the setup command in it when there is one (see [Preparing a new space](#preparing-a-new-space)). It does not start Pi. |
24
- | `pi-space setup <name\|--every>` | Runs the setup command in a space, or in every space. Never in `base`. |
25
- | `pi-space rename <old> <new>` | Renames a space, as `/space rename` does in Pi. It refuses what `remove` refuses (see below). |
26
- | `pi-space remove <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. |
27
- | `pi-space update <name\|--every> [pi update options...]` | Runs Pi's `update` in a space. What follows is Pi's: `--extensions`, `--all`, a source. With nothing after the name it is Pi's default. |
28
- | `pi-space install <name\|--every> <source> [pi install options...]` | Runs Pi's `install` in a space. The source is required. |
29
- | `pi-space uninstall <name\|--every> <source> [pi options...]` | Runs Pi's `uninstall` (its alias of `remove`) in a space. The source is required. |
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 name every argument belongs to Pi, so `pi-space work --help` starts Pi with `--help`. An unknown command (`pi-space --help ghost`) exits with status 2 and lists the commands.
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` and `--remove`, the options of 0.3, were replaced by `new` and `remove`; they exit with status 2 and name the command to use.
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 every space
54
+ ### Packages in a space, or in many
40
55
 
41
56
  ```sh
42
- pi-space list work # the packages of "work"
43
- pi-space install work npm:some-package # install in "work" only
44
- pi-space update base --extensions # update the extensions of the base home
45
- pi-space update --every # base, then every space
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 `$PI_SPACES_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; `pi-space` never sets `PI_CODING_AGENT_DIR` itself. `<name>` is `base` or an existing space; anything else exits with status 1 before Pi starts.
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
- `--every` takes the place of the name. The command runs in `base` first, then in every space in order, one after the other, each after a `== <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: base, work`.
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
- 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` (`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`.
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
- `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 it asks. 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).
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 (or name a [profile](#profiles) that holds both); 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` ignores `--command`, `rename` ignores `--setup`), so one alias can give them all:
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 # create one in that folder
63
- pi-space --command '"/opt/my launcher/run" --' work # a path with spaces, in quotes
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
- An alias keeps it short: `alias my-space='pi-space --command "my-launcher --" --dir ~/.my-launcher/spaces'`. To make it the default instead, set the variables in your shell profile:
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
- ```sh
71
- export PI_SPACES_COMMAND="my-launcher --" # pi-space work → my-launcher -- --space work
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` | The program to run, split on spaces (double or single quotes keep a path with spaces in one word, as in `"/opt/my launcher/run" --`), before `--space <name>`. Default: `pi`. `--command` wins for one call. |
78
- | `PI_SPACES_DIR` | The spaces folder. A relative value is taken from your home folder. Default: `spaces` next to the base home. `--dir` wins for one call; a relative `--dir` is taken from the current folder. |
79
- | `PI_SPACES_SETUP` | The command that prepares a new space (see [Preparing a new space](#preparing-a-new-space)). Unset or blank: none. `--setup` wins for one call. |
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 --profile ml list # the spaces of the profile "ml"
89
- pi-space --profile ml work # start the profile's program in its space "work"
90
- pi-space --profile ml new work # create it, then run the profile's setup in it
91
- pi-space --config ./other.json --profile ml list # the same profile from another file, for this call
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
- `--profile <name>` and `--config <path>` come before the command, like `--command`, `--dir` and `--setup`: each needs a value (not blank) and may be given once, and after a space name 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.`
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 command behaves exactly as without profiles. 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.
97
- - **`default`**: without `--profile`, the file's `default` profile is used, if it names one. With `--profile`, the default is not consulted at all: a profile never borrows from another.
98
- - **`pi`** is built in: command `pi`, home `PI_CODING_AGENT_DIR` (else `~/.pi/agent`). It always exists, so `--profile pi` goes back to plain Pi when the default is another program, and a `pi` in the file's `profiles` replaces it.
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. the profile named with `--profile`;
106
- 3. the variable (`PI_SPACES_COMMAND`, `PI_SPACES_DIR`, `PI_SPACES_SETUP`);
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 (instead of `PI_SPACES_BASE_HOME` or `PI_CODING_AGENT_DIR`), and `remove` and `rename` refuse the space that holds it.
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
- - `--config <path>` becomes `PI_SPACES_CONFIG` (absolute), like `--dir` becomes `PI_SPACES_DIR`.
117
- - When a profile supplies a `dir` or a `setup`, they reach it as `PI_SPACES_DIR` and `PI_SPACES_SETUP`, exactly as `--dir` and `--setup` would, so `/space new` there agrees with `pi-space new`.
118
- - Nothing else is added: when nothing is to be passed, the child inherits your environment as it is. `--command` is never passed.
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
- When a profile is selected (`--profile`, or the default), its `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`. It applies whichever setup command runs: the profile's own `setup`, or one from `--setup` or `PI_SPACES_SETUP`, because the space is that profile's. A call without any profile adds nothing, as before.
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 --profile my new work # creates ~/.my-launcher/spaces/work, then runs:
146
- # my-launcher --home ~/.my-launcher/spaces/work setup
147
- # with MY_LAUNCHER_CONFIG_HOME=~/.my-launcher/spaces/work/config
148
- pi-space --profile my work -c # my-launcher -- --space work -c
149
- pi-space --profile my setup --every # run the setup again in every space of "my"
150
- pi-space --profile pi list # the spaces of plain Pi, from the same shell
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 abbreviation or alias can shorten `--profile my` to one word. It is only sugar: no logic lives in it, and the profile stays in the config file.
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
- abbr my-space="pi-space --profile my" # zsh-abbr; typing `my-space work` expands to `pi-space --profile my work`
161
- alias my-space='pi-space --profile my' # any POSIX shell
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 names after `--profile`, files after `--config` and `--dir`, and the spaces. For zsh, add to `~/.zshrc` (after `compinit`):
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: after `pi-space --profile my remove <TAB>` you get the spaces of `my`, not those of the default. It lists:
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 `base` and the spaces (`completion` is not offered, but works typed in full) |
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 `--every` |
181
- | `list`, `update`, `install`, `uninstall` | `base`, the spaces and `--every` |
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 (`base` is "the home Pi starts with"), profiles, 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.
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 like the one above: they expand first, so `my-space <TAB>` completes what `pi-space --profile my <TAB>` would. A config file that is wrong, or a profile that does not exist, just gives no candidates; completion never prints an error.
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 its setup command with `--setup` (or `PI_SPACES_SETUP`), 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:
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 --every # run it again in every space, for example after an update
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 `--every` it runs in every space in order, never in `base`, each after a `== <name>` line, and exits as the package commands do. `base` is the home the program prepares itself.
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`. `--setup` also reaches the Pi that `pi-space` starts as `PI_SPACES_SETUP`, so `/space new` there names `pi-space setup <name>`.
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 `--profile` (the problem is printed), `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`, or `--command`, `--dir`, `--setup`, `--profile` or `--config` without a value (or a blank one) or given twice: the usage is printed. `setup` without a setup command: the problem is printed. The old `--new` and `--remove`: the replacing command is printed. A `--command`, `PI_SPACES_COMMAND`, `--setup`, `PI_SPACES_SETUP` or a profile's `command` or `setup` with an unclosed quote: the problem is printed, and nothing is created or started. |
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