localvault 1.12.0 → 1.12.2

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: 6ffea91e8b5b758be685a82b78154018889db3b8ece76a942f10879fe79e19d8
4
- data.tar.gz: 4b43e48d4913b88dffcb0ce18ddb819dd9470edde959cde7b8d4c50e86294e3d
3
+ metadata.gz: 02acc26385f42007abd7ba033716d5755f8a7c147a2f81a022ac839508cc4909
4
+ data.tar.gz: 84b8ac3eda467e9df18a8befa60eff2879b2ff838a23d45cee3b65cf72134e96
5
5
  SHA512:
6
- metadata.gz: 73c0bb42f97afff36f09cce9a66e6ea9f37d8a25c8609a424f9c190cdaa3abc0dd6fb70765bdd2c4f0d5d113812a36f8a645dd557b4914c3620b48c5838b62d7
7
- data.tar.gz: 5766f8a512cebf5be3ceb4778f72fa2f5cf591b098e435d3a4cfa623912016c07bb8a3073f557ae4bf5764845802584750cc2434d472907474e81ac9bfdada27
6
+ metadata.gz: 162ac0715abff981feeb7b8f2209c98e50d73c2e7061270fbc399075405ab8aed4fc4cd987d9a9286275e5b0c667b0e0793b8bddf74e969bbc069d5ce9fe7e94
7
+ data.tar.gz: 1ea2253c3bf76d5f272583a8f86107b0c15c6dd1f39c68f2f44530749da2f659ae642e4294b23ff25f89fcb12204968e6e5b5736afbeb170e45390b1055363f5
data/bin/lv ADDED
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Support both development (require_relative) and installed (load path) usage
4
+ begin
5
+ require_relative "../lib/localvault"
6
+ require_relative "../lib/localvault/cli"
7
+ rescue LoadError
8
+ require "localvault"
9
+ require "localvault/cli"
10
+ end
11
+
12
+ status = LocalVault::CLI.start(ARGV)
13
+ exit(status) if status.is_a?(Integer) && !status.zero?
@@ -0,0 +1,84 @@
1
+ require "thor"
2
+
3
+ module LocalVault
4
+ class CLI
5
+ # Colors every help surface — the main screen, `help COMMAND`, and
6
+ # subcommand namespaces — by hooking the shell Thor already routes all
7
+ # help output through, rather than colorizing at each call site.
8
+ #
9
+ # Thor disables color itself when stdout is not a TTY, so piped output
10
+ # stays plain.
11
+ class HelpShell < Thor::Shell::Color
12
+ # "Usage:", "Options:", "Description:", "Runtime options:"
13
+ LABEL = /\A([A-Z][A-Za-z ]*:)\s*\z/
14
+ # A leading run of caps: "GETTING STARTED", "NESTED KEY (dot-notation)"
15
+ HEADING = /\A(\s*)([A-Z][A-Z0-9'\/\-]*(?: [A-Z0-9'\/\-]+)*)(?=\z|[\s(:])/
16
+
17
+ def say(message = "", color = nil, force_new_line = (message.to_s !~ /( |\t)\Z/))
18
+ if color.nil? && message.is_a?(String)
19
+ message = message.lines.map { |line| decorate(line.chomp) }.join("\n")
20
+ end
21
+ super
22
+ end
23
+
24
+ # Thor word-wraps long descriptions, which collapses the alignment of
25
+ # example blocks (`localvault set K V # comment` loses its spacing).
26
+ # Lines flagged with \x05 — Thor's no-wrap marker, which every example in
27
+ # our long_desc blocks already carries — are printed verbatim instead, so
28
+ # examples stay aligned while prose still wraps to the terminal.
29
+ def print_wrapped(message, options = {})
30
+ indent = options[:indent] || 0
31
+ prose = []
32
+
33
+ message.to_s.lines.each do |line|
34
+ line = line.chomp
35
+ if line.lstrip.start_with?("\x05")
36
+ wrap_prose(prose, options)
37
+ stdout.puts("#{" " * indent}#{decorate(line.sub("\x05", ''))}")
38
+ elsif line.strip.empty?
39
+ wrap_prose(prose, options)
40
+ stdout.puts
41
+ else
42
+ prose << line
43
+ end
44
+ end
45
+
46
+ wrap_prose(prose, options)
47
+ end
48
+
49
+ # Option tables: green the flag column ("-v, [--vault=VAULT]").
50
+ def print_table(array, options = {})
51
+ array = array.map do |row|
52
+ first, *rest = row
53
+ first.is_a?(String) && first.strip.start_with?("-") ? [set_color(first, :green), *rest] : row
54
+ end
55
+ super
56
+ end
57
+
58
+ private
59
+
60
+ # Hand a run of prose lines back to Thor's wrapper, then reset the buffer.
61
+ def wrap_prose(lines, options)
62
+ return if lines.empty?
63
+ text = lines.join("\n")
64
+ lines.clear
65
+ return if text.strip.empty?
66
+ Thor::Shell::Basic.instance_method(:print_wrapped)
67
+ .bind_call(self, text.lines.map { |l| decorate(l.chomp) }.join("\n"), options)
68
+ end
69
+
70
+ def decorate(line)
71
+ return line unless can_display_colors?
72
+
73
+ if (match = LABEL.match(line))
74
+ return line.sub(match[1], set_color(match[1], :cyan, true))
75
+ end
76
+
77
+ match = HEADING.match(line)
78
+ return line unless match && match[2].length >= 4
79
+
80
+ "#{match[1]}#{set_color(match[2], :cyan, true)}#{line[(match[1].length + match[2].length)..]}"
81
+ end
82
+ end
83
+ end
84
+ end
@@ -66,7 +66,9 @@ module LocalVault
66
66
 
67
67
  def self.start(given_args = ARGV, config = {})
68
68
  require_relative "cli/error_presenter"
69
- config[:shell] ||= Thor::Base.shell.new
69
+ require_relative "cli/help_shell"
70
+ Thor::Base.shell = HelpShell # subcommand namespaces build their own shells
71
+ config[:shell] ||= HelpShell.new
70
72
  result = dispatch(nil, normalize_legacy_group_option(given_args.dup), nil, config)
71
73
  result.is_a?(CommandStatus) ? result.code : 0
72
74
  rescue Thor::Error => error
@@ -150,8 +152,6 @@ module LocalVault
150
152
  rendered = sections.map { |title, names| [title, names.flat_map { |n| help_rows_for(n) }] }
151
153
  width = rendered.flat_map { |_, rows| rows.map { |usage, _| usage.length } }.max + 4
152
154
 
153
- say_header = ->(text) { shell.say shell.set_color(text, :cyan, true) }
154
-
155
155
  shell.say ""
156
156
  shell.say shell.set_color("LocalVault", :cyan, true) + " — encrypted local secrets vault with MCP support for AI agents"
157
157
  shell.say " https://inventlist.com/tools/localvault"
@@ -159,22 +159,22 @@ module LocalVault
159
159
  rendered.each do |title, rows|
160
160
  next if rows.empty?
161
161
  shell.say ""
162
- say_header.call(title)
162
+ shell.say title
163
163
  rows.each do |usage, desc|
164
164
  shell.say " localvault #{shell.set_color(usage.ljust(width), :green)}#{desc}"
165
165
  end
166
166
  end
167
167
 
168
168
  shell.say ""
169
- say_header.call("SAFE SECRET INPUT (preferred over passing values as arguments)")
169
+ shell.say("SAFE SECRET INPUT (preferred over passing values as arguments)")
170
170
  shell.say " printf '%s' \"$SECRET\" | localvault set KEY --stdin"
171
171
  shell.say ""
172
- say_header.call("PROJECTS (dot-notation groups inside one vault)")
172
+ shell.say("PROJECTS (dot-notation groups inside one vault)")
173
173
  shell.say " localvault set platepose.API_KEY v Store a key in the 'platepose' group"
174
174
  shell.say " Filter any command with -p: show -p platepose, exec -p platepose -- CMD"
175
175
  shell.say " Delete a whole group: localvault delete 'platepose.*'"
176
176
  shell.say ""
177
- say_header.call("USING SECRETS WITH ANY CLI")
177
+ shell.say("USING SECRETS WITH ANY CLI")
178
178
  shell.say " localvault exec -- inventlist ships list"
179
179
  shell.say " localvault exec -- curl -H \"Authorization: Bearer $API_KEY\" ..."
180
180
  shell.say ""
@@ -785,6 +785,14 @@ module LocalVault
785
785
  require_relative "cli/guard"
786
786
  require_relative "cli/identity_cmd"
787
787
 
788
+ # Thor 1.5 injects a `tree` command into every class. Inside a namespace it
789
+ # lists under a name that isn't even callable (`identity_command tree`), and
790
+ # at top level it prints a raw class path as the root. Our grouped help
791
+ # covers the same ground properly, so drop it everywhere.
792
+ [self, Guard, Keys, Team, Sync, IdentityCommand].each do |namespace|
793
+ namespace.remove_command(:tree) if namespace.all_commands.key?("tree")
794
+ end
795
+
788
796
  register(Guard, "guard", "guard SUBCOMMAND", "Block plaintext secrets in agent tool traffic (Claude Code hooks)")
789
797
  register(IdentityCommand, "identity", "identity SUBCOMMAND", "Show or set your local identity (alias, handle, public key)")
790
798
  register(Keys, "keys", "keys SUBCOMMAND", "Manage your X25519 keypair for vault sharing")
@@ -1,3 +1,3 @@
1
1
  module LocalVault
2
- VERSION = "1.12.0"
2
+ VERSION = "1.12.2"
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.12.0
4
+ version: 1.12.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nauman Tariq
@@ -99,17 +99,20 @@ email:
99
99
  - nauman@intellecta.co
100
100
  executables:
101
101
  - localvault
102
+ - lv
102
103
  extensions: []
103
104
  extra_rdoc_files: []
104
105
  files:
105
106
  - LICENSE
106
107
  - README.md
107
108
  - bin/localvault
109
+ - bin/lv
108
110
  - lib/localvault.rb
109
111
  - lib/localvault/api_client.rb
110
112
  - lib/localvault/cli.rb
111
113
  - lib/localvault/cli/error_presenter.rb
112
114
  - lib/localvault/cli/guard.rb
115
+ - lib/localvault/cli/help_shell.rb
113
116
  - lib/localvault/cli/identity_cmd.rb
114
117
  - lib/localvault/cli/keys.rb
115
118
  - lib/localvault/cli/sync.rb