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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1f7a9ef056579778ef2dabd22148af8fe8fbd19b2e0b4aefafde3c9eb6a454ee
4
- data.tar.gz: e5006419cb47849c63a7f4c123ba661e6c95bd2f93fe8ef3230faff2ab5fe7ec
3
+ metadata.gz: 6ffea91e8b5b758be685a82b78154018889db3b8ece76a942f10879fe79e19d8
4
+ data.tar.gz: 4b43e48d4913b88dffcb0ce18ddb819dd9470edde959cde7b8d4c50e86294e3d
5
5
  SHA512:
6
- metadata.gz: 9cfc5a0d2635e86601077c1600f58339252262960663d39e45213ff59aeca09ec47c8a8e392e2ad16a0d4e7b2731b500b33d268c239e44b2567ea2b09cd51ef0
7
- data.tar.gz: 8a14b7b627c493f710c89738c0726f2cc4bca895996a76fcfca4801ff46aaf5047f27a7480aec157b876e807c757f0b3cb9dd3e9bfbe0ffe9d3313ce7dcfe5f8
6
+ metadata.gz: 73c0bb42f97afff36f09cce9a66e6ea9f37d8a25c8609a424f9c190cdaa3abc0dd6fb70765bdd2c4f0d5d113812a36f8a645dd557b4914c3620b48c5838b62d7
7
+ data.tar.gz: 5766f8a512cebf5be3ceb4778f72fa2f5cf591b098e435d3a4cfa623912016c07bb8a3073f557ae4bf5764845802584750cc2434d472907474e81ac9bfdada27
@@ -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
@@ -124,42 +124,57 @@ module LocalVault
124
124
  ["OTHER", %w[logout version doctor help]]
125
125
  ].freeze
126
126
 
127
- def self.help(shell, subcommand = false)
128
- visible = all_commands.reject { |_, c| c.hidden? }
129
- width = visible.values.map { |c| c.usage.length }.max + 4
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
- shell.say ""
132
- shell.say "LocalVault encrypted local secrets vault with MCP support for AI agents"
133
- shell.say " https://inventlist.com/tools/localvault"
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
- listed = []
144
+ def self.help(shell, subcommand = false)
136
145
  sections = HELP_SECTIONS.map { |title, names| [title, names.dup] }
137
- leftovers = visible.keys - HELP_SECTIONS.flat_map { |_, names| names.map { |n| n.tr("-", "_") } }
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.each do |title, names|
141
- rows = names.filter_map do |name|
142
- command = visible[name.tr("-", "_")]
143
- next unless command
144
- listed << name
145
- " localvault #{command.usage.ljust(width)}#{command.description}"
146
- end
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
- shell.say title
150
- rows.each { |row| shell.say row }
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
- shell.say "SAFE SECRET INPUT (preferred over passing values as arguments)"
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
- shell.say "PROJECTS (dot-notation groups inside one vault)"
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
- shell.say "USING SECRETS WITH ANY CLI"
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 stored secret groups without revealing values"
323
+ desc "groups [QUERY]", "List or search secret groups / projects without revealing values"
309
324
  long_desc <<~DESC
310
- Discover dot-notation namespaces and flat-key prefix groups.
311
-
312
- \x05 localvault groups
313
- \x05 localvault groups str
314
- \x05 localvault show --group STRIPE
315
- \x05 localvault set --group STRIPE API_KEY VALUE
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)
@@ -1,3 +1,3 @@
1
1
  module LocalVault
2
- VERSION = "1.11.2"
2
+ VERSION = "1.12.0"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: localvault
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.11.2
4
+ version: 1.12.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nauman Tariq