Skip to content

feat: add config show command for active config inspection#94

Merged
jy-tan merged 5 commits intomainfrom
show-config
Mar 31, 2026
Merged

feat: add config show command for active config inspection#94
jy-tan merged 5 commits intomainfrom
show-config

Conversation

@jy-tan
Copy link
Copy Markdown
Contributor

@jy-tan jy-tan commented Mar 29, 2026

Summary

Add a fence config show subcommand that lets developers inspect the exact config Fence would use, including auto-discovery and inheritance, without running a sandboxed command. This makes repo-local fence.json, @base, and template-based setups easier to audit while keeping the resolved config machine-readable.

Resolves #65.

Changes

  • Add fence config show as a no-exec inspection path for default config discovery, --settings, and --template
  • Print the config resolution chain as a compact tree on stderr and the fully resolved config as plain JSON on stdout
  • Reuse the same config-loading and extends-resolution flow as normal execution so inspection matches runtime behavior
  • Add resolver trace metadata (ResolutionTrace / ResolutionStep) so the CLI can render where each inherited layer came from
  • Make MarshalConfigJSON() include previously omitted non-empty fields such as devices and command.acceptSharedBinaryCannotRuntimeDeny, while still keeping generated starter configs compact
  • Refactor fence config init into its own command file without changing the default generated config output
  • Add tests for project-config + @base resolution, stdout/stderr separation, compact chain formatting, and config renderer completeness
  • Clean up code template to remove duplication and add regression tests

Developer Experience

Fence now supports these inspection flows:

  • fence config show
  • fence config show --settings ./custom.json
  • fence config show --template code
  • fence config show | jq '.network'

When fence config show is present, Fence does not run a command. Instead, it writes a human-readable resolution chain to stderr, leaves a blank line for readability, and writes the fully resolved config JSON to stdout.

Example shape:

stderr

Active config chain:
project config: /path/to/repo/fence.json
└── @base user config: /Users/alice/.config/fence/fence.json
    └── builtin template: code

stdout (excerpt, the actual output will contain all non-empty resolved fields from the effective config)

{
  "allowPty": true,
  "network": {
    "allowLocalBinding": true,
    "allowLocalOutbound": true,
    "allowedDomains": [
      "api.openai.com",
      "*.anthropic.com",
      "github.com",
      "repo.example.com"
      // ...
    ],
    "deniedDomains": [
      "169.254.169.254"
      // ...
    ]
  },
  "filesystem": {
    "allowWrite": [
      ".",
      "/tmp"
      // ...
    ]
  },
  // ...
}

Additional Notes

This change does not alter the default fence config init developer experience. A normal init still produces compact starter JSON such as { "extends": "code" }, and empty sections remain omitted. The renderer change only affects cases where fields like devices or command.acceptSharedBinaryCannotRuntimeDeny are actually set and should appear in resolved/shared JSON output.

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 9 files

@jy-tan jy-tan requested a review from dwt March 29, 2026 20:47
@dwt
Copy link
Copy Markdown
Collaborator

dwt commented Mar 30, 2026

I have thought about wether this might best live as fence config show or fence config --show to separate commands working with the config from the rest and we do not need a special mode where the command is ignored (which is not needed for this command anyway, but might not be clear from the command line). Hm... This would need additional flags as fence config show --settings path/to/file needs to work.

This has the disadvantage that this command is not advertised with fence --help - but perhaps that is solvable.

Regarding the output format, I think it's important to list the absolute paths to all the files that get included in the config - bonus points if we can have a --verbose mode that can show for each entry which config file it came from. (but that is much harder and probably not what we should start with).

@dwt
Copy link
Copy Markdown
Collaborator

dwt commented Mar 30, 2026

I would like to have this more compact to make it clearer what is what, perhaps something along the line of

Active config chain:
local file: /path/to/repo/fence.json
└── @base file: /Users/alice/.config/fence/fence.json
        └── builtin template: code

@dwt
Copy link
Copy Markdown
Collaborator

dwt commented Mar 30, 2026

This merging might also be really good for fence --landlock-init and the future fence --linux-bootstrap as we could hand in the already merged config via FENCE_CONFIG_JSON which could simplify the code inside the sandbox (e.g. it would not need access to all config files and be able to resolve them).

Copy link
Copy Markdown
Collaborator

@dwt dwt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See comments above

@jy-tan jy-tan changed the title feat: add --show config inspection feat: add config show command for active config inspection Mar 30, 2026
@jy-tan jy-tan changed the title feat: add config show command for active config inspection feat: add config show command for active config inspection Mar 30, 2026
@jy-tan
Copy link
Copy Markdown
Contributor Author

jy-tan commented Mar 30, 2026

@dwt Good suggestions, applied a number of them:

  • Using fence config show subcommand
  • Mentioning fence config show in fence --help
  • Make the config chain more compact

We can do these in a future PR:

  • Reusing the same resolved config pipeline for internal landlock/linux wrappers
  • --verbose mode to attributing each config entry to config file (this is more complex and lower priority)

@jy-tan jy-tan requested a review from dwt March 30, 2026 21:04
@dwt
Copy link
Copy Markdown
Collaborator

dwt commented Mar 31, 2026

Looking at the output, I like the compact representation of included config files

❯ ./fence config show
Active config chain:
local file: /Users/dwt/.config/fence/fence.json
└── builtin template: code

nit: I was a bit surprised by the user wide config being referred to as 'local file'.

Looking at the merged config: that's a great first step.

Something for later: I would really like if we could switch to a configuration loader that is able to preserve comments when merging.

@dwt
Copy link
Copy Markdown
Collaborator

dwt commented Mar 31, 2026

Looking at a merged config, I noticed this:

      "*.key",
      "*.pem",
      "*.p12",
      "*.pfx",
      "**/*.key",
      "**/*.pem",
      "**/*.p12",
      "**/*.pfx"

that duplication seems like a footgun. We should either document very clearly why this is required or make it so that

      "**/*.key",
      "**/*.pem",
      "**/*.p12",
      "**/*.pfx"

generates both patterns, i.e. also blocks in the current directory (and then document that).

@jy-tan
Copy link
Copy Markdown
Contributor Author

jy-tan commented Mar 31, 2026

@dwt The duplication was on code.json, I removed it and added tests to ensure no regressions.

Also updated the output to use clearer labels:

  • project config: ... for auto-discovered repo configs
  • user config: ... for the default user config fallback
  • settings file: ... for explicit --settings

Copy link
Copy Markdown
Collaborator

@dwt dwt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! I really like it!

@jy-tan jy-tan merged commit d5bce6a into main Mar 31, 2026
6 checks passed
@jy-tan jy-tan deleted the show-config branch March 31, 2026 19:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

support --show-template or --show-config to allow inspecting the succinct config form of the active config

2 participants