space-cadet 9.0.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 (56) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +32 -0
  3. data/LICENSE.txt +21 -0
  4. data/README.md +279 -0
  5. data/exe/space +13 -0
  6. data/lib/space_core/atomic_write.rb +21 -0
  7. data/lib/space_core/cli/base_command.rb +19 -0
  8. data/lib/space_core/cli/build.rb +27 -0
  9. data/lib/space_core/cli/config.rb +49 -0
  10. data/lib/space_core/cli/current.rb +16 -0
  11. data/lib/space_core/cli/help.rb +195 -0
  12. data/lib/space_core/cli/helpers.rb +115 -0
  13. data/lib/space_core/cli/init.rb +29 -0
  14. data/lib/space_core/cli/list.rb +24 -0
  15. data/lib/space_core/cli/loop_status.rb +47 -0
  16. data/lib/space_core/cli/new.rb +38 -0
  17. data/lib/space_core/cli/pack.rb +29 -0
  18. data/lib/space_core/cli/path.rb +16 -0
  19. data/lib/space_core/cli/repeatable_options.rb +84 -0
  20. data/lib/space_core/cli/repo.rb +76 -0
  21. data/lib/space_core/cli/run.rb +44 -0
  22. data/lib/space_core/cli/shell.rb +125 -0
  23. data/lib/space_core/cli/show.rb +21 -0
  24. data/lib/space_core/cli/status.rb +74 -0
  25. data/lib/space_core/cli/use.rb +17 -0
  26. data/lib/space_core/cli.rb +177 -0
  27. data/lib/space_core/cloner.rb +77 -0
  28. data/lib/space_core/commands.rb +51 -0
  29. data/lib/space_core/config.rb +152 -0
  30. data/lib/space_core/errors.rb +14 -0
  31. data/lib/space_core/git_client.rb +49 -0
  32. data/lib/space_core/mise_client.rb +37 -0
  33. data/lib/space_core/oci_builder.rb +56 -0
  34. data/lib/space_core/oci_packer.rb +103 -0
  35. data/lib/space_core/oci_runner.rb +89 -0
  36. data/lib/space_core/paths.rb +58 -0
  37. data/lib/space_core/repo_reference.rb +19 -0
  38. data/lib/space_core/repo_resolver.rb +167 -0
  39. data/lib/space_core/scm/client.rb +87 -0
  40. data/lib/space_core/scm/git.rb +232 -0
  41. data/lib/space_core/scm/status.rb +24 -0
  42. data/lib/space_core/shell.rb +90 -0
  43. data/lib/space_core/shell_integration.rb +438 -0
  44. data/lib/space_core/slugger.rb +16 -0
  45. data/lib/space_core/space.rb +174 -0
  46. data/lib/space_core/space_store.rb +319 -0
  47. data/lib/space_core/state.rb +86 -0
  48. data/lib/space_core/templates/oci/dockerfile.erb +73 -0
  49. data/lib/space_core/templates/oci/dockerignore.erb +17 -0
  50. data/lib/space_core/templates/oci/entrypoint.sh.erb +16 -0
  51. data/lib/space_core/terminal.rb +161 -0
  52. data/lib/space_core/version.rb +7 -0
  53. data/lib/space_core/warnings.rb +13 -0
  54. data/lib/space_core/xdg.rb +33 -0
  55. data/lib/space_core.rb +26 -0
  56. metadata +199 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 43aad33181b2d51dcdf9a43b797325a90b513b2ea6b9d1aa5774b5c6d3e14fed
4
+ data.tar.gz: c63367116cb12fc23008af8f0be141b3e4d86db6bd90826c135000898eef5c89
5
+ SHA512:
6
+ metadata.gz: 50f518864108c2475262cf5931bff2af4cd79205961b7ff935ab187ccf15cfdaa9caa40f835e6926e169cc4f1ca3fdaf284cfea1b4b029598673fcf9de0fc1a2
7
+ data.tar.gz: 849789bb6f71eb569af79a1d5ed93dbd2c32c1510b8601180fea6ca4129e5d82e2118e8479c3baa2c4e185f1756663046d07fb1959c3634824ba09f5f8d5c9bf
data/CHANGELOG.md ADDED
@@ -0,0 +1,32 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [9.0.0] - 2026-10-09
9
+
10
+ ### Changed
11
+
12
+ - **Extracted from space-architect 8.0.0.** The space tool (`Space::Core`,
13
+ binary `space`) is split back out of
14
+ [jetpks/space-architect](https://github.com/jetpks/space-architect) into its
15
+ own repo, gem, and version line — undoing the v1.0.0-era absorption. The gem
16
+ is `space-cadet`, the binary is `space`, the module stays `Space::Core`, and
17
+ the version restarts at 9.0.0 (one major above the 8.x line it left).
18
+ - The fish shell integration's internals are renamed to the gem's own identity:
19
+ `__space_core_*` functions and the `__SPACE_CORE_VERSION__` compat-token
20
+ placeholder (was `__space_architect_*` / `__SPACE_ARCHITECT_VERSION__`).
21
+ Re-run `space shell fish install` after upgrading.
22
+ - XDG config/state now live under `~/.config/space-cadet/` and
23
+ `~/.local/state/space-cadet/` (was `space-architect/`). Run `space init` and
24
+ migrate any custom `config.yml`/`state.yml` across.
25
+ - The engine's subprocess shell, copy-on-write cloner, and git SCM seam
26
+ (`Space::Core::Shell`, `Space::Core::Cloner`, `Space::Core::SCM::*`) are
27
+ vendored into the gem — previously shared with the space-architect monolith's
28
+ `Space::Src` engine.
29
+ - Dependencies trimmed to exactly what the space tool requires: `async`,
30
+ `async-process`, `pastel`, `dry-cli`, `dry-monads`.
31
+
32
+ [9.0.0]: https://github.com/jetpks/space-cadet/blob/main/CHANGELOG.md
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Eric
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,279 @@
1
+ # Space Cadet 🪐
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/space-cadet.svg)](https://badge.fury.io/rb/space-cadet)
4
+
5
+ > **Task-scoped project workspaces — for humans and their agents!** ✨🌌
6
+
7
+ `space-cadet` is a Ruby gem for **spaces** — task-scoped project workspaces
8
+ that hold repos, notes, and artifacts under one obvious filesystem root. One
9
+ binary, **`space`**, over the `Space::Core` library. It pairs with
10
+ [jetpks/space-architect](https://github.com/jetpks/space-architect) (the
11
+ Architect Loop, which runs on top of spaces) and
12
+ [jetpks/repo-tender](https://github.com/jetpks/repo-tender) (which tends the
13
+ evergreen checkouts spaces provision from).
14
+
15
+ **Lineage:** this repo is the space tool's original home (the v1.0.0 era); the
16
+ tool was absorbed into space-architect (up to 8.0.0) and is extracted back out
17
+ here as of 9.0.0.
18
+
19
+ ## What's a space? 🪐
20
+
21
+ A space is just a regular directory with a tiny YAML identity file and room for
22
+ everything a task needs:
23
+
24
+ ```text
25
+ ~/architect/spaces/20260531-name-of-space/
26
+ space.yaml # identity: id, title, status, repos, notes, tags
27
+ README.md
28
+ repos/ # cloned (or copy-on-write'd) repositories
29
+ notes/ # scratch, prompts, logs
30
+ architecture/ # project files when the space runs an Architect project
31
+ build/ # OCI contexts + scratch (build/oci/)
32
+ tmp/ # workspace-local temp — use this instead of /tmp
33
+ ```
34
+
35
+ Run a command from anywhere inside a space and it just works — `space` walks up
36
+ from `$PWD` until it finds the nearest `space.yaml`. No "current space" state
37
+ to get out of sync; where you *are* is the space you mean. 🧭
38
+
39
+ ## Installation 📦
40
+
41
+ Add it to your `Gemfile`:
42
+
43
+ ```ruby
44
+ gem "space-cadet"
45
+ ```
46
+
47
+ ```bash
48
+ bundle install
49
+ ```
50
+
51
+ Or grab it yourself:
52
+
53
+ ```bash
54
+ gem install space-cadet
55
+ ```
56
+
57
+ The gem is `space-cadet`; it installs one executable, `space`. 🎀
58
+
59
+ ## Quick start 🎀
60
+
61
+ ```sh
62
+ space init # create XDG config + state files
63
+ space new "Name of Space" # blast off a new space 🚀
64
+ space new "Name of Space" -r org/repo -r org/lib # …with repos cloned in (repeat -r)
65
+ space list # see all your spaces
66
+ space show # show the space you're standing in
67
+
68
+ # Containers (run from inside a space) — a portable, reproducible-by-SHA image of the space
69
+ space pack # render build/oci/ (Dockerfile + entrypoint)
70
+ space build # pack + build & tag <space-id>:<git-sha>
71
+ space run # run it — login shell, auth from your env
72
+ ```
73
+
74
+ ## Commands 🌌
75
+
76
+ ```sh
77
+ space init
78
+ space new "Name of Space"
79
+ space new "Name of Space" -r org/repo -r example-tools/alpha -r example-tools/beta
80
+ space list # alias: space ls
81
+ space show 20260531-name-of-space
82
+ space path 20260531-name-of-space
83
+ space current # based on $PWD
84
+ space show # based on $PWD
85
+ space status # report: metadata (+ project status when present)
86
+ space status 20260531-name-of-space # report another space
87
+ space status done # set: active | paused | done | archived
88
+ space status 20260531-name-of-space done
89
+ space config set default_provider github.com
90
+ space config set default_organization example-org
91
+ space repo add example-app # github.com/example-org/example-app
92
+ space repo add example-tools/alpha example-tools/beta
93
+ space repo add gitlab.com/example-org/api
94
+ space repo resolve example-app example-tools/async
95
+ space repo ls # alias: space repos ls
96
+ space use 20260531-name-of-space # records recent state, prints the path
97
+ space ls --color=always # auto | always | never (--colors also accepted)
98
+ ```
99
+
100
+ `space status` is **report-or-set**: with no status keyword (bare, or with just
101
+ a space id) it *reports* the space — its metadata plus a compact project-status
102
+ block when the space declares one, quietly omitted otherwise; pass a status
103
+ keyword (`active`, `paused`, `done`, `archived`) to *set* it instead. 🔁
104
+
105
+ Repos are passed with a repeatable `-r` flag (`-r org/repo -r org/lib`); the
106
+ comma form (`-r a,b`) works too. Space ids are date-prefixed
107
+ (`20260531-name-of-space`) so they sort naturally, and duplicate names on the
108
+ same day get a counter (`…-name-of-space-2`). 📅
109
+
110
+ Full command reference: [docs/reference.md](docs/reference.md).
111
+
112
+ ## Containerize a space: `pack` · `build` · `run` 📦
113
+
114
+ A space is self-describing enough to become a container. `space pack` renders a
115
+ portable OCI build context from the space; `space build` packs and builds it into
116
+ a **reproducible-by-SHA** image; `space run` runs that image with your auth
117
+ injected at runtime and stateful paths bind-mounted back to the host. 🐳
118
+
119
+ ```sh
120
+ space pack # render build/oci/ (Dockerfile + entrypoint + ignore file)
121
+ space pack -o /tmp/ctx # …to a different output directory
122
+ space build # pack, then build & tag <space-id>:<git-sha> and :latest
123
+ space run # run <space-id>:latest — login shell, auth from your env
124
+ space run architect status # …or run a one-off command instead of the login shell
125
+ space run --tty # force an interactive TTY (default: auto-detect)
126
+ ```
127
+
128
+ **What lands in the image.** The context copies the whole space tree (filtered by
129
+ a generated `Dockerfile.dockerignore`) onto a `ruby:4.0.5` base with `git`, the
130
+ Claude Code CLI, and the `space-cadet` gem — installed from the in-space
131
+ `repos/space-cadet` checkout when present (a pinned build), else from
132
+ RubyGems. Secrets never enter the layers: `.env`, `*.key`, `*.pem`, ssh keys,
133
+ `build/`, and `tmp/` are all excluded by the generated ignore file. 🔒
134
+
135
+ **Reproducible by SHA.** `space build` tags the image `<space-id>:<sha>`, where
136
+ `<sha>` is the space repo's 12-char `HEAD` (suffixed `-dirty` when the tree has
137
+ uncommitted changes), plus a moving `:latest`. Same commit → same tag → same
138
+ image. It drives the `container` CLI, but the output is an ordinary OCI/Docker
139
+ build context, so `docker build -f build/oci/Dockerfile .` (from the space root)
140
+ works just as well.
141
+
142
+ **Auth stays out of the layers.** `space run` injects only the auth environment
143
+ variables that are actually set — `ANTHROPIC_API_KEY`, `CLAUDE_CODE_OAUTH_TOKEN`,
144
+ `ANTHROPIC_BASE_URL` — with `-e` at run time, so credentials live in your shell,
145
+ never in the image. 🗝️
146
+
147
+ **Forwarding payload credentials.** Beyond the always-on auth trio, a space can declare
148
+ `run.env:` in `space.yaml` — a list of host env var names forwarded into the container at
149
+ run time. You can also pass `space run --env VAR` (repeatable) for ad hoc additions. All
150
+ forwarding is bare `-e VAR` passthrough: values never appear in argv, `ps`, or the image.
151
+ A requested-but-unset var warns on stderr instead of silently failing inside the guest.
152
+
153
+ ```yaml
154
+ run:
155
+ env: # run-time: host var names, forwarded as bare -e VAR
156
+ - FIREWORKS_API_KEY
157
+ - OPENAI_API_KEY
158
+ ```
159
+
160
+ **Declaring provisioning & persistence** — two optional keys in `space.yaml`:
161
+
162
+ ```yaml
163
+ pack:
164
+ provision: # build-time: relative scripts, baked in by `space build`
165
+ - scripts/setup-toolchain.sh
166
+ persist: # run-time: absolute guest paths, bind-mounted per run
167
+ - /root/.claude
168
+ - /root/.local/state
169
+ ```
170
+
171
+ `provision` scripts must live under the space root and be executable. Each script is
172
+ copied into the image individually (`COPY <script> /space/<script>`) and then invoked
173
+ (`RUN /space/<script>`) **before** the full space tree lands and **before** the gem is
174
+ installed. This ordering is the cache-hygiene guarantee: editing any other space file
175
+ leaves the provision and gem-install layers cached, so a rebuild completes in seconds
176
+ instead of minutes. Scripts must therefore be self-contained — they run with only the
177
+ base system layers and any earlier provision scripts' outputs; they cannot read other
178
+ space files or call `space`. Scripts must have the executable bit set; COPY preserves
179
+ the mode from the build context.
180
+
181
+ `persist` paths must be absolute; `space run` bind-mounts each one from
182
+ `<space>/.state<path>` on the host (created on first run) so a container's mutable state
183
+ survives across runs. Both are validated at pack time.
184
+
185
+ ## Fish shell integration 🐟
186
+
187
+ Shells can't let a child process change *their* working directory, so `space`
188
+ ships a small fish wrapper function plus completions (commands, subcommands,
189
+ spaces, statuses, config keys, repo refs). Install into fish's autoloaded
190
+ directories:
191
+
192
+ ```fish
193
+ space shell fish install
194
+ exec fish
195
+ ```
196
+
197
+ After restarting fish (or `exec fish`), `space new "…"` and
198
+ `space use <id>` will `cd` into the selected space once the command succeeds;
199
+ every other command keeps normal CLI behavior. 🚪 The functions and completions
200
+ are written under `~/.config/fish/`, so there's no need to edit `config.fish`.
201
+ For one-off testing without installing:
202
+
203
+ ```fish
204
+ space shell init fish | source
205
+ ```
206
+
207
+ ## Configuration ⚙️
208
+
209
+ Config lives at `~/.config/space-cadet/config.yml` (XDG-aware) and defaults to:
210
+
211
+ ```yaml
212
+ version: 1
213
+ base_dir: ~/architect # spaces_dir + src_dir hang off this by default
214
+ default_provider: github.com
215
+ default_organization:
216
+ git_clone_protocol: ssh # ssh | https
217
+ ```
218
+
219
+ Derived defaults: `spaces_dir` → `<base_dir>/spaces`, `src_dir` (evergreen
220
+ checkout root) → `<base_dir>/src`. Override either explicitly. View values with
221
+ `space config show`; set one with `space config set KEY VALUE`. Editable keys:
222
+ `base_dir`, `spaces_dir`, `src_dir`, `default_provider`, `default_organization`,
223
+ `git_clone_protocol`.
224
+
225
+ ## Repos: evergreen, copy-on-write, concurrent ⚡
226
+
227
+ Repos are added to the current space under `repos/` and tracked in `space.yaml`.
228
+ When an up-to-date evergreen checkout exists at
229
+ `<src_dir>/<host>/<owner>/<name>` (e.g.
230
+ `~/architect/src/github.com/example-org/example-app` — tended by
231
+ [jetpks/repo-tender](https://github.com/jetpks/repo-tender)), `space` copies it
232
+ into the space instead of cloning over the network — a copy-on-write clone on
233
+ APFS. ⚡ Set `src_dir` empty to always clone:
234
+
235
+ ```sh
236
+ space config set src_dir ""
237
+ ```
238
+
239
+ Clone URLs default to SSH (`git@github.com:example-org/example-app.git`); switch
240
+ with `space config set git_clone_protocol https`. Multiple repos passed to
241
+ `space repo add` are fetched **concurrently**, up to five at a time, on fibers —
242
+ no threads, all cooperative. 🧵 After each repo lands, `space` runs `mise trust`
243
+ in it. Each space also gets a workspace-local `tmp/` — use it instead of `/tmp`.
244
+
245
+ ## Embedding 📚
246
+
247
+ ```ruby
248
+ require "space_core" # config, state, XDG, terminal, git/mise clients,
249
+ # the space store — the `space` CLI runs on this alone
250
+ ```
251
+
252
+ ## Documentation 📖
253
+
254
+ - **[Command Reference](docs/reference.md)** — every command, flag, and behavior
255
+ - **[Releasing](docs/RELEASING.md)** — how a release lands
256
+ - **[Changelog](CHANGELOG.md)** — release history
257
+
258
+ ## Development 🛠️
259
+
260
+ ```sh
261
+ bundle install
262
+ bundle exec rake test # the minitest suite
263
+ bundle exec rake build # build the gem into pkg/
264
+ bundle exec rake install # build + install into your user gem home
265
+ ```
266
+
267
+ ## Contributing 💝
268
+
269
+ Bug reports and pull requests are welcome on GitHub at
270
+ [https://github.com/jetpks/space-cadet](https://github.com/jetpks/space-cadet)!
271
+
272
+ ## License 📄
273
+
274
+ Available as open source under the terms of the
275
+ [MIT License](https://opensource.org/licenses/MIT).
276
+
277
+ ---
278
+
279
+ Made with 💖 and fibers 🧵 by Eric
data/exe/space ADDED
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ source_gemfile = File.expand_path("../Gemfile", __dir__)
5
+ if File.exist?(source_gemfile)
6
+ ENV["BUNDLE_GEMFILE"] ||= source_gemfile
7
+ require "bundler/setup"
8
+ $LOAD_PATH.unshift(File.expand_path("../lib", __dir__))
9
+ end
10
+
11
+ require "space_core"
12
+
13
+ Space::Core::CLI.run(ARGV, $stdout, $stderr)
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "fileutils"
4
+
5
+ module Space::Core
6
+ module AtomicWrite
7
+ module_function
8
+
9
+ def write(path, content)
10
+ path = path.to_s
11
+ dir = File.dirname(path)
12
+ FileUtils.mkdir_p(dir)
13
+ tmp_path = File.join(dir, ".#{File.basename(path)}.#{Process.pid}.tmp")
14
+
15
+ File.write(tmp_path, content)
16
+ File.rename(tmp_path, path)
17
+ ensure
18
+ FileUtils.rm_f(tmp_path) if defined?(tmp_path) && tmp_path && File.exist?(tmp_path)
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dry/cli"
4
+
5
+ module Space::Core::CLI
6
+ # Base for every space/architect command. dry-cli (>= 0.7.0) copies a
7
+ # superclass's options to its subclasses, so the global colour options are
8
+ # declared once here and inherited everywhere instead of being mixed in per
9
+ # command. Helpers (terminal/store/render) ride along by inheritance too.
10
+ #
11
+ # The `src` binary has its own output-mode system (--plain/--json) and does
12
+ # NOT inherit from this base.
13
+ class BaseCommand < Dry::CLI::Command
14
+ include Helpers
15
+
16
+ option :color, type: :string, default: "auto", desc: "Color output: auto, always, never"
17
+ option :colors, type: :string, desc: "Alias for --color"
18
+ end
19
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../oci_packer"
4
+ require_relative "../oci_builder"
5
+
6
+ module Space::Core::CLI
7
+ class Build < BaseCommand
8
+ desc "Build (and tag) the OCI image for the current space"
9
+
10
+ def call(**opts)
11
+ setup_terminal(**opts.slice(:color, :colors))
12
+ handle_errors do
13
+ result = store.current.bind do |space|
14
+ out_dir = space.path.join("build", "oci")
15
+ Space::Core::OciPacker.new(space: space, output_dir: out_dir).generate.bind do
16
+ Space::Core::OciBuilder.new(space: space, output_dir: out_dir).command
17
+ end
18
+ end
19
+ render(result) do |argv|
20
+ terminal.say "Building: #{argv.join(' ')}"
21
+ out.flush
22
+ Kernel.exec(*argv)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Space::Core::CLI
4
+ module Config
5
+ class Show < BaseCommand
6
+ desc "Show current config"
7
+
8
+ def call(**opts)
9
+ setup_terminal(**opts.slice(:color, :colors))
10
+ handle_errors do
11
+ rows = Space::Core::Config::EDITABLE_KEYS.map do |key|
12
+ value = project_config.data[key]
13
+ [key, value.nil? ? "" : value.to_s]
14
+ end
15
+ terminal.say terminal.table(%w[Key Value], rows)
16
+ CLI.record_outcome(Outcome.new(exit_code: 0))
17
+ end
18
+ end
19
+ end
20
+
21
+ class ConfigPath < BaseCommand
22
+ desc "Print the config file path"
23
+
24
+ def call(**opts)
25
+ setup_terminal(**opts.slice(:color, :colors))
26
+ handle_errors do
27
+ terminal.say terminal.path(project_config.path)
28
+ CLI.record_outcome(Outcome.new(exit_code: 0))
29
+ end
30
+ end
31
+ end
32
+
33
+ class Set < BaseCommand
34
+ desc "Set a config key"
35
+ argument :key, required: true, desc: "Config key"
36
+ argument :value, required: true, desc: "Config value"
37
+
38
+ def call(key:, value:, **opts)
39
+ setup_terminal(**opts.slice(:color, :colors))
40
+ handle_errors do
41
+ project_config.set(key, value)
42
+ stored = project_config.data[key]
43
+ terminal.success "Set #{key}=#{stored.nil? ? '' : stored.to_s}"
44
+ CLI.record_outcome(Outcome.new(exit_code: 0))
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Space::Core::CLI
4
+ class Current < BaseCommand
5
+ desc "Show the current space"
6
+
7
+ def call(**opts)
8
+ setup_terminal(**opts.slice(:color, :colors))
9
+ render(store.find) do |space|
10
+ terminal.say space.id.to_s
11
+ terminal.say terminal.path(space.path)
12
+ CLI.record_outcome(Outcome.new(exit_code: 0))
13
+ end
14
+ end
15
+ end
16
+ end