Documentation
¶
Overview ¶
Package config reads and writes sync82's configuration: the global config file (~/.sync82/config.json) holding the last used project and the custom vault path, the per-workspace marker file (.sync82.json) that maps a directory to a project, and the vault path resolution helpers. Global config updates are serialized across goroutines and processes.
Index ¶
- Constants
- func DefaultVaultPath() string
- func GlobalConfigPath() (string, error)
- func ResolvePath(raw string) string
- func UpdateGlobalConfig(mutate func(cfg *GlobalConfig)) error
- func UpdateLastProject(project, subproject, vaultPath string) error
- func WriteLocalConfig(workspaceRoot string, cfg LocalConfig) error
- type GlobalConfig
- type LocalConfig
- type LocalConfigResult
Constants ¶
const (
DBPathEnvVar = "SYNC82_DB_PATH"
)
DBPathEnvVar names the environment variable overriding the default vault path; defaultVaultDir and defaultVaultFile locate the default vault under the home directory.
Variables ¶
This section is empty.
Functions ¶
func DefaultVaultPath ¶
func DefaultVaultPath() string
DefaultVaultPath returns the vault path used when no tool argument, local config, or global config supplies one: the SYNC82_DB_PATH environment variable (with ResolvePath applied, then made absolute against the current directory) if set, otherwise ~/.sync82/knowledge.db. When the home directory is unknown, the default is relative to the current directory.
func GlobalConfigPath ¶
GlobalConfigPath returns the path to ~/.sync82/config.json. It returns an error when the user's home directory cannot be determined.
func ResolvePath ¶
ResolvePath expands a leading HOME, $HOME, or ~ token in raw (alone or followed by a slash, or on Windows also by a backslash) to the user's home directory. Any other value, or any value when the home directory cannot be determined, is returned unchanged.
func UpdateGlobalConfig ¶
func UpdateGlobalConfig(mutate func(cfg *GlobalConfig)) error
UpdateGlobalConfig performs a locked read-modify-write of the global config: it reads the current config, lets mutate adjust it in place, and writes the result back. It is the single entry point for read-modify-write changes to the file, such as UpdateLastProject and the vault path commands.
Two locks are held for the whole read-modify-write: globalConfigMu, which serializes goroutines of this process, and an exclusive advisory lock on ~/.sync82/config.lock, which serializes separate processes (each MCP client runs its own server process, and the CLI is another one). Both are released on every return path.
When mutate leaves the config unchanged, nothing is written, unless a corrupt file was just set aside.
A config file that exists but is empty, whitespace-only, or not valid JSON is renamed to config.json.corrupt-<unix-timestamp> (keeping its permission bits) and the update continues from a zero-value config, so the file becomes writable again instead of failing every update. ReadGlobalConfig still reports such a file as a parse error.
It returns an error when the path cannot be resolved, the lock cannot be taken, the file cannot be read or moved aside, or the write fails.
func UpdateLastProject ¶
UpdateLastProject records the most recently used project/subproject and the vault path it lives in, so a later call that passes no project argument can fall back to them. Other fields of the config are kept. Nothing is written when the values are unchanged. It returns the errors of UpdateGlobalConfig; callers may treat them as best-effort.
func WriteLocalConfig ¶
func WriteLocalConfig(workspaceRoot string, cfg LocalConfig) error
WriteLocalConfig atomically writes cfg as .sync82.json directly in workspaceRoot, without searching ancestors. It never writes through a symlink: an existing .sync82.json that is not a regular file is refused with an error wrapping fsutil.ErrNotRegularFile. It returns an error when the path cannot be made absolute, cfg cannot be encoded, or the file cannot be written.
Types ¶
type GlobalConfig ¶
type GlobalConfig struct {
LastProject string `json:"lastProject,omitempty"`
LastSubproject string `json:"lastSubproject,omitempty"`
LastVaultPath string `json:"lastVaultPath,omitempty"`
VaultPath string `json:"vaultPath,omitempty"`
}
GlobalConfig is the content of ~/.sync82/config.json: the last project/subproject used and the vault it lives in (the fallback tier of context resolution), plus an optional custom vault path set by "sync82 config set-vault".
func ReadGlobalConfig ¶
func ReadGlobalConfig() (GlobalConfig, error)
ReadGlobalConfig reads the global config. A missing file is not an error: it returns the zero-value config. The read holds a shared lock on ~/.sync82/config.lock, so it never has the file open while UpdateGlobalConfig, which holds the exclusive lock, renames a new file over it (Windows refuses that rename while the file is open); in a read-only ~/.sync82 or on a read-only filesystem, where the lock file can't be created, it reads without the lock. It returns an error when the path cannot be resolved, the lock cannot be taken, the file cannot be read, or its content is not valid JSON.
type LocalConfig ¶
type LocalConfig struct {
Project string `json:"project"`
Subproject string `json:"subproject,omitempty"`
Path string `json:"path,omitempty"`
}
LocalConfig is the content of a workspace's .sync82.json: the project/subproject (and optionally the vault path) the workspace maps to, so tool calls need no explicit project argument.
type LocalConfigResult ¶
type LocalConfigResult struct {
Config LocalConfig
ConfigRoot string
}
LocalConfigResult bundles a found LocalConfig with the absolute directory it was found in (ConfigRoot), against which a relative Path is resolved.
func ReadLocalConfig ¶
func ReadLocalConfig(workspaceRoot string, searchAncestors bool) (*LocalConfigResult, error)
ReadLocalConfig looks for a .sync82.json file at workspaceRoot. When searchAncestors is true, it also walks upward through parent directories (up to maxLocalConfigWalkDepth directories in total, or the filesystem root, whichever comes first). Ancestor search is opt-in because a file found in an ancestor can redirect where memory is stored through its "path" field, so otherwise only workspaceRoot is trusted.
It returns (nil, nil) when no file is found. It returns an error when workspaceRoot cannot be made absolute, or a candidate file is not a regular file (a symlink could redirect the read, and WriteLocalConfig's write, to an unrelated file), cannot be read (other than not existing) or is not valid JSON.