Skip to main content

Manage local SSH config from a workspace and host repo.

Project description

keywharf

keywharf is a Python 3.11+ CLI for selecting SSH hosts from a host repo into a local desired state, then materializing only manager-owned SSH artifacts.

It manages only:

  • one explicit local state file
  • one managed SSH config fragment
  • one managed key directory

It does not take over the user's whole ~/.ssh/config. Only install-include may minimally append one Include block to the main SSH config.

Recommended Workflow

Create one named workspace:

keywharf init demo --directory ~

If you already have a host repo remote URL:

# edit ~/demo/config.json and set host_repo_remote_url
keywharf --workspace ~/demo repo sync
keywharf --workspace ~/demo repo host list
keywharf --workspace ~/demo repo host show demo

High-frequency read-only convenience views are also available:

keywharf --workspace ~/demo list repo
keywharf --workspace ~/demo show repo demo
keywharf --workspace ~/demo list local
keywharf --workspace ~/demo show local demo

If you are starting from scratch:

keywharf --workspace ~/demo repo init
keywharf --workspace ~/demo repo host add demo --comment "demo host"
keywharf --workspace ~/demo repo host endpoint add demo public --hostname demo.example.com --comment "public endpoint"
keywharf --workspace ~/demo repo host auth add demo home --user fox --identity-file keys/id_demo --comment "home key"

keywharf init creates ~/demo/repo as the workspace's one host repo directory, but it starts empty. repo init writes the host repo skeleton there. repo host add creates a host shell only; endpoint and authentication options are added separately by stable name. If you want ~/demo/repo to become a real git repository, run git init, git remote add, and git push there yourself.

Then continue with normal selection and apply flow:

keywharf --workspace ~/demo select demo
# or select explicitly by stable name:
# keywharf --workspace ~/demo select demo --endpoint public --auth home
keywharf --workspace ~/demo validate
keywharf --workspace ~/demo render
keywharf --workspace ~/demo apply
keywharf --workspace ~/demo install-include

select still accepts explicit --endpoint and --auth stable names. If one side has a single candidate, it is selected automatically. If one side has multiple candidates, select prompts in an interactive terminal and fails fast in noninteractive environments until you pass the stable name explicitly. Local state keeps name-based selectors; singleton selections may leave endpoint_name or authentication_name as null.

If the manager config lives outside the default workspace root, use --config <path> instead of --workspace.

Ownership Boundary

keywharf manages:

  • state_path
  • managed_config_path
  • managed_keys_dir

keywharf does not manage:

  • unrelated Host entries in the main SSH config
  • Match blocks
  • other Include lines
  • user comments and ordering in the main SSH config

Workspace Discovery

Workspace resolution is explicit and predictable:

  1. --workspace
  2. KEYWHARF_WORKSPACE
  3. auto-search pwd, each ancestor, then ~
  4. for each base directory: scan one level of child directories first, then the base directory itself
  5. the first directory containing KEYWHARF_WORKSPACE wins
  6. fail fast with the checked candidate paths listed

keywharf init <workspace_name> creates the marker, config.json, state/state.json, an empty repo/ directory, and small workspace text files from package resources. It does not touch ~/.ssh and does not initialize a git repo for you.

Formal Config And Templates

Manager config is a formal runtime config:

  • defaults come from pkg://keywharf/config_defaults/manager.json
  • file or mapping input is override only
  • defaults and overrides are deep-merged before Pydantic v2 validation
  • runtime path resolution is separate from raw config loading

Resource roles are intentionally split:

  • config_defaults/*.json: formal defaults for manager config
  • templates/*.json: structured starter data such as the empty state file
  • templates/*.j2: human-facing text templates such as workspace README.md, workspace .gitignore, and the include block text

Host Repo CRUD

repo init bootstraps a local-first host repo skeleton:

  • empty config.json
  • keys/
  • .gitignore

It writes those files into the workspace's one host repo directory, %{WORKSPACE}/repo. It does not run git init or create .git.

repo host edits only the host repo config.json:

  • repo host list
  • repo host show
  • repo host add
  • repo host update
  • repo host remove
  • repo host endpoint list
  • repo host endpoint show
  • repo host endpoint add
  • repo host endpoint update
  • repo host endpoint remove
  • repo host auth list
  • repo host auth show
  • repo host auth add
  • repo host auth update
  • repo host auth remove

These commands do not commit, push, run git init, or mutate git metadata. They perform structured JSON reads/writes, preserve array order, and revalidate the resulting host set before writing.

Design rules:

  • repo host add creates a host shell and may set only the host comment
  • repo host endpoint ... manages named endpoint options with HostName, optional Port, and optional comment
  • repo host auth ... manages named authentication options with optional User, optional IdentityFile, and optional comment
  • select writes name-based endpoint/authentication selectors into local state; singleton selections may leave those fields null
  • validate scans the whole host repo and reports every host shell that is missing endpoint options, authentication options, or both
  • render and apply only require the hosts selected in local state to be complete

ExtraConfig is preserved and rendered, but it is not exposed as a CLI editor yet.

Read-only convenience facade (canonical paths stay primary):

  • list repo -> repo host list
  • show repo <server> -> repo host show <server>
  • list local -> local list
  • show local <server> -> local show <server>

Scope boundary:

  • convenience targets are only repo (host definitions) and local
  • convenience commands are read-only only
  • there is no convenience facade for repo host endpoint ..., repo host auth ..., or any write operations

--sudo

Mutating commands support --sudo:

  • init
  • repo init
  • repo sync
  • select
  • deselect
  • apply
  • install-include
  • repo host add
  • repo host update
  • repo host remove
  • repo host endpoint add
  • repo host endpoint update
  • repo host endpoint remove
  • repo host auth add
  • repo host auth update
  • repo host auth remove

Privilege handling is centralized:

  • normal writable paths run without sudo
  • unwritable paths fail fast with concrete path-based reasons
  • --sudo re-execs the full command through sudo

Installation

python3.11 -m venv .venv
. .venv/bin/activate
python -m pip install -e '.[dev]'
pytest

Runtime requirements:

  • Python 3.11+
  • system git

Documentation

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

keywharf-1.0.4.tar.gz (60.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

keywharf-1.0.4-py3-none-any.whl (74.5 kB view details)

Uploaded Python 3

File details

Details for the file keywharf-1.0.4.tar.gz.

File metadata

  • Download URL: keywharf-1.0.4.tar.gz
  • Upload date:
  • Size: 60.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for keywharf-1.0.4.tar.gz
Algorithm Hash digest
SHA256 2256793202ef3b58e6133f9dbd24ed60c9083d1d62f4f45e30e6882f7982438a
MD5 fafe7f3e6340100ecb1242ed5169ebcf
BLAKE2b-256 4b58fca8b651be05da8cf0e2e7f218e483221a8405a538a9309e4c2a1f480b14

See more details on using hashes here.

Provenance

The following attestation bundles were made for keywharf-1.0.4.tar.gz:

Publisher: publish.yml on eserie-fox/keywharf

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file keywharf-1.0.4-py3-none-any.whl.

File metadata

  • Download URL: keywharf-1.0.4-py3-none-any.whl
  • Upload date:
  • Size: 74.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for keywharf-1.0.4-py3-none-any.whl
Algorithm Hash digest
SHA256 dcd0d1f6f305e969fec4415d973cfbf5243e592fc27d75d3421d2d59b86609ff
MD5 37fd653581472d44fc7e9d2c9db3067d
BLAKE2b-256 604085decd41ae62d804c6afda0f4f0ac662f563e9f6f415c6203a2a7603ee27

See more details on using hashes here.

Provenance

The following attestation bundles were made for keywharf-1.0.4-py3-none-any.whl:

Publisher: publish.yml on eserie-fox/keywharf

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page