diff --git a/src/main.cpp b/src/main.cpp
index 08ca273..b6a9027 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -53,6 +53,7 @@ Subcommands:
list List installed packages
rollback Show available generations
index
Build an index.kap from .kap files in a directory
+ search Search cached indexes for packages
add [v] Add a package to system config (optional version)
--features "key=on,key2=off" Set feature flags
--config "key=val,key2=val2" Set config values
@@ -223,6 +224,7 @@ int main(int argc, char* argv[]) {
|| (subcommand == "fetch-package")
|| (subcommand == "rollback")
|| (subcommand == "index")
+ || (subcommand == "search")
|| (subcommand == "add")
|| (subcommand == "remove");
@@ -341,6 +343,50 @@ int main(int argc, char* argv[]) {
}
}
+ if (subcommand == "search") {
+ if (file_arg == nullptr) {
+ std::cerr << "error: no search query specified\n";
+ return 1;
+ }
+ auto idx_dir = paths::cache_dir() / "indexes";
+ std::error_code ec;
+ if (!std::filesystem::exists(idx_dir)) {
+ std::cout << "no cached indexes — run kappa fetch-package first\n";
+ return 0;
+ }
+
+ std::string_view query(file_arg);
+ int found = 0;
+ for (auto& entry : std::filesystem::directory_iterator(idx_dir, ec)) {
+ if (ec) break;
+ auto ext = entry.path().extension().string();
+ if (ext != ".kap") continue;
+
+ std::ifstream in(entry.path());
+ if (!in) continue;
+ std::ostringstream buf;
+ buf << in.rdbuf();
+
+ try {
+ auto idx = dsl::parse_index(buf.str());
+ for (auto& pkg : idx.packages) {
+ if (pkg.name.find(query) != std::string::npos) {
+ std::cout << pkg.name << " " << pkg.version
+ << " @ " << idx.name << "\n";
+ found++;
+ }
+ }
+ } catch (...) { continue; }
+ }
+
+ if (found == 0) {
+ std::cout << "no packages matching '" << query << "'\n";
+ } else {
+ std::cout << found << " result(s)\n";
+ }
+ return 0;
+ }
+
if (subcommand == "add") {
if (file_arg == nullptr) {
std::cerr << "error: no package name specified\n";