A release driven entirely by 2.0 field reports. The authorization default made project access a real concept, but the CLI had no way to manage it and no way to reset a password; lific init/lific service quietly ignored --config; and configuration lived wherever the command happened to run instead of where an OS keeps config. 2.1 closes all of it: project membership and password resets from the CLI, config discovered (and created) in standard OS locations, --config honored everywhere, and - for private local instances - the option to turn auth off entirely.
lific member - manage project access from the CLI
With enforcement on (the 2.0 fresh-install default), a newly created user is a member of nothing and sees nothing. That was manageable only through the web UI's members page; now the CLI can do it:
lific member list --project <IDENT>- members and their roles.lific member add --project <IDENT> --user <name> [--role viewer|maintainer|lead]- grant access (viewer by default).--allgrants on every existing project at once, skipping projects where the user is already a member (their role is never silently overwritten).lific member role -p <IDENT> -u <name> -r <role>- change a role. The last-lead guard applies: you cannot demote a project's only lead.lific member remove -p <IDENT> -u <name>- revoke access (same last-lead guard;projects.lead_user_idis repaired when the removed user was the primary lead).
Membership changes are audit-logged like every other write (the project_members triggers from 2.0 cover CLI writes automatically). JSON output on --json or piped stdout, as everywhere.
lific user set-password - operator password reset
There was no password reset at all: the web UI's change-password requires the current password, and a forgotten one meant SQL surgery. lific user set-password --username <name> sets a new one from the shell (masked prompt on a TTY, read-a-line when piped, --password for scripts). Shell access to the server is the trust boundary, same as user create --admin. Matching self-service semantics, a reset invalidates all of the user's sessions.
lific init and lific service install honor --config
"lific service sets the wrong config path every time, even after passing the flag" - correct, it did. Both commands hardcoded ./lific.toml from the invocation cwd when rendering the service definition, so the installed unit could point at a different config than the one you named.
- Both commands now root the instance at
--config <path>:initcreates the file there (parent directories included), and the service definition'sExecStart/WorkingDirectoryderive from the config file's canonical location - a relativedatabase.pathresolves beside the config at runtime, exactly asinitresolved it at setup time. lific service install --config <missing path>fails fast with the path it looked at instead of silently installing a unit for the wrong instance.
Auth optional through config - [auth] required = false
For a private, local, single-user instance, authentication itself can now be turned off: with required = false under [auth], a request that presents no credential at all is treated as operator-equivalent (the same trust rail 2.0 gave unbound API keys) on both REST and MCP. A presented-but-invalid token still 401s - a broken client config surfaces as an error instead of silently degrading to anonymous-with-admin-powers, and real credentials keep resolving to their real identity.
Deliberately a config-file key rather than a runtime instance setting: turning auth off requires shell access to the server, exactly like minting an operator key. Guard rails: lific start refuses to boot when auth is optional and server.public_url points anywhere but localhost (loopback IPs are verified as IPs - 127.evil.com doesn't count), and otherwise logs a prominent warning that the default 0.0.0.0 bind makes the instance LAN-reachable.
lific init uses standard OS directories by default
init used to create lific.toml + lific.db in whatever directory it ran from - run it in three directories, get three accidental instances. A bare lific init now roots the instance in your OS's standard locations: config at ~/.config/lific/lific.toml and database at ~/.local/share/lific/lific.db on Linux (macOS/Windows equivalents), with backups and attachments beside the database in the data dir. Since config discovery already probes the user config dir, every other command finds this instance from any directory with no flags.
lific init --herekeeps the old directory-local layout (./lific.toml+./lific.db) for repo-scoped instances.- A
lific.tomlalready in the current directory wins over the OS dirs: re-running bareinitbeside an existing directory-local instance repairs it rather than silently creating a second instance in XDG. lific service installwithout--confignow discovers the config the same wayConfig::loaddoes (cwd, then user config dir, then system config dir) instead of insisting on./lific.toml.
Config discovered in standard system locations
The config search order gains the platform system config dir as a last-resort fallback, for one machine-level config shared by every invocation: /etc/lific/lific.toml on Linux/BSD, /Library/Application Support/Lific/lific.toml on macOS, %ProgramData%\lific\lific.toml on Windows. Full order: --config > ./lific.toml > user config dir (~/.config/lific/, $XDG_CONFIG_HOME respected) > system config dir. First match wins; a relative database.path anchors to the config file's own directory regardless of where it was found.