Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions src/cli/cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*/
#include "cli/cli.h"
#include "foundation/compat.h"
#include "foundation/platform.h"

// the correct standard headers are included below but clang-tidy doesn't map them.
#include <ctype.h>
Expand Down Expand Up @@ -1613,7 +1614,7 @@ unsigned char *cbm_extract_binary_from_targz(const unsigned char *data, int data
static const char *get_cache_dir(const char *home_dir) {
static char buf[1024];
if (!home_dir) {
home_dir = getenv("HOME");
home_dir = cbm_get_home_dir();
}
if (!home_dir) {
return NULL;
Expand Down Expand Up @@ -1837,10 +1838,9 @@ int cbm_cmd_config(int argc, char **argv) {
return 0;
}

// NOLINTNEXTLINE(concurrency-mt-unsafe)
const char *home = getenv("HOME");
const char *home = cbm_get_home_dir();
if (!home) {
fprintf(stderr, "error: HOME not set\n");
fprintf(stderr, "error: HOME not set (use USERPROFILE on Windows)\n");
return 1;
}

Expand Down Expand Up @@ -1968,9 +1968,9 @@ int cbm_cmd_install(int argc, char **argv) {
}
}

const char *home = getenv("HOME");
const char *home = cbm_get_home_dir();
if (!home) {
fprintf(stderr, "error: HOME not set\n");
fprintf(stderr, "error: HOME not set (use USERPROFILE on Windows)\n");
return 1;
}

Expand Down Expand Up @@ -2232,9 +2232,9 @@ int cbm_cmd_uninstall(int argc, char **argv) {
}
}

const char *home = getenv("HOME");
const char *home = cbm_get_home_dir();
if (!home) {
fprintf(stderr, "error: HOME not set\n");
fprintf(stderr, "error: HOME not set (use USERPROFILE on Windows)\n");
return 1;
}

Expand Down Expand Up @@ -2425,9 +2425,9 @@ int cbm_cmd_uninstall(int argc, char **argv) {
int cbm_cmd_update(int argc, char **argv) {
parse_auto_answer(argc, argv);

const char *home = getenv("HOME");
const char *home = cbm_get_home_dir();
if (!home) {
fprintf(stderr, "error: HOME not set\n");
fprintf(stderr, "error: HOME not set (use USERPROFILE on Windows)\n");
return 1;
}

Expand Down
19 changes: 18 additions & 1 deletion src/foundation/platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
#include "platform.h"
#include "compat.h"

#include <stdint.h> // uint64_t, int64_t
#include <stdint.h> // uint64_t, int64_t
#include <stdlib.h> // getenv

#ifdef _WIN32

Expand Down Expand Up @@ -216,3 +217,19 @@ int64_t cbm_file_size(const char *path) {
}

#endif /* _WIN32 */

/* ── Home directory (cross-platform) ──────────────────────────── */

const char *cbm_get_home_dir(void) {
// NOLINTNEXTLINE(concurrency-mt-unsafe)
const char *h = getenv("HOME");
if (h && h[0]) {
return h;
}
// NOLINTNEXTLINE(concurrency-mt-unsafe)
h = getenv("USERPROFILE");
if (h && h[0]) {
return h;
}
return NULL;
}
6 changes: 6 additions & 0 deletions src/foundation/platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,12 @@ cbm_system_info_t cbm_system_info(void);
* initial=false: max(1, perf_cores-1) (leave headroom for user apps) */
int cbm_default_worker_count(bool initial);

/* ── Home directory ─────────────────────────────────────────────── */

/* Cross-platform home directory: tries HOME first, then USERPROFILE (Windows).
* Returns NULL when neither is set. */
const char *cbm_get_home_dir(void);

/* ── File system ───────────────────────────────────────────────── */

/* Check if a path exists. */
Expand Down
3 changes: 2 additions & 1 deletion src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "store/store.h"
#include "cli/cli.h"
#include "foundation/log.h"
#include "foundation/platform.h"
#include "foundation/compat_thread.h"
#include "foundation/mem.h"
#include "ui/config.h"
Expand Down Expand Up @@ -221,7 +222,7 @@ int main(int argc, char **argv) {

/* Open config store for runtime settings */
char config_dir[1024];
const char *cfg_home = getenv("HOME");
const char *cfg_home = cbm_get_home_dir();
cbm_config_t *runtime_config = NULL;
if (cfg_home) {
snprintf(config_dir, sizeof(config_dir), "%s/.cache/codebase-memory-mcp", cfg_home);
Expand Down
11 changes: 4 additions & 7 deletions src/mcp/mcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -564,10 +564,9 @@ bool cbm_mcp_server_has_cached_store(cbm_mcp_server_t *srv) {
/* Returns the platform cache directory: ~/.cache/codebase-memory-mcp
* Writes to buf, returns buf for convenience. */
static const char *cache_dir(char *buf, size_t bufsz) {
// NOLINTNEXTLINE(concurrency-mt-unsafe)
const char *home = getenv("HOME");
const char *home = cbm_get_home_dir();
if (!home) {
home = "/tmp";
home = cbm_tmpdir();
}
snprintf(buf, bufsz, "%s/.cache/codebase-memory-mcp", home);
return buf;
Expand Down Expand Up @@ -1995,8 +1994,7 @@ static void detect_session(cbm_mcp_server_t *srv) {
/* 1. Try CWD */
char cwd[1024];
if (getcwd(cwd, sizeof(cwd)) != NULL) {
// NOLINTNEXTLINE(concurrency-mt-unsafe)
const char *home = getenv("HOME");
const char *home = cbm_get_home_dir();
/* Skip useless roots: / and $HOME */
if (strcmp(cwd, "/") != 0 && (home == NULL || strcmp(cwd, home) != 0)) {
snprintf(srv->session_root, sizeof(srv->session_root), "%s", cwd);
Expand Down Expand Up @@ -2067,8 +2065,7 @@ static void maybe_auto_index(cbm_mcp_server_t *srv) {
}

/* Check if project already has a DB */
// NOLINTNEXTLINE(concurrency-mt-unsafe)
const char *home = getenv("HOME");
const char *home = cbm_get_home_dir();
if (home) {
char db_check[1024];
snprintf(db_check, sizeof(db_check), "%s/.cache/codebase-memory-mcp/%s.db", home,
Expand Down
10 changes: 4 additions & 6 deletions src/pipeline/pipeline.c
Original file line number Diff line number Diff line change
Expand Up @@ -127,10 +127,9 @@ static char *resolve_db_path(const cbm_pipeline_t *p) {
if (p->db_path) {
snprintf(path, 1024, "%s", p->db_path);
} else {
// NOLINTNEXTLINE(concurrency-mt-unsafe)
const char *home = getenv("HOME");
const char *home = cbm_get_home_dir();
if (!home) {
home = "/tmp";
home = cbm_tmpdir();
}
snprintf(path, 1024, "%s/.cache/codebase-memory-mcp/%s.db", home, p->project_name);
}
Expand Down Expand Up @@ -680,14 +679,13 @@ int cbm_pipeline_run(cbm_pipeline_t *p) {
if (!check_cancel(p)) {
cbm_clock_gettime(CLOCK_MONOTONIC, &t);

// NOLINTNEXTLINE(concurrency-mt-unsafe) — called once during single-threaded dump
const char *home = getenv("HOME");
const char *home = cbm_get_home_dir();
char db_path[1024];
if (p->db_path) {
snprintf(db_path, sizeof(db_path), "%s", p->db_path);
} else {
if (!home) {
home = "/tmp";
home = cbm_tmpdir();
}
snprintf(db_path, sizeof(db_path), "%s/.cache/codebase-memory-mcp/%s.db", home,
p->project_name);
Expand Down
5 changes: 2 additions & 3 deletions src/store/store.c
Original file line number Diff line number Diff line change
Expand Up @@ -348,10 +348,9 @@ cbm_store_t *cbm_store_open(const char *project) {
return NULL;
}
/* Build path: ~/.cache/codebase-memory-mcp/<project>.db */
const char *home = getenv("HOME"); // NOLINT(concurrency-mt-unsafe) — called once during
// single-threaded store open, never concurrently
const char *home = cbm_get_home_dir();
if (!home) {
home = "/tmp";
home = cbm_tmpdir();
}
char path[1024];
snprintf(path, sizeof(path), "%s/.cache/codebase-memory-mcp/%s.db", home, project);
Expand Down
6 changes: 4 additions & 2 deletions src/ui/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
*/
#include "ui/config.h"
#include "foundation/log.h"
#include "foundation/platform.h"
#include "foundation/compat_fs.h"
#include "foundation/compat.h"

#include <yyjson/yyjson.h>

Expand All @@ -17,9 +19,9 @@
/* ── Path ────────────────────────────────────────────────────── */

void cbm_ui_config_path(char *buf, int bufsz) {
const char *home = getenv("HOME"); // NOLINT(concurrency-mt-unsafe)
const char *home = cbm_get_home_dir();
if (!home) {
home = "/tmp";
home = cbm_tmpdir();
}
snprintf(buf, (size_t)bufsz, "%s/.cache/codebase-memory-mcp/config.json", home);
}
Expand Down
22 changes: 11 additions & 11 deletions src/ui/http_server.c
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ static void handle_browse(struct mg_connection *c, struct mg_http_message *hm) {
char path[1024] = {0};
if (!get_query_param(hm->query, "path", path, (int)sizeof(path)) || path[0] == '\0') {
/* Default to home directory */
const char *home = getenv("HOME");
const char *home = cbm_get_home_dir();
if (home)
snprintf(path, sizeof(path), "%s", home);
else
Expand Down Expand Up @@ -387,9 +387,9 @@ static void handle_adr_get(struct mg_connection *c, struct mg_http_message *hm)
return;
}

const char *home = getenv("HOME");
const char *home = cbm_get_home_dir();
if (!home)
home = "/tmp";
home = cbm_tmpdir();
char db_path[1024];
snprintf(db_path, sizeof(db_path), "%s/.cache/codebase-memory-mcp/%s.db", home, name);

Expand Down Expand Up @@ -480,9 +480,9 @@ static void handle_adr_save(struct mg_connection *c, struct mg_http_message *hm)
const char *proj = yyjson_get_str(v_proj);
const char *content = yyjson_get_str(v_content);

const char *home = getenv("HOME");
const char *home = cbm_get_home_dir();
if (!home)
home = "/tmp";
home = cbm_tmpdir();
char db_path[1024];
snprintf(db_path, sizeof(db_path), "%s/.cache/codebase-memory-mcp/%s.db", home, proj);

Expand Down Expand Up @@ -777,9 +777,9 @@ static void handle_delete_project(struct mg_connection *c, struct mg_http_messag
return;
}

const char *home = getenv("HOME"); // NOLINT(concurrency-mt-unsafe)
const char *home = cbm_get_home_dir();
if (!home)
home = "/tmp";
home = cbm_tmpdir();
char db_path[1024];
snprintf(db_path, sizeof(db_path), "%s/.cache/codebase-memory-mcp/%s.db", home, name);

Expand Down Expand Up @@ -815,9 +815,9 @@ static void handle_project_health(struct mg_connection *c, struct mg_http_messag
return;
}

const char *home = getenv("HOME"); // NOLINT(concurrency-mt-unsafe)
const char *home = cbm_get_home_dir();
if (!home)
home = "/tmp";
home = cbm_tmpdir();
char db_path[1024];
snprintf(db_path, sizeof(db_path), "%s/.cache/codebase-memory-mcp/%s.db", home, name);

Expand Down Expand Up @@ -873,9 +873,9 @@ static void handle_layout(struct mg_connection *c, struct mg_http_message *hm) {
}

/* Open a read-only store for this project */
const char *home = getenv("HOME"); // NOLINT(concurrency-mt-unsafe)
const char *home = cbm_get_home_dir();
if (!home)
home = "/tmp";
home = cbm_tmpdir();
char db_path[1024];
snprintf(db_path, sizeof(db_path), "%s/.cache/codebase-memory-mcp/%s.db", home, project);

Expand Down
5 changes: 3 additions & 2 deletions tests/test_integration.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <store/store.h>
#include <pipeline/pipeline.h>
#include <foundation/log.h>
#include <foundation/platform.h>

#include <string.h>
#include <stdlib.h>
Expand Down Expand Up @@ -105,9 +106,9 @@ static int integration_setup(void) {
return -1;

/* Build db path for direct store queries (pipeline writes here) */
const char *home = getenv("HOME");
const char *home = cbm_get_home_dir();
if (!home)
home = "/tmp";
home = cbm_tmpdir();
snprintf(g_dbpath, sizeof(g_dbpath), "%s/.cache/codebase-memory-mcp/%s.db", home, g_project);

/* Ensure cache dir exists */
Expand Down