Files
arca/PLAN.md
Kyle Isom e44dd382dd M6: shell completions with dynamic alias lookup
Add ValidArgsFunction to mount and unmount commands that reads config
aliases for tab completion. Install zsh, bash, and fish completion
scripts via flake postInstall. Update PLAN.md with post-1.0 roadmap.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 08:35:19 -07:00

3.7 KiB

arca — Post-1.0 Plan

Current State (v1.0.0)

Released. FIDO2/passphrase/keyfile/TPM2 unlock with method sequencing, idempotent mount/unmount, config aliases, init command, status command, NixOS LD_LIBRARY_PATH workaround for cryptsetup token plugins, unit tests, nix flake packaging.


v1.1: Shell completions and verbose mode

M6: Shell completions

Cobra generates completion scripts. Wire them up so alias names complete in the shell.

Files changed

  • cmd/root.go
  • flake.nix

Work

  1. Cobra provides completion subcommand by default (arca completion zsh, arca completion bash, etc.). Verify it works.

  2. Add a custom ValidArgsFunction to mountCmd and unmountCmd that reads the config and returns alias names + device paths from arca status. This gives dynamic completion for:

    arca mount <TAB>   -> backup  media  /dev/sda1
    arca unmount <TAB> -> backup  media
    
  3. In flake.nix, install the zsh completion file to $out/share/zsh/site-functions/_arca so NixOS picks it up automatically.

M7: Verbose mode

Add -v / --verbose flag to aid debugging (e.g., the FIDO2 plugin discovery issue we hit during development).

Files changed

  • cmd/root.go
  • internal/cryptsetup/cryptsetup.go
  • internal/unlock/unlock.go
  • internal/udisks/client.go

Work

  1. Add a --verbose / -v persistent flag on the root command. Store in a package-level Verbose bool.

  2. In cryptsetup.Open: print the full command being executed (including LD_LIBRARY_PATH and privilege wrapper).

  3. In findTokenPluginDir: print which directory was found (or that none was found).

  4. In unlock.Unlock: print which method is being attempted before each try.

  5. In udisks.NewClient: print the D-Bus connection status.

Use fmt.Fprintf(os.Stderr, "arca: ...") for verbose output — no logging framework needed.


v1.2: Config management and cleanup

M8: arca add <device>

Add a single device to an existing config without regenerating everything.

Files changed

  • cmd/add.go (new)
  • internal/config/config.go

Work

  1. New subcommand: arca add /dev/sda1 or arca add --uuid <uuid>.

  2. Resolve the device via udisks2 to get UUID.

  3. Generate a UUID-prefix alias (same as init).

  4. Prompt for alias name (default: UUID prefix), methods (default: passphrase), and optional mountpoint.

  5. Append to existing config. If the UUID is already configured, print the existing alias and exit.

  6. Add config.Save(*Config) to write the config file (currently only init writes, with inline marshaling).

M9: init --merge

Merge newly discovered devices into an existing config without overwriting existing entries.

Files changed

  • cmd/init.go
  • internal/config/config.go

Work

  1. Add --merge flag to init. When set, load existing config first.

  2. For each discovered device, skip if its UUID already exists in config (regardless of alias name).

  3. Add new devices with UUID-prefix aliases.

  4. Write the merged config.

This replaces the current --force behavior for the common case of "I plugged in a new drive."

M10: Mount cleanup

Privileged unmount leaves empty directories under /mnt/.

Files changed

  • internal/cryptsetup/cryptsetup.go
  • cmd/unmount.go

Work

  1. After Unmount, attempt rmdir on the mount point. Only remove if empty (not rm -rf).

  2. Use privileged rmdir since the directory was created with privilege.


Non-goals

  • --dry-run flag
  • --json output for status
  • udev auto-mount on plug
  • Keyfile creation/management
  • Multiple config files or config includes
  • Systemd mount unit integration