localvault 1.11.2 → 1.12.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.
- checksums.yaml +4 -4
- data/lib/localvault/cli/sync.rb +4 -2
- data/lib/localvault/cli.rb +65 -27
- data/lib/localvault/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6ffea91e8b5b758be685a82b78154018889db3b8ece76a942f10879fe79e19d8
|
|
4
|
+
data.tar.gz: 4b43e48d4913b88dffcb0ce18ddb819dd9470edde959cde7b8d4c50e86294e3d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 73c0bb42f97afff36f09cce9a66e6ea9f37d8a25c8609a424f9c190cdaa3abc0dd6fb70765bdd2c4f0d5d113812a36f8a645dd557b4914c3620b48c5838b62d7
|
|
7
|
+
data.tar.gz: 5766f8a512cebf5be3ceb4778f72fa2f5cf591b098e435d3a4cfa623912016c07bb8a3073f557ae4bf5764845802584750cc2434d472907474e81ac9bfdada27
|
data/lib/localvault/cli/sync.rb
CHANGED
|
@@ -111,18 +111,20 @@ module LocalVault
|
|
|
111
111
|
default_task :all
|
|
112
112
|
|
|
113
113
|
desc "push [NAME]", "Push a vault to InventList cloud sync"
|
|
114
|
+
method_option :vault, type: :string, aliases: "-v", desc: "Vault name (same as NAME)"
|
|
114
115
|
def push(vault_name = nil)
|
|
115
116
|
return unless logged_in?
|
|
116
|
-
vault_name ||= Config.default_vault
|
|
117
|
+
vault_name ||= options[:vault] || Config.default_vault
|
|
117
118
|
client = ApiClient.new(token: Config.token)
|
|
118
119
|
perform_push(vault_name, client)
|
|
119
120
|
end
|
|
120
121
|
|
|
121
122
|
desc "pull [NAME]", "Pull a vault from InventList cloud sync"
|
|
122
123
|
method_option :force, type: :boolean, default: false, desc: "Overwrite existing local vault"
|
|
124
|
+
method_option :vault, type: :string, aliases: "-v", desc: "Vault name (same as NAME)"
|
|
123
125
|
def pull(vault_name = nil)
|
|
124
126
|
return unless logged_in?
|
|
125
|
-
vault_name ||= Config.default_vault
|
|
127
|
+
vault_name ||= options[:vault] || Config.default_vault
|
|
126
128
|
client = ApiClient.new(token: Config.token)
|
|
127
129
|
perform_pull(vault_name, client, force: options[:force])
|
|
128
130
|
end
|
data/lib/localvault/cli.rb
CHANGED
|
@@ -124,42 +124,57 @@ module LocalVault
|
|
|
124
124
|
["OTHER", %w[logout version doctor help]]
|
|
125
125
|
].freeze
|
|
126
126
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
127
|
+
# One row per plain command; registered subcommands (sync, team, keys,
|
|
128
|
+
# guard, identity, ...) expand to a row per action, straight from that
|
|
129
|
+
# registry — so `sync push` or a newly added `guard` action is always
|
|
130
|
+
# visible without touching this method.
|
|
131
|
+
def self.help_rows_for(name)
|
|
132
|
+
command = all_commands[name.tr("-", "_")]
|
|
133
|
+
return [] if command.nil? || command.hidden?
|
|
130
134
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
135
|
+
registry = subcommand_classes[command.name]
|
|
136
|
+
return [[command.usage, command.description]] unless registry
|
|
137
|
+
|
|
138
|
+
registry.all_commands.filter_map do |sub_name, sub|
|
|
139
|
+
next if sub.hidden? || %w[help tree].include?(sub_name) # Thor built-ins, redundant per-namespace
|
|
140
|
+
["#{command.name} #{sub.usage}", sub.description]
|
|
141
|
+
end
|
|
142
|
+
end
|
|
134
143
|
|
|
135
|
-
|
|
144
|
+
def self.help(shell, subcommand = false)
|
|
136
145
|
sections = HELP_SECTIONS.map { |title, names| [title, names.dup] }
|
|
137
|
-
|
|
146
|
+
known = HELP_SECTIONS.flat_map { |_, names| names.map { |n| n.tr("-", "_") } }
|
|
147
|
+
leftovers = all_commands.reject { |_, c| c.hidden? }.keys - known
|
|
138
148
|
sections.last[1].concat(leftovers.map { |n| n.tr("_", "-") })
|
|
139
149
|
|
|
140
|
-
sections.
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
150
|
+
rendered = sections.map { |title, names| [title, names.flat_map { |n| help_rows_for(n) }] }
|
|
151
|
+
width = rendered.flat_map { |_, rows| rows.map { |usage, _| usage.length } }.max + 4
|
|
152
|
+
|
|
153
|
+
say_header = ->(text) { shell.say shell.set_color(text, :cyan, true) }
|
|
154
|
+
|
|
155
|
+
shell.say ""
|
|
156
|
+
shell.say shell.set_color("LocalVault", :cyan, true) + " — encrypted local secrets vault with MCP support for AI agents"
|
|
157
|
+
shell.say " https://inventlist.com/tools/localvault"
|
|
158
|
+
|
|
159
|
+
rendered.each do |title, rows|
|
|
147
160
|
next if rows.empty?
|
|
148
161
|
shell.say ""
|
|
149
|
-
|
|
150
|
-
rows.each
|
|
162
|
+
say_header.call(title)
|
|
163
|
+
rows.each do |usage, desc|
|
|
164
|
+
shell.say " localvault #{shell.set_color(usage.ljust(width), :green)}#{desc}"
|
|
165
|
+
end
|
|
151
166
|
end
|
|
152
167
|
|
|
153
168
|
shell.say ""
|
|
154
|
-
|
|
169
|
+
say_header.call("SAFE SECRET INPUT (preferred over passing values as arguments)")
|
|
155
170
|
shell.say " printf '%s' \"$SECRET\" | localvault set KEY --stdin"
|
|
156
171
|
shell.say ""
|
|
157
|
-
|
|
172
|
+
say_header.call("PROJECTS (dot-notation groups inside one vault)")
|
|
158
173
|
shell.say " localvault set platepose.API_KEY v Store a key in the 'platepose' group"
|
|
159
174
|
shell.say " Filter any command with -p: show -p platepose, exec -p platepose -- CMD"
|
|
160
175
|
shell.say " Delete a whole group: localvault delete 'platepose.*'"
|
|
161
176
|
shell.say ""
|
|
162
|
-
|
|
177
|
+
say_header.call("USING SECRETS WITH ANY CLI")
|
|
163
178
|
shell.say " localvault exec -- inventlist ships list"
|
|
164
179
|
shell.say " localvault exec -- curl -H \"Authorization: Bearer $API_KEY\" ..."
|
|
165
180
|
shell.say ""
|
|
@@ -305,15 +320,38 @@ module LocalVault
|
|
|
305
320
|
vault.list.each { |key| $stdout.puts key }
|
|
306
321
|
end
|
|
307
322
|
|
|
308
|
-
desc "groups [QUERY]", "List or search
|
|
323
|
+
desc "groups [QUERY]", "List or search secret groups / projects without revealing values"
|
|
309
324
|
long_desc <<~DESC
|
|
310
|
-
Discover
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
325
|
+
Discover the groups in a vault. "Group" and "project" are the same
|
|
326
|
+
thing: a named bucket of keys inside one vault. You never create one
|
|
327
|
+
explicitly — storing a key in it creates it, deleting its last key
|
|
328
|
+
removes it.
|
|
329
|
+
|
|
330
|
+
CREATE by storing keys into a group (three equivalent spellings):
|
|
331
|
+
\x05 localvault set kuickr.API_KEY abc123 # dot-notation
|
|
332
|
+
\x05 localvault set --group kuickr API_KEY abc123
|
|
333
|
+
\x05 localvault set -g kuickr API_KEY abc123
|
|
334
|
+
|
|
335
|
+
LIST groups (names and key counts only — values stay hidden):
|
|
336
|
+
\x05 localvault groups # all groups in the default vault
|
|
337
|
+
\x05 localvault groups stock # only groups matching "stock"
|
|
338
|
+
\x05 localvault groups -v intellectaco # groups in another vault
|
|
339
|
+
|
|
340
|
+
WORK WITH one group (any command takes -p / --project):
|
|
341
|
+
\x05 localvault show -p kuickr # see its keys (masked)
|
|
342
|
+
\x05 localvault list -p kuickr # just the key names
|
|
343
|
+
\x05 localvault exec -p kuickr -- rails s # inject only its keys as env vars
|
|
344
|
+
\x05 localvault env -p kuickr # export only its keys
|
|
345
|
+
\x05 localvault import .env -p kuickr # import a .env file into the group
|
|
346
|
+
|
|
347
|
+
DELETE one key or the whole group:
|
|
348
|
+
\x05 localvault delete kuickr.API_KEY
|
|
349
|
+
\x05 localvault delete 'kuickr.*'
|
|
350
|
+
|
|
351
|
+
`localvault projects` is an alias for this command.
|
|
316
352
|
DESC
|
|
353
|
+
map "projects" => "groups"
|
|
354
|
+
|
|
317
355
|
def groups(query = nil)
|
|
318
356
|
vault = open_vault!
|
|
319
357
|
matches = GroupCatalog.new(vault.all).search(query)
|
data/lib/localvault/version.rb
CHANGED