Metadata-Version: 2.4
Name: tlnt-cli
Version: 1.5.2
Summary: CLI wrapper for HRIS attendance and employment workflows.
Author: Fathiraz Arthuro
License-Expression: MIT
License-File: LICENSE
Requires-Dist: httpx>=0.28,<0.29
Requires-Dist: loguru>=0.7,<1
Requires-Dist: mcp>=2.0,<3
Requires-Dist: platformdirs>=4.3,<5
Requires-Dist: playwright>=1.50,<2
Requires-Dist: rich>=14,<16
Requires-Dist: rich-pixels>=3,<4
Requires-Dist: typer>=0.20,<1
Requires-Python: >=3.11, <3.15
Description-Content-Type: text/markdown

![tlnt CLI logo](assets/logo.png)

# tlnt

![CI](https://github.com/fathirazarthuro/tlnt/actions/workflows/ci.yml/badge.svg)
![License](https://img.shields.io/github/license/fathirazarthuro/tlnt)

`tlnt` is a macOS Apple Silicon CLI for Mekari Talenta employment data,
notifications, attendance summaries and previews, and human-confirmed attendance actions.

> [!WARNING]
> `tlnt` is an unofficial, independent research and educational project. It
> is not affiliated with Mekari or Talenta. Use it only when your account and
> the actions you perform are authorized. Read the [full bilingual
> disclaimer](docs/index.md#disclaimer) before using it.

## Why tlnt?

- Inspect employment and notification data from the terminal.
- Read attendance summaries and metrics.
- Read time-off data and submit or cancel requests with confirmation.
- Preview attendance requests before submitting them.
- Keep login visible and live actions human-confirmed.
- Warn when a newer tlnt is on PyPI, or when your configured Talenta app
  version differs from Google Play.
- Update itself with `tlnt update`.
- Provide stable JSON output and a read-only MCP server for agents.

## Install

Install from PyPI with [uv](https://docs.astral.sh/uv/):

```bash
uv tool install tlnt-cli
```

Or use `pipx install tlnt-cli` or `pip install tlnt-cli`. PyPI refuses the name
`tlnt` as too similar to an existing project, so the package is `tlnt-cli`; the
command is still `tlnt`.

For other install methods (`uvx`, from source) and the agent-specific path,
choose the instructions for your audience:

- [For humans](docs/integrations.md#for-humans)
- [For LLM agents](docs/integrations.md#for-llm-agents)

Login uses Playwright to open your installed Google Chrome or Microsoft Edge;
nothing is downloaded. To use a browser you already run instead, see
[Sign in with your own browser](#sign-in-with-your-own-browser). To have tlnt
type your email and password for you, see
[Sign in from the terminal](#sign-in-from-the-terminal).

### Configure

Before first use, create the config file:

```bash
tlnt setup
```

It creates `config.json` in the default OS config folder (or the file given
with `--config PATH`) with every supported key. Ask the project maintainers for
`client_id` and set it there. Run `tlnt setup` again after `tlnt update`: it
adds new keys, removes keys tlnt no longer reads, and keeps your values.

See [Setup](docs/setup.md) for configuration and login prerequisites.
`tlnt` never opens login automatically from another command.

### Sign in with your own browser

`tlnt login --cdp` attaches to a browser that is already running instead of
launching one. tlnt opens one tab in it, you sign in on Mekari's page, and only
that tab is closed. With Chrome, use a dedicated profile folder (Chrome 136 and
later ignore the DevTools port on the default profile):

```bash
# terminal 1: leave running
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" \
  --remote-debugging-port=9222 --user-data-dir="$HOME/.tlnt-chrome"
# terminal 2
tlnt login --cdp 9222
```

With agent-browser:

```bash
agent-browser --session tlnt-login --headed open about:blank
tlnt login --cdp "$(agent-browser --session tlnt-login get cdp-url)"
agent-browser --session tlnt-login close
```

See [Setup](docs/setup.md#sign-in-with-a-browser-you-already-run) for details.

### Sign in from the terminal

`tlnt login --email you@example.com` asks for your Mekari password with a hidden
prompt and types both into Mekari's own sign-in page. There is no `--password`
flag. See [Setup](docs/setup.md#sign-in-from-the-terminal) for hosts with no
terminal.

## Update tlnt

```bash
tlnt update
```

`tlnt update` installs the latest PyPI release with
`uv tool install tlnt-cli==<version> --force` when it is newer than the installed
version, and never downgrades. It needs `uv` on `PATH`, prints uv's output, and
exits with uv's exit code.

Installed tlnt 1.5.0 or earlier, when the package was still named `tlnt`?
Switch once:

```bash
uv tool install tlnt-cli --force && uv tool uninstall tlnt && uv tool install tlnt-cli --force
```

If the first install fails, nothing changes. Uninstalling the old package also
removes the `tlnt` command, so the last install puts it back. After that,
`tlnt update` works.

## tlnt version check

Every command except `mcp` and `update` also checks PyPI for a newer tlnt. If
one exists, a notice appears on stderr:

```text
⚠️ tlnt v1.4.0 is installed, but v1.5.0 is available. Run `tlnt update` to update.
```

The lookup times out after 3 seconds and its result is cached for 24 hours, a
failed lookup included, and the check stays silent when PyPI is unreachable. Stdout, `--json` results, and exit codes
are unchanged. The notice never updates anything by itself.

## Talenta app version check

Talenta requests carry the mobile app version from `app_version` in your
config. Every command except `mcp` and `update` compares it with the latest
version in the [Talenta Google Play
listing](https://play.google.com/store/apps/details?id=co.talenta&hl=id). If
they differ, a notice appears on stderr:

```text
⚠️ Talenta app v2.123.0 is configured, but v2.125.0 is on Google Play. Set "app_version" to "2.125.0" in /path/to/config.json (or TALENTA_APP_VERSION), then run `tlnt logout` and `tlnt login`.
```

Update `app_version` (and optionally `user_agent_mobile`; see
[Setup](docs/setup.md)), then log out and log in again. The lookup times out
after 3 seconds and its result is cached for 24 hours, a failed lookup
included, and the check stays silent when Google Play is unreachable. Stdout, `--json` results, and exit codes are
unchanged. The notice never logs out, logs in, or updates anything by itself.

## Modes at a glance

| Mode | Flag | Behavior |
| --- | --- | --- |
| Machine output | `--json` | Writes one result object to stdout. |
| Diagnostics | `--verbose` | Adds DEBUG diagnostics without changing stdout. |
| Safe preview | `--dry-run` | Builds an attendance preview without submitting it. |
| Configuration | `--config PATH` | Selects a config file for this invocation; pass it when a command needs values from a non-default file. Environment variables and the default OS config path need no flag. |
| Interactive input | `--interactive` | Prompts for missing values on supported commands; refuses to run without a TTY or with `--json`. |

Use `--json` when output will be consumed by an agent. Clock-in and
clock-out confirmation prompts use stdout in human mode and stderr with
`--json`; diagnostics use stderr.

## Common workflows

These examples assume settings come from the default OS config path or
environment variables. If you use a non-default config file, pass
`--config PATH` before each command that needs its values.

Read employment information:

```bash
tlnt profile --json
```

Read notifications and attendance summaries. Summary commands default to the
local date; use `--date YYYY-MM-DD` to select another day:

```bash
tlnt notification count --json
tlnt notification list --page 1 --query "" --status 3 --json
tlnt notification detail INBOX_ID --json
tlnt attendance summary-list --json
tlnt attendance summary-metrics --json
```

Preview, then explicitly confirm a live attendance action:

```bash
tlnt attendance clock-in \
  --dry-run --latitude LATITUDE --longitude LONGITUDE --notes "Preview" --json
tlnt attendance clock-in \
  --latitude LATITUDE --longitude LONGITUDE --notes "On time" --json
```

Review an attendance request before approval:

```bash
tlnt notification detail INBOX_ID --json
tlnt attendance approve INBOX_ID --reason "Reviewed" --json
```

See [Workflows](docs/workflows.md) for the complete safe procedures.

## Calendar commands

These calendar lookups are read-only and use the current Talenta mobile token.
Filtered commands default to `--limit 10` and `--page 1`; other filters are
sent only when supplied. `birthday` lists employee birthdays and can be
filtered to one employee with `--user-id`. `my-birthday` returns your
own birth date.

```bash
tlnt calendar holiday --start-date 2026-01-01 --end-date 2026-12-31 --json
tlnt calendar timeoff --start-date 2026-09-27 --end-date 2026-09-27 --json
tlnt calendar index --month 2 --year 2026 --json
tlnt calendar my-birthday --json
tlnt calendar birthday --start-date 2026-09-27 --end-date 2026-09-27 --json
tlnt calendar activity --start-date 2026-01-01 --end-date 2026-12-31 --json
```

Holiday, time-off, index, birthday, and activity commands also accept
`--start-date`, `--end-date`, `--limit`, `--month`, `--year`,
`--page`, `--id`, `--type`, `--search`, `--date`, and `--user-id`.
The personal `my-birthday` command has no filters.

## Time-off commands

Lookup commands are read-only. Time-off requests, approvals, and cancellations
require terminal confirmation; declining sends nothing. Balance requests use the signed-in
profile's company and user IDs.

```bash
tlnt timeoff types-list --json
tlnt timeoff balance --json
tlnt timeoff balance --show-unlimited-balance --json
tlnt timeoff delegation-list --search "NAME" --json
tlnt timeoff list --json
tlnt timeoff detail REQUEST_ID --json
tlnt timeoff request --date 2026-10-12 --policy-id 4448 --reason "reason"
tlnt timeoff request --date 2026-10-12 --policy-id 4448 --reason "reason" --half-day after --schedule-in 13:00 --schedule-out 18:00
tlnt timeoff request --date 2026-10-12 --policy-id 4448 --reason "reason" --half-day before --schedule-in 09:00 --schedule-out 12:00 --delegate-to 2378974 --file support.jpeg
tlnt timeoff cancel REQUEST_ID
tlnt timeoff approve INBOX_ID --reason "Reviewed"
```

See [Commands](docs/commands.md#time-off-data) for filters, defaults, and half-day details.

## Safety contract

- Do not open the login flow automatically.
- Never ask the user for their Mekari password. Only they start
  `tlnt login --email`, and the password comes from a hidden prompt or from
  `TALENTA_PASSWORD` in the host's own environment.
- Live clock-in, clock-out, approval, time-off requests, and cancellations always require terminal confirmation.
- `--dry-run` never submits attendance.
- MCP cannot log in, log out, approve attendance, or submit attendance.
- The version checks only read public listings (PyPI and Google Play), never
  send your session or config, and never log out, log in, or update for you.
- Never print passwords, bearer tokens, cookies, authorization codes, request
  bodies, selfie contents, or real employee data.
- If `status` returns `session_missing`, `session_invalid`,
  `mobile_token_missing`, or `mobile_token_expired`, ask
  the user to run login explicitly.

## Documentation

- [Docs site](https://tlnt-docs.vercel.app)
- [Cookbook](docs/cookbook.md)
- [Setup](docs/setup.md)
- [Commands and JSON contract](docs/commands.md)
- [Workflows](docs/workflows.md)
- [AI agent integrations](docs/integrations.md)
- [Security](docs/security.md)
- [Contributing](docs/contributing.md)
- [Agent skill](skills/tlnt-cli/SKILL.md)

## Troubleshooting

Login drives your installed Google Chrome or Microsoft Edge through
Playwright, so one of them must be installed, unless you attach to a browser you
already run with `tlnt login --cdp` (see [Setup](docs/setup.md#login)). Use `tlnt status --json` to inspect the local session without
contacting Talenta. Read [Security](docs/security.md) before removing a
session with `logout`. If the saved token already expired, `logout` still
removes the local session. If a command returns `mobile_token_expired` while
`tlnt login` says `Already logged in`, run `tlnt logout` and then
`tlnt login`. If a command prints the Google Play version notice,
see [App version check](#talenta-app-version-check).

## License

`tlnt` is licensed under the [MIT License](LICENSE).
