https://github.com/11ways/sym
A user-friendly symbolic link manager for managing links in ~/.local/bin
https://github.com/11ways/sym
Last synced: about 2 months ago
JSON representation
A user-friendly symbolic link manager for managing links in ~/.local/bin
- Host: GitHub
- URL: https://github.com/11ways/sym
- Owner: 11ways
- License: mit
- Created: 2025-10-31T16:24:28.000Z (9 months ago)
- Default Branch: main
- Last Pushed: 2026-04-16T21:46:01.000Z (3 months ago)
- Last Synced: 2026-04-16T23:25:26.604Z (3 months ago)
- Language: Shell
- Size: 136 KB
- Stars: 2
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
Awesome Lists containing this project
README
# sym - Symbolic Link Manager
A simple, user-friendly command-line tool for managing symbolic links in `~/.local/bin`.
**Homepage:**



## Table of Contents
- [Installation](#installation)
- [Quick Start](#quick-start)
- [Commands](#commands)
- [Creating Links](#creating-links)
- [Listing Links](#listing-links)
- [Inspecting Links](#inspecting-links)
- [Removing Links](#removing-links)
- [Verifying Links](#verifying-links)
- [Fixing Broken Links](#fixing-broken-links)
- [Options](#options)
- [Output Formats](#output-formats)
- [Configuration](#configuration)
- [Examples](#examples)
- [Tips & Best Practices](#tips--best-practices)
- [Troubleshooting](#troubleshooting)
- [Contributing](#contributing)
- [License](#license)
## Installation
### Homebrew (Recommended for macOS)
The easiest way to install sym on macOS is using Homebrew:
```bash
brew install 11ways/sym/sym
```
This automatically installs:
- The `sym` command in your PATH
- The man page (accessible via `man sym`)
- All dependencies
**Verify installation:**
```bash
sym --version
man sym
```
### One-Line Install (Linux & macOS)
For a quick installation on any Unix-like system:
```bash
curl -fsSL https://raw.githubusercontent.com/11ways/sym/main/install.sh | bash
```
**Or safer (inspect the script first):**
```bash
curl -fsSL https://raw.githubusercontent.com/11ways/sym/main/install.sh -o install.sh
less install.sh # Review the script
bash install.sh
```
This installs to `~/.local/bin` and builds the man page if `pandoc` is available.
**For Linux users:**
Homebrew also works on Linux! Install Homebrew first, then:
```bash
brew install 11ways/sym/sym
```
### Install with Makefile
The Makefile automates installation of both the script and man page:
```bash
# Clone the repository
git clone https://github.com/11ways/sym.git
cd sym
# Install to user directory (no sudo required)
make install-local
# Or install system-wide (requires sudo)
sudo make install
```
**What gets installed:**
- Script: `~/.local/bin/sym` (or `/usr/local/bin/sym` for system-wide)
- Man page: `~/.local/share/man/man1/sym.1.gz` (or `/usr/local/share/man/man1/sym.1.gz`)
**View the man page:**
```bash
# Add to your shell config (~/.bashrc or ~/.zshrc)
export MANPATH="$MANPATH:$HOME/.local/share/man"
# Then view the manual
man sym
```
**Requirements:**
- `pandoc` - for building the man page ([install instructions](https://pandoc.org/installing.html))
- `gzip` - usually pre-installed
### Manual Install
1. Download `sym.sh` to a directory of your choice
2. Make it executable: `chmod +x sym.sh`
3. Add it to your PATH or create a symlink in `~/.local/bin`
### Verify Installation
```bash
sym --version
# Output: sym version 1.2.0
```
### Uninstalling
**Homebrew:**
```bash
brew uninstall sym
```
**Makefile:**
```bash
make uninstall-local # or make uninstall for system-wide
```
## Quick Start
```bash
# Create a symlink
sym mycommand /path/to/executable
# List all symlinks
sym ls
# Show information about a link
sym info mycommand
# Remove a link
sym rm mycommand
```
## Commands
### Creating Links
Create a symbolic link with an explicit name:
```bash
sym
```
Or let sym prompt you for a name:
```bash
sym
# You'll be prompted to enter a link name
```
**Examples:**
```bash
# Create a link to Sublime Text
sym sublime /Applications/Sublime\ Text.app/Contents/SharedSupport/bin/subl
# Create a link to a Python script (will prompt for name)
sym ~/scripts/my-tool.py
# Create multiple links
sym docker-compose /usr/local/bin/docker-compose
sym dc /usr/local/bin/docker-compose # Short alias
```
**Alternative Syntax:**
```bash
sym create # Will prompt for name
sym create
```
### Listing Links
List all symbolic links:
```bash
sym ls
```
Show only broken links:
```bash
sym ls --broken
```
Output in different formats:
```bash
sym ls --format=json
sym ls --format=csv
```
**Example Output:**
```
Existing symbolic links in '~/.local/bin':
notch → ~/Repos/wp-notch/notch.sh
sym → ~/Repos/sym/sym.sh
swatch → ~/swatch/swatch.sh
speak → ~/Repos/simple-speaker/speak.sh
km → /Applications/Keyboard Maestro.app/Contents/MacOS/keyboardmaestro
yap → ~/repos/slack-extract/yap (Does not exist!)
```
### Inspecting Links
Show detailed information about a specific link:
```bash
sym info
```
Or use the shorthand:
```bash
sym
```
**Example Output:**
```
→ From: ~/.local/bin/sublime
→ To: /Applications/Sublime Text.app/Contents/SharedSupport/bin/subl
→ Created: 2025-10-31 14:23:45
→ Size: 2.4MB
→ Type: File
To delete:
sym rm sublime
To change the destination:
sym sublime
```
### Removing Links
Remove a symbolic link (with confirmation):
```bash
sym rm
```
**Aliases:**
```bash
sym remove
sym delete
```
### Verifying Links
Check all symbolic links and report their status:
```bash
sym verify
```
**Example Output:**
```
Verifying symbolic links...
✓ notch → ~/Repos/wp-notch/notch.sh
✓ sym → ~/Repos/sym/sym.sh
✗ yap → ~/repos/slack-extract/yap (broken)
⚠ Warning: Found 1 broken link(s) out of 3 total.
To remove broken links, run: sym fix
```
**Aliases:**
```bash
sym check
```
### Fixing Broken Links
Automatically remove all broken symbolic links:
```bash
sym fix
```
This will:
1. Find all broken links
2. Show you what will be removed
3. Ask for confirmation
4. Remove the broken links
**Aliases:**
```bash
sym clean
```
## Options
### Global Options
These options work with all commands:
| Option | Short | Description |
|--------|-------|-------------|
| `--help` | `-h` | Show help message |
| `--version` | `-v` | Show version information |
| `--force` | `-f` | Skip all confirmation prompts |
| `--dry-run` | `-n` | Preview changes without making them |
### Command-Specific Options
**For `sym ls`:**
| Option | Description |
|--------|-------------|
| `--broken` | Show only broken links |
| `--format=FORMAT` | Output format: `text`, `json`, or `csv` |
### Using Options
```bash
# Create without confirmation
sym -f mylink /path/to/file
# Preview what would happen
sym -n mylink /path/to/file
# Force remove without prompt
sym -f rm oldlink
# List broken links in JSON format
sym ls --broken --format=json
```
## Output Formats
### Text (Default)
Human-readable, color-coded output perfect for terminal use.
```bash
sym ls
```
### JSON
Machine-readable format for scripting and integrations:
```bash
sym ls --format=json
```
```json
[
{
"name": "sublime",
"target": "/Applications/Sublime Text.app/Contents/SharedSupport/bin/subl",
"status": "ok",
"size": "2.4MB",
"created": "2025-10-31 14:23:45"
},
{
"name": "oldtool",
"target": "~/bin/removed-tool",
"status": "broken",
"size": "",
"created": "2025-09-15 10:30:22"
}
]
```
### CSV
Spreadsheet-friendly format:
```bash
sym ls --format=csv
```
```csv
name,target,status,size,created
sublime,/Applications/Sublime Text.app/Contents/SharedSupport/bin/subl,ok,2.4MB,2025-10-31 14:23:45
oldtool,~/bin/removed-tool,broken,,2025-09-15 10:30:22
```
## Configuration
### Environment Variables
| Variable | Default | Description |
|----------|---------|-------------|
| `SYM_DIR` | `~/.local/bin` | Directory where symlinks are created |
| `NO_COLOR` | (unset) | Disable colored output |
### Custom Directory
Set a different directory for your symlinks:
```bash
export SYM_DIR="$HOME/bin"
sym mylink /path/to/file
```
### Disable Colors
```bash
# Temporarily
NO_COLOR=1 sym ls
# Permanently (add to ~/.bashrc or ~/.zshrc)
export NO_COLOR=1
```
### Add to PATH
Make sure your symlink directory is in your PATH:
```bash
# Add to ~/.bashrc or ~/.zshrc
export PATH="$PATH:$HOME/.local/bin"
```
## Examples
### Common Use Cases
**Link to GUI Applications (macOS):**
```bash
# Sublime Text
sym sublime /Applications/Sublime\ Text.app/Contents/SharedSupport/bin/subl
# Visual Studio Code
sym code /Applications/Visual\ Studio\ Code.app/Contents/Resources/app/bin/code
# Keyboard Maestro
sym km /Applications/Keyboard\ Maestro.app/Contents/MacOS/keyboardmaestro
```
**Link to Scripts:**
```bash
# Python script
sym mytool ~/scripts/mytool.py
# Shell script
sym backup ~/scripts/backup.sh
# Node.js script
sym deploy ~/projects/deployer/cli.js
```
**Create Short Aliases:**
```bash
# Long command with short alias
sym dc /usr/local/bin/docker-compose
sym k /usr/local/bin/kubectl
sym tf /usr/local/bin/terraform
```
**Batch Cleanup:**
```bash
# Find and fix all broken links
sym verify
sym fix
# Or just fix directly
sym fix -f # Skip confirmation
```
**Export Link Inventory:**
```bash
# Create a backup of all links
sym ls --format=json > ~/symlinks-backup.json
# Create a CSV for documentation
sym ls --format=csv > ~/symlinks-inventory.csv
```
### Integration with Scripts
**Check if a link exists:**
```bash
if sym info mylink &>/dev/null; then
echo "Link exists"
else
echo "Link doesn't exist"
fi
```
**Process all broken links:**
```bash
# Get broken links as JSON
broken_links=$(sym ls --broken --format=json)
# Process with jq
echo "$broken_links" | jq -r '.[].name' | while read link; do
echo "Broken: $link"
done
```
**Automated cleanup:**
```bash
# Remove all broken links without prompts
sym fix -f
```
## Tips & Best Practices
### Naming Conventions
✅ **Good:**
- Use lowercase names: `mycommand`
- Use hyphens for multi-word names: `my-command`
- Keep names short and memorable: `dc` instead of `docker-compose-wrapper`
❌ **Avoid:**
- Spaces in names: `my command`
- Special characters: `my@command`, `my$cmd`
- Starting with a dot: `.mycommand` (hidden files)
### Organization
- **Keep it simple**: Don't create too many symlinks
- **Use descriptive names**: Others should understand what each link does
- **Regular maintenance**: Run `sym verify` periodically
- **Document custom links**: Keep a README in `~/.local/bin`
### Safety
- **Always review**: Check `sym info` before removing links
- **Use dry-run**: Test with `-n` flag before destructive operations
- **Backup important links**: Export with `sym ls --format=json`
- **Verify after changes**: Run `sym verify` after bulk operations
### Performance
- **Use absolute paths**: Relative paths work but absolute are clearer
- **Check your PATH**: Ensure `~/.local/bin` is in PATH
- **Avoid deep nesting**: Keep source files in accessible locations
## Troubleshooting
### Link not found in PATH
**Problem:** Created a link but can't use it.
**Solution:**
```bash
# Check if directory is in PATH
echo $PATH | grep -q "$HOME/.local/bin" || echo "Not in PATH!"
# Add to PATH (in ~/.bashrc or ~/.zshrc)
export PATH="$PATH:$HOME/.local/bin"
# Reload shell
source ~/.bashrc # or source ~/.zshrc
```
### Permission denied errors
**Problem:** Can't create or remove links.
**Solution:**
```bash
# Check directory permissions
ls -ld ~/.local/bin
# Fix permissions
chmod 755 ~/.local/bin
# If directory doesn't exist
mkdir -p ~/.local/bin
```
### Colors not working
**Problem:** Output is not colored.
**Solution:**
```bash
# Check if NO_COLOR is set
echo $NO_COLOR
# Unset it
unset NO_COLOR
# Check terminal type
echo $TERM
# If TERM is "dumb", use a better terminal
```
### Broken links after moving files
**Problem:** Links break when source files move.
**Solution:**
```bash
# Find all broken links
sym ls --broken
# Fix by recreating
sym rm oldlink
sym oldlink /new/path/to/file
# Or remove all broken links
sym fix
```
### Script not executable
**Problem:** `sym: command not found`
**Solution:**
```bash
# Make script executable
chmod +x sym.sh
# Or use bash explicitly
bash sym.sh --help
```
## Exit Codes
sym uses meaningful exit codes for scripting:
| Code | Meaning |
|------|---------|
| `0` | Success |
| `1` | General error |
| `2` | Not found (file or link doesn't exist) |
| `3` | Permission denied |
| `4` | Invalid argument |
**Example Usage:**
```bash
if sym info mylink; then
echo "Link exists"
else
case $? in
2) echo "Link not found" ;;
3) echo "Permission denied" ;;
*) echo "Unknown error" ;;
esac
fi
```
## Advanced Features
### Custom Destination Directory
```bash
# Set custom directory
export SYM_DIR="$HOME/bin"
# All commands now use ~/bin
sym mylink /path/to/file
```
### Piping Output
```bash
# Count total links
sym ls --format=csv | tail -n +2 | wc -l
# Find links to a specific path
sym ls | grep "/Applications"
# Export only broken links
sym ls --broken --format=json > broken-links.json
```
### Automation
**Weekly maintenance script:**
```bash
#!/bin/bash
# ~/.local/scripts/sym-maintenance.sh
echo "Checking symbolic links..."
sym verify
echo "Cleaning up broken links..."
sym fix -f
echo "Exporting inventory..."
sym ls --format=json > ~/Dropbox/symlinks-backup.json
echo "Done!"
```
**Add to cron:**
```bash
# Run every Sunday at 9 AM
0 9 * * 0 /bin/bash ~/.local/scripts/sym-maintenance.sh
```
## Platform Compatibility
### macOS
✅ Fully supported
- Uses BSD stat commands
- Handles .app bundles correctly
- Supports long paths with spaces
### Linux
✅ Fully supported
- Uses GNU stat commands
- Works with all distributions
- Supports systemd paths
### Windows (WSL)
✅ Supported via WSL (Windows Subsystem for Linux)
- Use Linux commands in WSL
- Can link to Windows executables
- Requires proper PATH configuration
## Performance Notes
- **Fast operations**: All commands run in milliseconds
- **No dependencies**: Pure bash, no external tools required
- **Efficient sorting**: Uses native bash sorting
- **Optional features**: `numfmt` used for better file sizes if available
## Contributing
Contributions are welcome! Here's how you can help:
1. **Report bugs**: Open an issue on GitHub
2. **Suggest features**: Share your ideas in discussions
3. **Submit pull requests**: Fix bugs or add features
4. **Improve documentation**: Help make the docs better
5. **Share feedback**: Let us know how you use sym
### Development
```bash
# Clone the repo
git clone https://github.com/11ways/sym.git
cd sym
# Make changes
vim sym.sh
# Test your changes
./sym.sh --version
./sym.sh ls
# Run with dry-run to test safely
./sym.sh -n mytest /path/to/file
```
### Code Style
- Use `bash` (not `sh`)
- Follow existing formatting
- Add comments for complex logic
- Use meaningful variable names
- Handle errors gracefully
## License
MIT License - see [LICENSE](LICENSE) file for details.
Copyright (c) 2025 Roel van Gils
## Acknowledgments
- Inspired by the need for simple symlink management
- Built with love for the command-line
- Thanks to all contributors and users
## Support
- **Issues**: https://github.com/11ways/sym/issues
- **Discussions**: https://github.com/11ways/sym/discussions
---
**Made with ❤️ by [Roel Van Gils](https://github.com/roelvangils)**
If you find this tool useful, consider giving it a ⭐ on GitHub!