Metadata-Version: 2.4
Name: ign8ssh
Version: 0.3.0
Summary: Manage and connect to SSH hosts configured in ~/.ign8/ign8ssh.json.
Author-email: Jakob Holst <lyngknuden@gmail.com>
License: MIT
Project-URL: Homepage, https://gitlab.com/ign8-it-group/team-nine/ign8ssh
Project-URL: Repository, https://gitlab.com/ign8-it-group/team-nine/ign8ssh
Keywords: ssh,ign8,cli
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: System Administrators
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: System :: Networking
Classifier: Topic :: Utilities
Requires-Python: >=3.9
Description-Content-Type: text/markdown
Requires-Dist: typer>=0.12
Requires-Dist: rich>=13
Requires-Dist: questionary>=2.0
Provides-Extra: dev
Requires-Dist: pytest>=8; extra == "dev"
Requires-Dist: ruff>=0.4; extra == "dev"
Requires-Dist: mypy>=1.10; extra == "dev"

# ign8ssh

Manage and connect to SSH hosts declared in `~/.ign8/ign8ssh.json`.

## Install

```bash
pip install ign8ssh
```

## Configure

Create `~/.ign8/ign8ssh.json`:

```json
[
  {
    "name": "prod-web",
    "host": "web.example.com",
    "user": "deploy",
    "port": 22,
    "identity_file": "~/.ssh/id_ed25519"
  },
  {
    "name": "bastion",
    "host": "bastion.example.com",
    "user": "jaho"
  }
]
```

The file may also be an object with a `hosts` key wrapping the list. `port`
defaults to `22` and `identity_file` is optional.

## Commands

Two data stores are used side by side:

- `~/.ign8/ign8ssh.json` — curated fleet used by `list` / `check` / `connect`.
- `~/.ssh/config` — where `map` writes discovered hosts and what `ign8ssh-tui` reads.

### `ign8ssh` (JSON-backed fleet)

| Command | Description |
|---------|-------------|
| `ign8ssh list`             | List configured hosts (from `~/.ign8/ign8ssh.json`) |
| `ign8ssh check`            | Probe every host with a non-interactive SSH ping (BatchMode) |
| `ign8ssh connect <name>`   | Open an interactive SSH session |

The default (no subcommand) prints a short status summary.

### `ign8ssh map` (LAN discovery → `~/.ssh/config`)

Scan the local network for SSH servers and register them as `Host` entries
in `~/.ssh/config`. The entries live inside a sentinel block that gets
replaced on every run, so re-scanning is idempotent — vanished hosts drop
off automatically and you can hand-edit stanzas outside the block without
losing them.

```bash
# Scan the /24 attached to the primary interface
ign8ssh map --local

# Scan an explicit range, tag every entry with a specific key and user
ign8ssh map --network 10.0.0.0/24 --user root --identity-file ~/.ssh/id_lab

# See what would be written without touching ~/.ssh/config
ign8ssh map --local --dry-run
```

### `ign8ssh-tui`

Standalone entry point: arrow-key menu over every `Host` block in
`~/.ssh/config` (skipping wildcards and `Match` blocks). Select a host, then
choose an action:

- **Connect** — execs `ssh <name>` in the current terminal.
- **Rename** — prompt for a new alias and edit `~/.ssh/config` in place. If
  the host was inside the ign8ssh-managed block, its stanza is moved out
  automatically so a future `ign8ssh map` run can't clobber the new name.
  `ign8ssh map` also skips any IP already declared as a `HostName` outside
  the managed block, so renamed hosts never come back as `lan-<ip>`
  duplicates on rescan.

```bash
ign8ssh-tui
```

## Release

Publishing to PyPI is handled by the GitLab CI `publish` job, which runs on any
tag matching `v*` and mints a token via PyPI's Trusted Publisher OIDC flow.

```bash
# bump version in pyproject.toml, commit, then:
git tag v0.1.0
git push origin v0.1.0
```

Before the first release, register the GitLab project as a Trusted Publisher
for `ign8ssh` on <https://pypi.org/manage/account/publishing/>:

- PyPI project name: `ign8ssh`
- Namespace: `ign8-it-group/team-nine`
- Repository name: `ign8ssh`
- Workflow file / job: `publish`
- Environment: *(leave blank)*
