Skip to content

feat: major cleanup — remove dashboard, semantic CLI, banner, API management, uninstall, more tools#27

Merged
root-Manas merged 3 commits intomainfrom
copilot/cleanup-repo-configuration
Apr 12, 2026
Merged

feat: major cleanup — remove dashboard, semantic CLI, banner, API management, uninstall, more tools#27
root-Manas merged 3 commits intomainfrom
copilot/cleanup-repo-configuration

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 12, 2026

Summary

Complete overhaul of macaron as described in the issue. All changes build and all tests pass.


Changes

Removed

  • Dashboard entirely deletedinternal/ui/ (server.go + HTML assets), serve command, all related flags and references

CLI / UX

  • CLI banner — new internal/cliui/banner.go with ASCII art, NO_COLOR support, and Info/OK/Warn/Err color helpers
  • Semantic subcommand interface — replaced cryptic 3-letter flag codes (-scn, -sts, -res, -sak, etc.) with clear subcommands and readable flags:
    • macaron scan -t <domain> -p <profile> --stages ...
    • macaron status, results, setup, export, config, guide, version
    • macaron api list|set|unset|import|bulk
    • macaron uninstall
  • macaron uninstall — locates binary via os.Executable(), removes it from PATH, optionally removes storage directory (with confirmation prompt or --yes flag)
  • No tech-stack mentions anywhere in CLI output (removed Go version, SQLite references, "macaronV2" branding)

API Management

  • Global key store shared across all tools macaron runs — no per-tool config needed
  • macaron api set key=value [key=value ...] — set one or more keys
  • macaron api unset key [key ...] — remove keys
  • macaron api list — show masked keys
  • macaron api import — pull keys from installed tool configs (subfinder ~/.config/subfinder/provider-config.yaml, amass config)
  • macaron api bulk -f keys.yaml — load many keys at once from a YAML file
  • When macaron runs subfinder, keys are injected via a temporary provider-config.yaml — user's own subfinder config is never modified

Pipeline improvements

  • More tools — catalog expanded from 10 → 16: amass, gospider, hakrawler, ffuf, gobuster, feroxbuster added
  • Port scanning — naabu-backed when installed (1000 ports), with native TCP-dial fallback on failure (with warning)
  • URL discovery — Wayback CDX + gau + katana all run when available (per-host)
  • Subdomain stage — amass added alongside subfinder/assetfinder/findomain
  • Tool inventory table shows role for each tool

Documentation

  • README completely rewritten — researcher-oriented language, no tech-stack mentions, tables for pipeline stages / tools / flags, API management section, install instructions

Testing

  • All existing tests updated to cover new API
  • New tests: TestApplyProfileBalanced, TestLooksLikeDomain, TestMacaronHomeOverride
  • go build ./... and go test ./... pass cleanly
  • CodeQL scan: 0 alerts

Copilot AI and others added 3 commits April 12, 2026 15:39
…t, uninstall, more tools, new README

Agent-Logs-Url: https://github.com/root-Manas/macaron/sessions/bd43ae69-d546-45ff-aed6-3450bdddd865

Co-authored-by: root-Manas <97402139+root-Manas@users.noreply.github.com>
…n validation, append bug, comments

Agent-Logs-Url: https://github.com/root-Manas/macaron/sessions/bd43ae69-d546-45ff-aed6-3450bdddd865

Co-authored-by: root-Manas <97402139+root-Manas@users.noreply.github.com>
… buffer constant, recursive flattenAPIKeys comment, uppercase TLD support

Agent-Logs-Url: https://github.com/root-Manas/macaron/sessions/bd43ae69-d546-45ff-aed6-3450bdddd865

Co-authored-by: root-Manas <97402139+root-Manas@users.noreply.github.com>
@root-Manas root-Manas marked this pull request as ready for review April 12, 2026 15:48
Copilot AI review requested due to automatic review settings April 12, 2026 15:48
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR is a major CLI- and pipeline-focused overhaul of macaron, removing the web dashboard/UI and replacing legacy flags with semantic subcommands while expanding tool support and introducing global API key management.

Changes:

  • Removes the dashboard (internal/ui) and related CLI surface area.
  • Reworks the CLI into subcommands (scan/status/results/setup/export/config/api/uninstall) with a new banner + output helpers.
  • Expands pipeline/tooling (e.g., amass subdomains, naabu ports, gau/katana URLs) and adds API key import/bulk management with subfinder key injection.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
README.md Rewritten usage docs reflecting new subcommand-based CLI and pipeline/tool inventory.
internal/ui/server.go Deletes the dashboard server implementation.
internal/ui/assets/index.html Deletes dashboard frontend assets.
internal/engine/engine.go Adds amass, naabu port scanning, gau/katana URL discovery, and subfinder API key injection.
internal/cliui/banner.go Adds CLI banner + colored Info/OK/Warn/Err helpers with NO_COLOR support.
internal/cfg/config.go Adds bulk load + import helpers for API keys and subfinder provider-config generation.
internal/app/app.go Expands tool catalog/tool inventory output and updates status/setup rendering.
cmd/macaron/main.go Replaces legacy flags with a subcommand dispatcher; adds api + uninstall flows.
cmd/macaron/main_test.go Removes legacy arg-normalization tests; adds tests for profiles/domain detection/home override.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread internal/cfg/config.go
@@ -46,6 +50,7 @@ func Save(storageRoot string, cfg *Config) error {
return os.WriteFile(filepath.Join(storageRoot, "config.yaml"), b, 0o644)
Copy link

Copilot AI Apr 12, 2026

Choose a reason for hiding this comment

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

Save writes config.yaml with mode 0644, but this file contains API keys/secrets. This makes keys readable by other users on the system. Use a restrictive permission (e.g., 0600) when writing the config file (and ideally preserve permissions on updates).

Suggested change
return os.WriteFile(filepath.Join(storageRoot, "config.yaml"), b, 0o644)
path := filepath.Join(storageRoot, "config.yaml")
mode := os.FileMode(0o600)
if info, err := os.Stat(path); err == nil {
mode = info.Mode().Perm()
} else if !os.IsNotExist(err) {
return err
}
return os.WriteFile(path, b, mode)

Copilot uses AI. Check for mistakes.
Comment thread internal/cfg/config.go
Comment on lines +254 to +266
for _, candidate := range []string{
filepath.Join(home, ".config", "amass", "config.yaml"),
filepath.Join(home, ".config", "amass", "config.ini"),
} {
b, err := os.ReadFile(candidate)
if err != nil {
continue
}
// Best-effort: look for api_key or apikey patterns.
var raw map[string]any
if err := yaml.Unmarshal(b, &raw); err != nil {
continue
}
Copy link

Copilot AI Apr 12, 2026

Choose a reason for hiding this comment

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

readAmassConfig attempts to parse ~/.config/amass/config.ini via yaml.Unmarshal, which will fail for INI format and silently skip importing keys from that file. Either parse INI properly (if you want to support it) or remove the .ini candidate to avoid a non-functional import path.

Copilot uses AI. Check for mistakes.
Comment thread internal/cfg/config.go
Comment on lines +89 to +95
for k, v := range bulk.APIKeys {
k = strings.ToLower(strings.TrimSpace(k))
if k != "" && strings.TrimSpace(v) != "" {
cfg.APIKeys[k] = strings.TrimSpace(v)
}
}
return len(bulk.APIKeys), nil
Copy link

Copilot AI Apr 12, 2026

Choose a reason for hiding this comment

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

BulkLoadFile returns len(bulk.APIKeys) even though empty/whitespace values are skipped during merge. This can report that N keys were loaded when fewer were actually applied. Consider counting only the keys that are actually inserted/updated in cfg.APIKeys and returning that count.

Suggested change
for k, v := range bulk.APIKeys {
k = strings.ToLower(strings.TrimSpace(k))
if k != "" && strings.TrimSpace(v) != "" {
cfg.APIKeys[k] = strings.TrimSpace(v)
}
}
return len(bulk.APIKeys), nil
count := 0
for k, v := range bulk.APIKeys {
k = strings.ToLower(strings.TrimSpace(k))
v = strings.TrimSpace(v)
if k != "" && v != "" {
cfg.APIKeys[k] = v
count++
}
}
return count, nil

Copilot uses AI. Check for mistakes.
Comment thread internal/engine/engine.go
Comment on lines +275 to +322
// writeSubfinderProviderConfig creates a temporary provider-config.yaml with
// macaron's API keys so subfinder uses them without changing the user's own
// subfinder config. Returns the temp file path, or "" if nothing to write.
// The caller is responsible for removing the returned file when done.
func writeSubfinderProviderConfig(apiKeys map[string]string) string {
if len(apiKeys) == 0 {
return ""
}
// macaron key name → subfinder provider name
mapping := map[string]string{
"securitytrails": "securitytrails",
"virustotal": "virustotal",
"shodan": "shodan",
"binaryedge": "binaryedge",
"c99": "c99",
"chaos": "chaos",
"hunter": "hunter",
"intelx": "intelx",
"urlscan": "urlscan",
"zoomeye": "zoomeye",
"fullhunt": "fullhunt",
"github": "github",
"leakix": "leakix",
"netlas": "netlas",
"quake": "quake",
}
providers := make(map[string][]string)
for macaronKey, providerName := range mapping {
v, ok := apiKeys[macaronKey]
if !ok || strings.TrimSpace(v) == "" {
continue
}
providers[providerName] = append(providers[providerName], v)
}
if len(providers) == 0 {
return ""
}
tmp, err := os.CreateTemp("", "macaron_sfprov_*.yaml")
if err != nil {
return ""
}
// Write YAML manually — keep it simple.
for provider, keys := range providers {
fmt.Fprintf(tmp, "%s:\n", provider)
for _, k := range keys {
fmt.Fprintf(tmp, " - %s\n", k)
}
}
Copy link

Copilot AI Apr 12, 2026

Choose a reason for hiding this comment

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

writeSubfinderProviderConfig writes YAML manually and emits raw key strings without quoting/escaping. API keys often contain characters that can break YAML (e.g., :, #, leading/trailing spaces), which would make subfinder fail to read the provider config. Prefer generating the YAML via yaml.Marshal (or reuse the existing provider-config writer in internal/cfg) so values are correctly escaped and the provider mapping logic lives in one place.

Copilot uses AI. Check for mistakes.
Comment thread cmd/macaron/main.go
Comment on lines +76 to 105
func runScan(args []string) int {
fs := pflag.NewFlagSet("scan", pflag.ContinueOnError)
var (
scanTargets []string
status bool
results bool
listTools bool
export bool
configCmd bool
pipeline bool
serve bool
filePath string
useStdin bool
domain string
scanID string
what string
mode string
fast bool
narrow bool
rate int
threads int
limit int
output string
quiet bool
showVersion bool
serveAddr string
storagePath string
stages string
setAPI []string
showAPI bool
setup bool
installTools bool
profile string
guide bool
targets []string
file string
stdin bool
mode string
rate int
threads int
stages string
profile string
quiet bool
storage string
)
fs.StringArrayVarP(&targets, "target", "t", nil, "Target domain(s) (repeatable)")
fs.StringVarP(&file, "file", "f", "", "Read targets from file (one per line)")
fs.BoolVar(&stdin, "stdin", false, "Read targets from stdin")
fs.StringVarP(&mode, "mode", "m", "wide", "Scan mode: wide|narrow|fast|deep|osint")
fs.IntVar(&rate, "rate", 150, "Request rate hint")
fs.IntVar(&threads, "threads", 30, "Concurrent workers")
fs.StringVar(&stages, "stages", "all", "Comma-separated stages: subdomains,http,ports,urls,vulns")
fs.StringVarP(&profile, "profile", "p", "balanced", "Workflow profile: passive|balanced|aggressive")
fs.BoolVarP(&quiet, "quiet", "q", false, "Suppress progress output")
fs.StringVar(&storage, "storage", "", "Storage root (default: ./storage)")
_ = fs.Parse(args)

pflag.StringArrayVar(&scanTargets, "scn", nil, "Scan target(s)")
pflag.BoolVar(&status, "sts", false, "Show scan status")
pflag.BoolVar(&results, "res", false, "Show results")
pflag.BoolVar(&listTools, "lst", false, "List external tool availability")
pflag.BoolVar(&export, "exp", false, "Export results to JSON")
pflag.BoolVar(&configCmd, "cfg", false, "Show config paths")
pflag.BoolVar(&pipeline, "pip", false, "Show pipeline path (v2 native pipeline is built-in)")
pflag.BoolVar(&serve, "srv", false, "Start web dashboard server")

pflag.StringVar(&filePath, "fil", "", "Read targets from file")
pflag.BoolVar(&useStdin, "inp", false, "Read targets from stdin")
pflag.StringVar(&domain, "dom", "", "Filter by domain")
pflag.StringVar(&scanID, "sid", "", "Fetch specific scan ID")
pflag.StringVar(&what, "wht", "all", "Result view: all|subdomains|live|ports|urls|js|vulns")
pflag.StringVar(&mode, "mod", "wide", "Mode: wide|narrow|fast|deep|osint")
pflag.BoolVar(&fast, "fst", false, "Shortcut for mode fast")
pflag.BoolVar(&narrow, "nrw", false, "Shortcut for mode narrow")
pflag.IntVar(&rate, "rte", 150, "Request rate hint")
pflag.IntVar(&threads, "thr", 30, "Worker threads")
pflag.IntVar(&limit, "lim", 50, "Output limit")
pflag.StringVar(&output, "out", "", "Output file")
pflag.BoolVar(&quiet, "qut", false, "Quiet output")
pflag.BoolVar(&showVersion, "ver", false, "Show version")
pflag.StringVar(&serveAddr, "adr", "127.0.0.1:8088", "Dashboard bind address")
pflag.StringVar(&storagePath, "str", "", "Storage root directory (default: ./storage)")
pflag.StringVar(&stages, "stg", "all", "Comma-separated stages: subdomains,http,ports,urls,vulns")
pflag.StringArrayVar(&setAPI, "sak", nil, "Set API key as name=value (repeatable). Use empty value to unset.")
pflag.BoolVar(&showAPI, "shk", false, "Show configured API keys (masked)")
pflag.BoolVar(&setup, "stp", false, "Show setup screen with tool installation status")
pflag.BoolVar(&installTools, "ins", false, "Install missing supported tools (Linux)")
pflag.StringVar(&profile, "prf", "balanced", "Workflow profile: passive|balanced|aggressive")
pflag.BoolVar(&guide, "gud", false, "Show first-principles workflow guide")
pflag.Parse()

if showVersion {
fmt.Printf("macaronV2 %s (Go %s, stable)\n", version, runtime.Version())
return 0
// Positional args are also targets.
for _, a := range fs.Args() {
targets = append(targets, a)
}
Copy link

Copilot AI Apr 12, 2026

Choose a reason for hiding this comment

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

All subcommands ignore flag parsing errors (_ = fs.Parse(args)). With ContinueOnError, this means unknown flags / missing values / --help can be silently ignored and execution continues with partial/default values (e.g., treating leftover args as targets). Capture and handle the parse error (including pflag.ErrHelp) and return a non-zero exit code where appropriate.

Copilot uses AI. Check for mistakes.
Comment thread cmd/macaron/main.go
removeStorage = readYes()
}
} else {
removeStorage = storage != ""
Copy link

Copilot AI Apr 12, 2026

Choose a reason for hiding this comment

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

uninstall --yes sets removeStorage = storage != "", so running macaron uninstall --yes will never remove the default storage directory even though the interactive flow offers to remove it. This makes --yes behave differently than “answer yes to prompts”. Consider either adding an explicit --remove-storage flag or making --yes apply to both prompts (and keep --storage as the path selector).

Suggested change
removeStorage = storage != ""
removeStorage = home != ""

Copilot uses AI. Check for mistakes.
Comment thread README.md
latest.txt
```

Override with `--storage /path/to/dir` or `MACARON_HOME` (env not yet supported — use the flag).
Copy link

Copilot AI Apr 12, 2026

Choose a reason for hiding this comment

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

The README states MACARON_HOME is “not yet supported”, but macaronHome() already honors the MACARON_HOME environment variable. Update the docs to reflect current behavior (or remove env support if it’s not intended).

Suggested change
Override with `--storage /path/to/dir` or `MACARON_HOME` (env not yet supported — use the flag).
Override with `--storage /path/to/dir` or the `MACARON_HOME` environment variable.

Copilot uses AI. Check for mistakes.
root-Manas added a commit that referenced this pull request Apr 12, 2026
Merge PR #25 and PR #27 into fix-conflicts-and-merge, resolving all conflicts
@root-Manas root-Manas merged commit 94ec21f into main Apr 12, 2026
7 checks passed
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.

3 participants