@@ -7,18 +7,27 @@ import (
77 "github.com/rs/zerolog/log"
88 "github.com/spf13/cobra"
99
10+ "go.dot.industries/vx/internal/config"
1011 "go.dot.industries/vx/internal/resolver"
1112)
1213
14+ var flagFormat string
15+
1316func init () {
17+ listCmd .Flags ().StringVar (& flagFormat , "format" , "table" , "output format: table, dotenv" )
1418 rootCmd .AddCommand (listCmd )
1519}
1620
1721var listCmd = & cobra.Command {
1822 Use : "list" ,
1923 Short : "List secrets that would be resolved for the current context" ,
20- Long : `Shows all secret mappings for the current environment and workspace
21- without actually fetching them from Vault. Useful for debugging configuration.` ,
24+ Long : `Shows all secret mappings for the current environment and workspace.
25+
26+ The default "table" format shows Vault paths without fetching values.
27+ Use --format=dotenv to resolve secrets from Vault and output KEY=VALUE pairs
28+ suitable for piping to a .env file:
29+
30+ vx list --format=dotenv > .env.docker` ,
2231 Args : cobra .NoArgs ,
2332 RunE : runList ,
2433}
@@ -48,6 +57,18 @@ func runList(cmd *cobra.Command, args []string) error {
4857 Int ("defaults" , len (merged .Defaults )).
4958 Msg ("resolved config" )
5059
60+ switch flagFormat {
61+ case "table" :
62+ return printTable (merged , env , workspace )
63+ case "dotenv" :
64+ return printDotenv (cfg , merged )
65+ default :
66+ return fmt .Errorf ("unsupported format %q (use table or dotenv)" , flagFormat )
67+ }
68+ }
69+
70+ // printTable shows the human-readable mapping table (no Vault fetch).
71+ func printTable (merged * config.MergedConfig , env string , workspace string ) error {
5172 fmt .Printf ("Environment: %s\n " , env )
5273 if workspace != "" {
5374 fmt .Printf ("Workspace: %s\n " , workspace )
@@ -77,6 +98,35 @@ func runList(cmd *cobra.Command, args []string) error {
7798 return nil
7899}
79100
101+ // printDotenv resolves secrets from Vault and outputs KEY=VALUE lines.
102+ func printDotenv (cfg * config.RootConfig , merged * config.MergedConfig ) error {
103+ vaultClient , err := authenticatedClient (cfg , merged .Environment )
104+ if err != nil {
105+ return err
106+ }
107+
108+ secrets , err := resolveSecrets (vaultClient , merged )
109+ if err != nil {
110+ return err
111+ }
112+
113+ // Merge: defaults first, secrets override.
114+ all := make (map [string ]string , len (merged .Defaults )+ len (secrets ))
115+ for k , v := range merged .Defaults {
116+ all [k ] = v
117+ }
118+ for k , v := range secrets {
119+ all [k ] = v
120+ }
121+
122+ names := sortedKeys (all )
123+ for _ , name := range names {
124+ fmt .Printf ("%s=%s\n " , name , all [name ])
125+ }
126+
127+ return nil
128+ }
129+
80130func sortedKeys (m map [string ]string ) []string {
81131 keys := make ([]string , 0 , len (m ))
82132 for k := range m {
0 commit comments