Skip to content

v2.0.0

Choose a tag to compare

@github-actions github-actions released this 05 Jul 04:03
· 566 commits to master since this release

Lific 2.0 is three releases in one. The web UI moves from complete to fast, personal, and pleasant: a real home page, analytics, saved views, undo, a peek panel, full keyboard control, and a theming system. Underneath it, Lific gets real authorization. Project-scoped membership and roles are enforced identically across the REST API and every MCP tool, on by default for fresh installs and opt-in for instances upgrading from 1.x (existing setups keep working bit-for-bit). And around it, a new CLI onboards the whole thing in two commands: lific init builds a running, boot-persistent instance and lific connect wires any of 11 AI clients to it, with health checks, device-flow login, and per-tool agent identities.

The CLI got a facelift - clack-style sessions and real selectors

Human-facing CLI output moved from bare println! walls to a proper prompt UI (via cliclack, the Rust implementation of the @clack/prompts look): a ┌ lific init session header, a gutter connecting completed steps, boxed notes for things you must actually read (API keys, next steps, manual snippets), and a outro.

  • lific connect has a real picker now. The "type comma-separated numbers" prompt is gone: an arrow-key multi-select lists every client with installed ones marked (detected) and preselected - space toggles, enter confirms. The AGENTS.md question is a proper confirm prompt.
  • Sessions everywhere: init, connect, doctor (// per check severity, summary as the outro), login (code in a note block, a live spinner while waiting for approval), service, restore, dump, plus key and user management output.
  • lific user create's password prompt is masked now - it previously echoed the password in plaintext.
  • Agents see zero change. JSON output (explicit --json or piped stdout), non-TTY fail-fast prompts, and every machine-readable shape are byte-for-byte untouched; the pretty layer renders only for humans at a terminal.

lific connect can no longer wire your tools to the wrong instance silently

Running connect from the wrong directory used to be a quiet disaster: it would silently create a brand-new empty lific.db in whatever directory you happened to be in, mint keys against it, and rewrite every selected client's lific entry to point there - replacing their config for your real instance without a word about which instance it was targeting.

  • Connect refuses to run where no instance exists. If the resolved database file isn't there, it errors with directions (run from the instance directory, pass --config/--db, or lific init) instead of conjuring a fresh one.
  • The target is announced up front: the session opens with Instance: <url> (keys minted in <db path>), and the client picker itself asks "Which clients should connect to ?" - wiring tools to the wrong instance now requires ignoring two explicit statements of it.
  • --config works from anywhere now. A relative database.path in a config file resolves against the config file's directory, not the process cwd - previously lific --config /srv/lific/lific.toml <cmd> run from elsewhere would look for (or create) the database in your cwd. Backups anchor the same way.

lific init now sets up everything - including a service that survives reboot

The 60-second setup used to end with a server tied to an open terminal: close it (or log out) and your agents' "missing memory" was gone. lific init is now the whole onboarding story:

  • One command: writes lific.toml (kept if present), creates and migrates the database, mints and prints your initial API key, installs a background service, starts it, and verifies the server actually answers before claiming success. Re-running is safe and repairs whatever is missing.
  • Real service integration: a systemd user unit on Linux (~/.config/systemd/user/lific.service, with best-effort loginctl enable-linger so it outlives logout) or a launchd LaunchAgent on macOS (~/Library/LaunchAgents/dev.lific.plist). Starts on boot, restarts on failure.
  • lific service install | uninstall | status | stop | restart manages the service afterward; status exits nonzero when the service isn't running, so scripts and agents can gate on it.
  • Honest failure modes: no service manager (containers, WSL without systemd) falls back to clear lific start instructions; a port squatted by another process is diagnosed as such instead of reported as success (init cross-checks the unit's own state against the health probe, so a stranger answering on :3456 can't fake a working install).
  • The API key prints during init, in your terminal - not into a service journal nobody reads. The old box-drawing around the key (which rendered broken) is gone; lific start remains for foreground use (lific init --no-service skips service setup entirely).
  • The README's 60-second setup now matches reality, and its lific user promote <username> example is corrected to the actual --username syntax.

Authorization on by default for fresh installs

Project-scoped authorization (detailed below) would be pointless shipped dark: a brand-new install with authz_enforced off has no authorization at all - any valid bearer token could read, mutate, or delete every project. So fresh installs enforce by default, without breaking the zero-user init → connect flow; instances upgrading from 1.x keep enforcement off until an admin opts in.

  • Install-dependent seed. On the first run that creates the settings row, authz_enforced is seeded from whether the database has any users yet: a fresh install (zero users) enforces by default; an instance upgraded from an earlier version (users already exist) stays off. The row is authoritative once written - later starts never re-evaluate or flip it, and an admin who turns enforcement off stays off.
  • Operator-key trust rule. The agent-first flow runs on user-unbound API keys, which resolve to no effective user and would be default-denied under enforcement. Such keys can only be minted with shell access to the server (lific start's auto-key, lific key create, connect's fresh-install path), so in enforced mode they are now treated as operator-trusted (admin-equivalent). The signal is credential-type-specific and set only on the unbound-API-key auth path - a legacy pre-binding OAuth token also resolves to no user but is not granted operator power and stays default-denied (covered by explicit regression tests on both REST and MCP).
  • Unbound API keys bypass authorization by design. Audit them with lific key list. Prefer per-tool bot identities (what lific connect mints once you have a user account), which inherit their owner's project access and are attributed by name.

Project membership and roles

Until now, authentication was a door with no rooms behind it: any logged-in account - and any connected agent - could read, edit, or delete content in every project. 2.0 adds project-scoped membership and roles, so an agent holds exactly the authority its owner granted it and nothing more.

  • Three roles per project: viewer (read + comment), maintainer (full content and structure CRUD), and lead (everything, plus settings, membership, and project deletion). Multiple leads per project are supported; global admins override everything as the break-glass path.
  • Default-deny, reads included. With enforcement on, a non-member sees nothing - projects vanish from lists and search, and direct reads are refused. There is no implicit access floor.
  • One enforcement layer, two transports. REST handlers and all 29 MCP tools call the same authz module, so the web UI and agents can never drift apart. Cross-project operations (issue relations, plan-step issue links) require the role on every project touched.
  • Agents inherit their owner. A bot acts with its owning user's memberships and can never exceed them; OAuth-token requests resolve to their real user end to end. A token-backed agent that is a member keeps working under default-deny - verified by explicit lockout-regression tests on both transports.
  • Safe, reversible rollout. Enforcement is a runtime instance setting (authz_enforced, seeded on for fresh installs and off for upgrades; flip it anytime in Instance Settings or lific instance set --authz-enforced true). Legacy mode preserves pre-2.0 behavior bit-for-bit; existing project leads are backfilled as lead members automatically.
  • Membership management in Project Settings: list members with role badges, add by name, change roles inline, remove with confirmation - lead-gated, with last-lead protection so a project can't be orphaned. Every membership change lands in the audit log with actor attribution.
  • Enumeration-derived coverage. The test suite extracts every REST route and every MCP tool and fails if any surface is missing an authorization classification, so future endpoints can't ship ungated. The suite now stands at 931 tests.

Connect an agent in one command

  • lific connect <tool> writes working MCP config into 11 AI clients - OpenCode, Claude Code, Claude Desktop, Cursor, VS Code, Codex, Zed, Gemini CLI, Windsurf, Goose, and Crush - globally or per-project, over stdio or HTTP. Each connected tool gets its own bot identity, so the audit log shows which agent did what; --oauth connects native-auth clients without minting a key.
  • lific doctor health-checks config, database, backups, server reachability, OAuth, and MCP wiring, with actionable fix hints.
  • lific login / logout: two-step device-flow auth (RFC 8628) with keyring-backed credential storage - no pasting API keys.
  • lific agents-md writes a maintained Lific section into a repo's AGENTS.md so agents learn the house conventions.
  • Terminal citizenship: shell completions for bash/zsh/fish, TTY-aware output (auto-JSON when piped, prompts never hang non-interactive runs), and piped output can no longer panic on SIGPIPE.
  • For agents over MCP: the server's instructions now teach Lific workflow conventions, cold read tools nudge self-onboarding on a zero-project instance, and the repo ships an MCP Registry manifest and publish runbook.

Agent tooling (MCP)

  • Edit and delete comments over MCP: new edit_comment and delete_comment tools, enforcing the same author-or-admin ownership rules as their REST counterparts.
  • Batch issue edits in one call: bulk_update applies a status/priority/module change to every issue matching a filter (capped at 500) and returns the affected count - triage that was N round-trips is now one.
  • Schedule issues over MCP: create_issue and update_issue now accept start_date and target_date, which already existed everywhere but the MCP layer.
  • Clear fields, not just set them: MCP can unassign an issue's module, move a page back to the folder root, and set or clear project and module emoji (empty string clears; omitted still skips).
  • Find what's stuck: list_issues gains a blocked=true filter - the inverse of workable - surfacing each blocked issue's unresolved blockers.
  • Comments join full-text search: comment threads are now indexed alongside issues and pages across search, MCP, and the web UI, with hits linking back to their parent issue or page.
  • Duplicate relations are visible: issues linked as duplicate now show that relation in get_issue, MCP output, and markdown export - it was previously write-only.
  • Page listings paginate: list_resources(page) honors the limit/offset it always documented, with the same over-fetch has-more hint as issue listings.

Account and instance settings

  • Account settings: profile editing (display name, email), change password, and sign-out-everywhere. Changing your password revokes every other session - a stolen token dies the moment you rotate - while your current browser stays signed in.
  • Instance settings: a DB-backed, admin-gated settings surface - name your instance, open or close signup, toggle authorization enforcement, and enable single-user auto-login (skip the login screen entirely on a personal single-account instance). Editable in the UI or via lific instance set.
  • Connected-tools flow redesigned: a stepped connect modal with per-OS config paths, masked keys, copyable command chips, and real brand logos for every supported client.

A place to land

  • My Work home dashboard: the new default landing page - your active issues grouped by project, recently viewed items, pinned pages, a cross-project activity digest, and quick actions. Login and signup land here now.
  • Insights: a per-project analytics tab - created-vs-closed weekly trends (hand-rolled SVG, reopen-aware closure counting), current status/priority/module distributions, and most-active actors, with a 4/12/26/52-week window.

A faster issue surface

  • Saved views: persist any filter/group/sort/layout combo as a named per-user view, switchable from the topbar, with a default view that auto-applies per project. Private to each user, project-visibility enforced.
  • Board v2: swimlanes by module or priority (drag across a lane updates both status and the lane field in one move), collapsible columns that stay valid drop targets, and proper scroll-snap columns on mobile.
  • Issue peek panel: preview an issue in a slide-over (bottom sheet on mobile) without leaving the list or board - quick status/priority/module edits included. Cmd/ctrl-click a board card or use the row's hover affordance.
  • Keyboard-first navigation: j/k focus that survives refetches, x to select, enter to open, space to peek, s/p/m open pickers on the focused row (shift+S/P keep the old quick-cycle), and a ? help overlay generated from a single shortcut registry so it can't drift from reality.
  • Undo: status, priority, and module changes (from the list, board drags, detail view, and bulk operations) now confirm with a toast carrying a real Undo action. One unified toast system across the app (accessible live regions, hover/focus pauses dismissal).
  • Undo-able deletes. Deleting issues (single or bulk) is deferred: rows vanish instantly, a toast offers Undo, and the actual delete only fires once the toast closes. Closing the tab flushes the pending delete instead of silently cancelling it.

Everywhere else

  • Issue references come alive: bare identifiers (LIF-42, PROJ-DOC-3) auto-link in all rendered markdown (code blocks correctly excluded), show rich hover preview cards, and autocomplete in every editor via # or an identifier prefix at the caret. Issue chips learned tricks too: shift-click opens the peek panel, right-click offers preview and open-in-new-tab.
  • Path-style deep links: plain URLs like /LIF/issues/LIF-42 resolve into the app at boot, so links from dashboards, chats, and agents land directly on the right view.
  • Appearance system: six accent presets (all AA-verified in both modes, including a fix to the stock indigo dark-mode contrast), comfortable/compact density, three font scales, and a reduced-motion preference that every animation in the app honors - applied before first paint, no flash.
  • Motion & loading polish: content-shaped skeletons replace spinners on every heavy route, list rows and board cards glide on reorder, routes fade in quietly, and transition durations are normalized app-wide.
  • Markdown formatting toolbar: bold, italic, headings, lists, checklists, code, links, and quotes in every editor, with Cmd+B / Cmd+I / Cmd+Shift+K shortcuts. Transforms toggle cleanly and play nice with native undo.
  • Live timestamps: relative times ("2m ago") tick as time passes instead of going stale, and hovering any of them shows the exact date.
  • Consistent breadcrumbs: issue, page, module, and plan detail views share one breadcrumb trail (PROJ > Issues > LIF-42) instead of ad-hoc back arrows.
  • No silent failures: saves, deletes, comments, and clipboard copies that used to fail without a word now surface an error toast; copy actions confirm.
  • Edit and merge labels. Labels can now be renamed and recolored in place, and duplicate labels can be merged (issues and pages re-tagged, source label removed) - with a full label manager and color picker in Project Settings.
  • Pinned pages stay at the top of the page list.

Design and mobile

  • Login and signup redesigned around the brand - and meet Lizzy, the mascot who now staffs the empty states, error pages, and the sign-in screen.
  • Real error pages: a 404 and a global error boundary that recover gracefully without leaking internals.
  • Light theme contrast overhaul and a typography token system (display through micro) replacing ad-hoc pixel sizes app-wide.
  • Mobile pass: off-canvas navigation drawer, reflowed topbars, issue rows, and detail views, board snap-scroll columns, and touch-reachable actions.
  • Topbar filters consolidated into a single Filter popover; projects reorder by drag in the sidebar, with collapsible per-project sub-navigation.

Security fixes

  • Password changes revoke all other sessions - a stolen session token no longer survives a password rotation.
  • The session cookie's Secure flag is now gated on the request scheme, fixing broken logins on plain-http and localhost deploys.
  • OAuth approval CSRF tokens are bound to the approving session (previously forgeable across users), the CSRF MAC comparison is constant-time, and token revocation validates its bearer before acting.
  • API key expiry is now enforced. expires_at existed in the schema and was shown by lific key list, but the auth path never checked it - an expired key authenticated forever. Both key lookups now reject expired keys, and lific key create gains --expires.

Performance

  • Issue list label hydration is O(1) - one query instead of one per row.
  • Hot read paths cache prepared statements.
  • list_plans is 2x faster via page-then-aggregate.

Upgrading

  • The database upgrades itself automatically on first launch. Upgrading from any 1.x is safe and needs no manual steps.
  • Fresh installs enforce authorization by default; upgrades from 1.x keep it off. An instance that already has users behaves exactly as before until an admin flips authz_enforced in Instance Settings or runs lific instance set --authz-enforced true. Project leads are backfilled as members automatically, so flipping it on does not lock anyone out of their own projects.
  • Unbound API keys are operator-trusted and bypass authorization in enforced mode. Review them with lific key list and revoke any you don't recognize.