projcfg

package
v0.22.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 15, 2026 License: Apache-2.0 Imports: 23 Imported by: 0

Documentation

Index

Constants

View Source
const ConfigFileName = ".mache.json"

ConfigFileName is the convention file looked up by `mache serve`.

Variables

View Source
var (
	MacheHTTPListen = EnvOr("MACHE_DAEMON_LISTEN", "localhost:7532")
	MacheHTTPURL    = "http://" + MacheHTTPListen + "/mcp"
)

Canonical MCP transport endpoint. mache serves Streamable HTTP on this address, and onboarding registers clients against it. Re-homed here from cmd/daemon_agent.go (R2, mache-96c378): editor/MCP-config generation needs the endpoint, and reaching upward into cmd for it was the other would-be import cycle. The daemon lifecycle code in cmd reads these same values, so there is exactly one answer to "where does mache listen".

Overridable via environment so a second, isolated daemon can coexist with the canonical one (the hermetic launchd E2E, or an operator's canary).

Functions

func CheckPathContainment

func CheckPathContainment(resolved, base string) error

CheckPathContainment verifies that resolved is within or equal to base. Prevents path traversal attacks from untrusted .mache.json files.

Resolves symlinks via filepath.EvalSymlinks before comparison so a target pointing to a symlink that escapes the project directory is caught even if the symlink itself sits inside the project. If the target does not exist yet (EvalSymlinks errors), falls back to filepath.Abs since nonexistent paths cannot point anywhere malicious until they are created.

func DetectProjectType

func DetectProjectType(dir string) string

DetectProjectType scans a directory and returns the best-fit schema preset name. Checks sentinel files first (go.mod, pyproject.toml, etc.), then falls back to counting file extensions in the top-level directory. Returns empty string if no preset matches (caller should omit schema).

func EnsureProjectRegistered

func EnsureProjectRegistered(rootPath string) bool

EnsureProjectRegistered records rootPath in the local registry if it is not already there, and reports whether a write happened.

This is what makes registration a BYPRODUCT of serving rather than a separate setup step. Before it, RegisterProject had exactly one caller — `mache init` — so a daemon could serve a project a hundred times and ~/.mache/projects.json would still not exist. That is not hypothetical: a long-running shared daemon was found serving this repo with an empty registry, so every ?project= lookup necessarily missed (mache-6ec106's resolution path was in place but had nothing to resolve against).

Now any session that resolves a workspace root by ANY means — client roots, an explicit --path — registers it, so the token exists for the next client that cannot answer roots/list. `mache init` keeps its distinct job: writing the ?project= token into the client's config, which a server cannot do.

Deliberately non-fatal and quiet on failure. A read-only HOME or a corrupt registry must not take down a session that is otherwise resolving fine — serving the graph is the job; registration is an optimization for later. The existence check keeps the steady state read-only: re-registering on every tool call would rewrite the file constantly for no gain.

func EnvBytesOr

func EnvBytesOr(key string, fallback int64) int64

EnvBytesOr parses key as a non-negative byte count, or returns fallback. Separate from EnvIntOr because a size budget is int64 and may legitimately be zero, which EnvIntOr's positive-only rule would reject.

func EnvDurationOr

func EnvDurationOr(key string, fallback time.Duration) time.Duration

EnvDurationOr parses key as a Go duration, or returns fallback when unset, unparseable, or non-positive. Lives here beside EnvOr because the daemon lifecycle's tunables (settle, drain, breaker window) are read from three different packages, and three copies of this parser is exactly what the duplicate-code gate exists to prevent.

func EnvIntOr

func EnvIntOr(key string, fallback int) int

EnvIntOr parses key as a positive integer, or returns fallback.

func EnvOr

func EnvOr(key, fallback string) string

EnvOr returns the environment value for key, or fallback when unset/empty.

func LoadProjectRegistry

func LoadProjectRegistry() (map[string]string, error)

LoadProjectRegistry reads the token -> path map, returning an empty map (not an error) when the registry has not been created yet.

func MacheHomeDir

func MacheHomeDir() (string, error)

MacheHomeDir returns ~/.mache, creating it if necessary. Exported so other packages that keep per-machine daemon state (internal/daemonguard) resolve it through the SAME seam — which means they inherit the test-hermeticity guard below for free, rather than each re-deriving a path that tests can pollute (mache-3e78d2).

func RegisterAllEditors

func RegisterAllEditors(w io.Writer, binaryPath string, claudeRegister func(string) bool)

RegisterAllEditors registers mache with all detected editors. claudeRegister performs the Claude Code CLI registration — production callers pass RegisterClaudeCodeCLI; tests pass a stub.

func RegisterClaudeCodeCLI

func RegisterClaudeCodeCLI(binaryPath string) bool

RegisterClaudeCodeCLI registers mache via `claude mcp add` if the CLI is available. Callers pass it (or a stub) to RegisterAllEditors — a parameter, not a package var, so tests in different packages can never race on one shared global (B14/B19 in the decomposition review).

func RegisterProject

func RegisterProject(absPath string) (string, error)

RegisterProject records absPath in the local registry under its derived token and returns the token. Idempotent: re-registering the same path (e.g. re-running `mache init`) reproduces the same token and simply overwrites its own entry — every other project's entry is preserved. That preservation is also the migration policy for tokens minted before path canonicalization: adding the canonical token does not delete the old spelling, so already-written client URLs keep resolving during the grace period. New registrations converge on the canonical token.

func ResolveDataSource

func ResolveDataSource(sourcePath, configDir string) (string, error)

ResolveDataSource resolves a data source path relative to configDir. Absolute paths are returned as-is. Relative paths are checked for containment within configDir to prevent path traversal.

func ResolveProjectToken

func ResolveProjectToken(token string) (string, bool)

ResolveProjectToken looks up token in the local registry, returning the absolute path it was registered against. ok is false when the token is unknown — whether guessed, stale, or from a registry that was wiped after the client's config was written.

func ResolveSchema

func ResolveSchema(schemaRef, configDir string) (*api.Topology, error)

ResolveSchema resolves a schema reference to a Topology. It handles three forms:

  • Preset name: "go", "python", etc.
  • Relative path: "./custom-schema.json" (resolved against configDir)
  • Absolute path: "/path/to/schema.json"

Returns nil if schemaRef is empty (caller should use inference or default).

func WriteClaudeMCPConfig

func WriteClaudeMCPConfig(projectDir, projectToken string) error

WriteClaudeMCPConfig writes or merges a mache entry into .claude/mcp.json. Uses map[string]any as root type to preserve unknown top-level keys. projectToken is forwarded to httpServerEntry — see its doc comment.

func WriteClaudeMD

func WriteClaudeMD(projectDir, schemaPreset string) error

WriteClaudeMD writes a .claude/CLAUDE.md that describes the mache MCP tools so Claude Code automatically knows how to use them.

Types

type ProjectConfig

type ProjectConfig struct {
	Sources []SourceConfig `json:"sources"`
	// SmellRulesDir points at a directory of external SmellRule JSON
	// files (see LoadExternalSmellRules). A relative value is resolved
	// against the .mache.json's own directory for portability; see
	// resolveSmellRulesDir. Optional — omit to use built-in rules only.
	SmellRulesDir string `json:"smellRulesDir,omitempty"`
}

ProjectConfig represents the .mache.json project configuration.

func LoadProjectConfig

func LoadProjectConfig(dir string) (*ProjectConfig, error)

LoadProjectConfig reads .mache.json from the given directory.

type SourceConfig

type SourceConfig struct {
	Path   string `json:"path"`
	Schema string `json:"schema,omitempty"`
}

SourceConfig describes a single data source within a project.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL