Contributing
dssh is a small, focused project — the kind where a single well-scoped PR can meaningfully move the needle. This page walks through the dev loop.
Where things live
Section titled “Where things live”dssh/├── cmd/dssh/ # main.go — wires version into cli.Execute├── internal/│ ├── cli/ # Cobra commands: add, rm, list, create, edit, delete, config, reset, root│ ├── crypto/ # AES-256-GCM + Argon2id│ ├── db/ # modernc.org/sqlite layer│ ├── model/ # Connection, AuthType, RuntimeConfig, ValidateName│ ├── ssh/ # exec_unix.go, exec_windows.go, askpass script│ ├── sshconfig/ # reader / writer for ~/.ssh/config entries│ └── tui/ # Bubble Tea app: tabs, modals, theme├── install.sh / install.ps1├── Makefile└── README.mdHigh-level dependency flow: cmd → cli → (tui, ssh, db, sshconfig) → (crypto, model). Keep new code respecting that direction — TUI and DB shouldn’t reach into each other.
Dev setup
Section titled “Dev setup”Requires Go 1.26+.
git clone https://github.com/madLinux7/dssh.gitcd dsshgo mod downloadBuild and test:
make build # static CGO-free binary, stripped ldflagsmake test # go test ./...make release # build + UPX compressmake clean # remove binary artifactsmake release requires upx in PATH. If you don’t have it, make build is enough for local work.
The binary lands in the repo root as ./dssh. Run ./dssh --version to verify the build embedded the git-describe tag via ldflags.
Running tests
Section titled “Running tests”go test ./...Tests live alongside the code in each package (crypto_test.go, model_test.go, sshconfig/read_test.go, sshconfig/write_test.go). New logic that touches crypto or ssh_config parsing should ship with coverage — those two areas are where subtle regressions hurt most.
Trying changes locally
Section titled “Trying changes locally”Because the data dir is ~/.dssh, it’s easy to trash your real connections during dev. Isolate with a throwaway $HOME:
mkdir -p /tmp/dssh-devHOME=/tmp/dssh-dev ./dssh configHOME=/tmp/dssh-dev ./dssh add test root@localhostHOME=/tmp/dssh-dev ./dssh lsWhen you’re done, rm -rf /tmp/dssh-dev.
Code conventions
Section titled “Code conventions”- Keep packages thin. If a new feature needs to cross two layers, add a function at the right layer instead of reaching through.
- Errors are values. Wrap with
fmt.Errorf("... %w", err)when propagating; return sentinel errors where callers branch on them (seesshconfig.ErrNotFound). - No third-party TUI components. The existing Charm stack (Bubble Tea / Bubbles / Lip Gloss) is sufficient — avoid adding new UI deps without a strong reason.
- Comments: explain why, not what. Cross-platform quirks, security-relevant defaults, and non-obvious ordering deserve a line. Straightforward code does not.
- No breaking changes to
~/.dssh/dssh.dbwithout a migration. Users upgrade dssh; their data needs to survive.
Opening a PR
Section titled “Opening a PR”- Fork and branch. One feature per branch, descriptive name.
- Run
go fmt ./...andgo vet ./...before committing. - Add or update tests for behaviour changes. Docs PRs can skip this.
- Keep the diff small. Refactors bundled into feature PRs are harder to review — if you spot cleanup while working, consider a separate PR.
- Describe the why in the PR body. “Adds feature X” is less useful than “Users hit friction when X because Y; this adds X to remove that friction.”
- Link any related issue.
CI (if configured on the repository) runs go test ./... across platforms. Make sure it’s green before requesting review.
Reporting bugs
Section titled “Reporting bugs”Before opening a bug:
- Upgrade to the latest release (
dssh --version). - Reproduce with a clean data dir (
HOME=/tmp/test ./dssh ...) — eliminates local-state oddities. - Capture
dssh <cmd> -- -vvvoutput if the bug involves an ssh connection.
Then file at github.com/madLinux7/dssh/issues with:
dssh --version- OS / terminal / shell
- Minimal steps to reproduce
- Expected vs. actual
Feature requests
Section titled “Feature requests”Feature requests are welcome — but dssh has a small-surface philosophy. Before filing, consider:
- Can this be done with
-- <ssh flags>forwarding? - Does the functionality belong in
ssh_configinstead? - Is it inside the “manage SSH connections” scope, or expanding outward (key gen, agent management, network diagnostics, …)?
Out-of-scope features won’t get an automatic “no” — but they’ll take a stronger case.
Security disclosures
Section titled “Security disclosures”Don’t file security issues in the public tracker. Use GitHub’s Security advisory flow on the repository. See Security model → Reporting.
Acknowledgements
Section titled “Acknowledgements”dssh stands on the shoulders of great open source:
- Bubble Tea, Bubbles, Lip Gloss — Charm’s TUI stack
- Cobra — CLI framework
- modernc.org/sqlite — pure-Go SQLite
- golang.org/x/crypto — Argon2id
- UPX — binary compression