npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@phibar/dotsloth

v0.4.0

Published

Sync your dots, be a sloth - Dev environment sync CLI for macOS

Readme

dotsloth

Sync your dots, be a sloth. A macOS CLI that keeps your development environment — git identities, dotfiles, secrets, env files and Claude Code config — in sync across machines via iCloud Drive and the macOS Keychain.

npm downloads release node license oclif

What it does

  • Git identities per organization. Generates ~/.gitconfig with includeIf rules so repos under ~/github/<org>/ automatically use the right name, email and signing key. Every command that changes config re-applies it immediately.
  • Dotfiles via iCloud. ~/.gitconfig, ~/.zprofile and ~/.ssh/config are symlinked to versions stored in iCloud Drive.
  • Secrets in the Keychain. Sensitive exports are pulled out of shell profiles and stored encrypted, never in a synced plaintext file.
  • Env files. .env and friends are gitignored by design, so git never saves them. dotsloth env backs them up and restores them after a reinstall.
  • Claude Code. Share settings.json, project memory and conversation history between machines.
  • Mail. Back up Mail rules and signatures and recreate them on a new machine, with a checklist for the accounts that need a manual sign-in.
  • Pre-reinstall safety. dotsloth doctor refuses to say "safe to wipe" while anything would be lost.
  • Periodic sync. A launchd agent keeps everything current.
  • Web UI. dotsloth ui opens a local web interface for all of the above.

Quick start

npm install -g @phibar/dotsloth
dotsloth init
dotsloth org add phibar --email [email protected] --username phibar
dotsloth clone [email protected]:phibar/some-repo.git

Web UI

dotsloth ui

Starts a local server, prints a sign-in link and opens it in your browser. Everything the CLI does is there: a dashboard with sync, organizations and cloning, a config editor, secrets, env files, doctor, Mail, Claude Code and the periodic sync. Press Ctrl+C to stop it.

Organizations

Secrets Env files

| Flag | | |---|---| | --port <n> | Listen on a fixed port (default: a free one) | | --no-open | Print the link without opening the browser |

Security model. The server can reach your Keychain, config and every repository, so it only answers the browser tab it opened:

  • It listens on 127.0.0.1 only.
  • The printed link carries a random token. Opening it swaps the token for an HttpOnly, SameSite=Strict session cookie and removes it from the address bar; every other request needs that cookie. The link stays valid while this dotsloth ui runs (so you can sign in again after closing the browser) - treat it like a password, and stop the server when you are done.
  • Requests with a foreign Host (DNS rebinding) or, for anything that changes state, a foreign Origin (CSRF) are refused.
  • Secret values are fetched one at a time when you click Reveal or Copy; there is no way to read several at once. Env file contents are never sent.
  • Deleting an organization's repositories requires typing its name, and the server checks it again.
  • Mail is only contacted when you ask: it is driven via AppleScript, and macOS asks once for permission to control it.

Reinstalling your Mac

See BOOTSTRAP.md for the full ordered procedure. The short version — before you wipe:

dotsloth doctor          # exits non-zero while anything would be lost
dotsloth env push
dotsloth claude memory push
brctl log --wait --shorten   # a file in iCloud is not a backup until uploaded

And on the new machine: Homebrew → node → iCloud sign-in → dotsloth → SSH key → dotsloth sync → clone → dotsloth env pull.

Where things live

| What | Where | |---|---| | Config | ~/Library/Mobile Documents/com~apple~CloudDocs/development/dotsloth/config.json | | Dotfiles | .../development/dotsloth/dotfiles/ | | Org gitconfigs | .../development/dotsloth/organizations/ | | Env files | .../development/dotsloth/envs/<org>/<repo>/ | | Claude Code | .../development/dotsloth/claude/ | | Secrets | macOS Keychain, account dotsloth | | Repos | ~/github/<org>/<repo> |

Development

npm install
npm run build     # CLI (tsc) and web app (vite) into dist/
npm test          # mocha + vitest + biome
./bin/run.js <command>

Working on the web app with hot reload:

npm run dev:ui

It starts dotsloth ui from source, then Vite with the server's sign-in link (so /api is proxied with the session cookie), and opens http://localhost:5173. Ctrl+C stops both. npm run dev:web starts only Vite; it reads the link from DOTSLOTH_UI_URL.

The code is layered so the CLI and the web UI share one implementation: src/core holds the logic (typed results, no prompts or printing), src/commands and src/cli are the terminal front end, src/server is the web API, and web/ is the React app.

Usage

$ npm install -g @phibar/dotsloth
$ dotsloth COMMAND
running command...
$ dotsloth (--version)
@phibar/dotsloth/0.4.0 linux-x64 node-v24.21.0
$ dotsloth --help [COMMAND]
USAGE
  $ dotsloth COMMAND
...

Commands

dotsloth claude history [DIRECTION]

Share Claude Code conversation history between machines

USAGE
  $ dotsloth claude history [DIRECTION] [--dry-run] [--retention <value>]

ARGUMENTS
  [DIRECTION]  (status|push|pull) [default: status] status | push | pull

FLAGS
  --dry-run            Show what would change without writing
  --retention=<value>  [default: 90] Only sync sessions touched within this many days

DESCRIPTION
  Share Claude Code conversation history between machines

EXAMPLES
  $ dotsloth claude history

  $ dotsloth claude history push

  $ dotsloth claude history pull --retention 30

See code: src/commands/claude/history.ts

dotsloth claude link

Share Claude Code settings between machines via the dotsloth store

USAGE
  $ dotsloth claude link [--dry-run]

FLAGS
  --dry-run  Show what would change without writing

DESCRIPTION
  Share Claude Code settings between machines via the dotsloth store

EXAMPLES
  $ dotsloth claude link

  $ dotsloth claude link --dry-run

See code: src/commands/claude/link.ts

dotsloth claude memory [DIRECTION]

Share Claude Code project memory between machines

USAGE
  $ dotsloth claude memory [DIRECTION] [--dry-run]

ARGUMENTS
  [DIRECTION]  (status|push|pull) [default: status] status | push | pull

FLAGS
  --dry-run  Show what would change without writing

DESCRIPTION
  Share Claude Code project memory between machines

EXAMPLES
  $ dotsloth claude memory

  $ dotsloth claude memory push

  $ dotsloth claude memory pull

See code: src/commands/claude/memory.ts

dotsloth claude status

Show which Claude Code config is shared between machines

USAGE
  $ dotsloth claude status

DESCRIPTION
  Show which Claude Code config is shared between machines

EXAMPLES
  $ dotsloth claude status

See code: src/commands/claude/status.ts

dotsloth clone URL

Clone a repository to the correct organization folder

USAGE
  $ dotsloth clone URL [-o <value>]

ARGUMENTS
  URL  Repository URL to clone

FLAGS
  -o, --org=<value>  Override organization (use a different org than detected)

DESCRIPTION
  Clone a repository to the correct organization folder

EXAMPLES
  $ dotsloth clone [email protected]:phibar/some-repo.git

  $ dotsloth clone https://github.com/ipfs/kubo

  $ dotsloth clone [email protected]:fork/repo.git --org phibar

See code: src/commands/clone.ts

dotsloth daemon install

Install the periodic sync agent (runs dotsloth sync on a schedule)

USAGE
  $ dotsloth daemon install [--interval <value>]

FLAGS
  --interval=<value>  [default: 86400] Seconds between syncs (default: once a day)

DESCRIPTION
  Install the periodic sync agent (runs dotsloth sync on a schedule)

EXAMPLES
  $ dotsloth daemon install

  $ dotsloth daemon install --interval 3600

See code: src/commands/daemon/install.ts

dotsloth daemon status

Show whether periodic sync is installed and when it last ran

USAGE
  $ dotsloth daemon status

DESCRIPTION
  Show whether periodic sync is installed and when it last ran

EXAMPLES
  $ dotsloth daemon status

See code: src/commands/daemon/status.ts

dotsloth daemon uninstall

Remove the periodic sync agent

USAGE
  $ dotsloth daemon uninstall

DESCRIPTION
  Remove the periodic sync agent

EXAMPLES
  $ dotsloth daemon uninstall

See code: src/commands/daemon/uninstall.ts

dotsloth doctor

Check whether anything would be lost if this machine were wiped

USAGE
  $ dotsloth doctor [--offline]

FLAGS
  --offline  Skip GitHub PR lookups (faster, less precise)

DESCRIPTION
  Check whether anything would be lost if this machine were wiped

EXAMPLES
  $ dotsloth doctor

  $ dotsloth doctor --offline

See code: src/commands/doctor.ts

dotsloth env list

List env files found in your repos and whether they are backed up

USAGE
  $ dotsloth env list [--unsaved]

FLAGS
  --unsaved  Only show files that are not yet backed up

DESCRIPTION
  List env files found in your repos and whether they are backed up

EXAMPLES
  $ dotsloth env list

  $ dotsloth env list --unsaved

See code: src/commands/env/list.ts

dotsloth env pull

Restore env files from the dotsloth store into your repos

USAGE
  $ dotsloth env pull [--dry-run] [-f]

FLAGS
  -f, --force    Overwrite local files that differ
      --dry-run  Show what would be restored without writing

DESCRIPTION
  Restore env files from the dotsloth store into your repos

EXAMPLES
  $ dotsloth env pull

  $ dotsloth env pull --force

See code: src/commands/env/pull.ts

dotsloth env push

Copy env files from your repos into the dotsloth store

USAGE
  $ dotsloth env push [--dry-run] [-f]

FLAGS
  -f, --force    Overwrite store entries that differ
      --dry-run  Show what would be copied without writing

DESCRIPTION
  Copy env files from your repos into the dotsloth store

EXAMPLES
  $ dotsloth env push

  $ dotsloth env push --dry-run

See code: src/commands/env/push.ts

dotsloth help [COMMAND]

Display help for dotsloth.

USAGE
  $ dotsloth help [COMMAND...] [-n]

ARGUMENTS
  [COMMAND...]  Command to show help for.

FLAGS
  -n, --nested-commands  Include all nested commands in the output.

DESCRIPTION
  Display help for dotsloth.

See code: @oclif/plugin-help

dotsloth init

Initialize dotsloth on this machine

USAGE
  $ dotsloth init [-f] [--skip-secrets] [--skip-ssh]

FLAGS
  -f, --force         Overwrite existing configuration
      --skip-secrets  Skip secrets extraction from zprofile
      --skip-ssh      Skip SSH keychain setup

DESCRIPTION
  Initialize dotsloth on this machine

EXAMPLES
  $ dotsloth init

See code: src/commands/init.ts

dotsloth mail export

Export Mail accounts, rules and signatures to the dotsloth store

USAGE
  $ dotsloth mail export [--dry-run]

FLAGS
  --dry-run  Show what would be exported without writing

DESCRIPTION
  Export Mail accounts, rules and signatures to the dotsloth store

EXAMPLES
  $ dotsloth mail export

  $ dotsloth mail export --dry-run

See code: src/commands/mail/export.ts

dotsloth mail restore

Recreate Mail signatures and rules, and list the accounts to re-add

USAGE
  $ dotsloth mail restore [--accounts-only] [--dry-run]

FLAGS
  --accounts-only  Only print the account checklist
  --dry-run        Show what would be recreated without changing Mail

DESCRIPTION
  Recreate Mail signatures and rules, and list the accounts to re-add

EXAMPLES
  $ dotsloth mail restore

  $ dotsloth mail restore --dry-run

See code: src/commands/mail/restore.ts

dotsloth mail status

Compare Mail on this machine with what is in the dotsloth store

USAGE
  $ dotsloth mail status

DESCRIPTION
  Compare Mail on this machine with what is in the dotsloth store

EXAMPLES
  $ dotsloth mail status

See code: src/commands/mail/status.ts

dotsloth org add [NAME]

Add a new organization configuration

USAGE
  $ dotsloth org add [NAME] [-e <value>] [-u <value>]

ARGUMENTS
  [NAME]  Organization name (e.g., phibar)

FLAGS
  -e, --email=<value>     Git email for this organization
  -u, --username=<value>  Git username for this organization

DESCRIPTION
  Add a new organization configuration

EXAMPLES
  $ dotsloth org add

  $ dotsloth org add phibar --email [email protected] --username phibar

See code: src/commands/org/add.ts

dotsloth org list

List configured organizations

USAGE
  $ dotsloth org list [--json]

FLAGS
  --json  Output as JSON

DESCRIPTION
  List configured organizations

EXAMPLES
  $ dotsloth org list

See code: src/commands/org/list.ts

dotsloth org remove NAME

Remove an organization configuration

USAGE
  $ dotsloth org remove NAME [--delete-repos] [-f]

ARGUMENTS
  NAME  Organization name to remove

FLAGS
  -f, --force         Skip confirmation
      --delete-repos  Also delete the repository folder

DESCRIPTION
  Remove an organization configuration

EXAMPLES
  $ dotsloth org remove phibar

See code: src/commands/org/remove.ts

dotsloth org update [NAME]

Update an organization configuration

USAGE
  $ dotsloth org update [NAME] [-e <value>] [-u <value>]

ARGUMENTS
  [NAME]  Organization name to update

FLAGS
  -e, --email=<value>     New git email
  -u, --username=<value>  New git username

DESCRIPTION
  Update an organization configuration

EXAMPLES
  $ dotsloth org update

  $ dotsloth org update phibar

  $ dotsloth org update phibar --email [email protected]

See code: src/commands/org/update.ts

dotsloth secret add NAME

Add or update a secret in macOS Keychain

USAGE
  $ dotsloth secret add NAME [-v <value>]

ARGUMENTS
  NAME  Secret name (e.g., AWS_ACCESS_KEY_ID)

FLAGS
  -v, --value=<value>  Secret value (not recommended - use prompt instead)

DESCRIPTION
  Add or update a secret in macOS Keychain

EXAMPLES
  $ dotsloth secret add AWS_ACCESS_KEY_ID

  $ dotsloth secret add OPENAI_API_KEY --value sk-...

See code: src/commands/secret/add.ts

dotsloth secret export

Export all secrets (for debugging/migration)

USAGE
  $ dotsloth secret export [-f shell|json]

FLAGS
  -f, --format=<option>  [default: shell] Output format
                         <options: shell|json>

DESCRIPTION
  Export all secrets (for debugging/migration)

EXAMPLES
  $ dotsloth secret export

See code: src/commands/secret/export.ts

dotsloth secret get NAME

Get a secret value from Keychain

USAGE
  $ dotsloth secret get NAME

ARGUMENTS
  NAME  Secret name to retrieve

DESCRIPTION
  Get a secret value from Keychain

EXAMPLES
  $ dotsloth secret get AWS_ACCESS_KEY_ID

See code: src/commands/secret/get.ts

dotsloth secret list

List all secret names stored in Keychain

USAGE
  $ dotsloth secret list

DESCRIPTION
  List all secret names stored in Keychain

EXAMPLES
  $ dotsloth secret list

See code: src/commands/secret/list.ts

dotsloth secret load

Output export statements for all secrets (for use in shell profile)

USAGE
  $ dotsloth secret load

DESCRIPTION
  Output export statements for all secrets (for use in shell profile)

EXAMPLES
  $ dotsloth secret load

  eval "$(dotsloth secret load)"

See code: src/commands/secret/load.ts

dotsloth secret remove NAME

Remove a secret from Keychain

USAGE
  $ dotsloth secret remove NAME [-f]

ARGUMENTS
  NAME  Secret name to remove

FLAGS
  -f, --force  Skip confirmation

DESCRIPTION
  Remove a secret from Keychain

EXAMPLES
  $ dotsloth secret remove AWS_ACCESS_KEY_ID

See code: src/commands/secret/remove.ts

dotsloth status

Show current dotsloth configuration status

USAGE
  $ dotsloth status [-v]

FLAGS
  -v, --verbose  Show detailed status

DESCRIPTION
  Show current dotsloth configuration status

EXAMPLES
  $ dotsloth status

See code: src/commands/status.ts

dotsloth sync

Sync configurations from iCloud Drive

USAGE
  $ dotsloth sync [--dry-run] [-f]

FLAGS
  -f, --force    Force overwrite local files
      --dry-run  Show what would be synced without making changes

DESCRIPTION
  Sync configurations from iCloud Drive

EXAMPLES
  $ dotsloth sync

  $ dotsloth sync --dry-run

See code: src/commands/sync.ts

dotsloth ui

Manage dotsloth in the browser (local web interface)

USAGE
  $ dotsloth ui [--open] [--port <value>]

FLAGS
  --[no-]open     Open the browser
  --port=<value>  Port to listen on (default: a free one)

DESCRIPTION
  Manage dotsloth in the browser (local web interface)

EXAMPLES
  $ dotsloth ui

  $ dotsloth ui --port 4321 --no-open

See code: src/commands/ui.ts