tlnt-cli 1.5.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. tlnt_cli-1.5.1/LICENSE +21 -0
  2. tlnt_cli-1.5.1/PKG-INFO +315 -0
  3. tlnt_cli-1.5.1/README.md +296 -0
  4. tlnt_cli-1.5.1/pyproject.toml +43 -0
  5. tlnt_cli-1.5.1/pyproject.toml.orig +39 -0
  6. tlnt_cli-1.5.1/src/tlnt/__init__.py +3 -0
  7. tlnt_cli-1.5.1/src/tlnt/__main__.py +4 -0
  8. tlnt_cli-1.5.1/src/tlnt/browser/__init__.py +0 -0
  9. tlnt_cli-1.5.1/src/tlnt/browser/login.py +414 -0
  10. tlnt_cli-1.5.1/src/tlnt/browser/oauth.py +50 -0
  11. tlnt_cli-1.5.1/src/tlnt/browser/scripted.py +183 -0
  12. tlnt_cli-1.5.1/src/tlnt/cli/__init__.py +0 -0
  13. tlnt_cli-1.5.1/src/tlnt/cli/avatars.py +51 -0
  14. tlnt_cli-1.5.1/src/tlnt/cli/commands/__init__.py +0 -0
  15. tlnt_cli-1.5.1/src/tlnt/cli/commands/approvals.py +98 -0
  16. tlnt_cli-1.5.1/src/tlnt/cli/commands/attendance.py +283 -0
  17. tlnt_cli-1.5.1/src/tlnt/cli/commands/calendar.py +108 -0
  18. tlnt_cli-1.5.1/src/tlnt/cli/commands/login.py +225 -0
  19. tlnt_cli-1.5.1/src/tlnt/cli/commands/logout.py +12 -0
  20. tlnt_cli-1.5.1/src/tlnt/cli/commands/mcp.py +8 -0
  21. tlnt_cli-1.5.1/src/tlnt/cli/commands/notifications.py +102 -0
  22. tlnt_cli-1.5.1/src/tlnt/cli/commands/profile.py +13 -0
  23. tlnt_cli-1.5.1/src/tlnt/cli/commands/setup.py +12 -0
  24. tlnt_cli-1.5.1/src/tlnt/cli/commands/status.py +12 -0
  25. tlnt_cli-1.5.1/src/tlnt/cli/commands/timeoff.py +491 -0
  26. tlnt_cli-1.5.1/src/tlnt/cli/commands/update.py +86 -0
  27. tlnt_cli-1.5.1/src/tlnt/cli/commands/version.py +15 -0
  28. tlnt_cli-1.5.1/src/tlnt/cli/main.py +163 -0
  29. tlnt_cli-1.5.1/src/tlnt/cli/options.py +56 -0
  30. tlnt_cli-1.5.1/src/tlnt/cli/output.py +321 -0
  31. tlnt_cli-1.5.1/src/tlnt/cli/prompts.py +76 -0
  32. tlnt_cli-1.5.1/src/tlnt/core/__init__.py +0 -0
  33. tlnt_cli-1.5.1/src/tlnt/core/clients/__init__.py +0 -0
  34. tlnt_cli-1.5.1/src/tlnt/core/clients/mekari/__init__.py +0 -0
  35. tlnt_cli-1.5.1/src/tlnt/core/clients/mekari/client.py +826 -0
  36. tlnt_cli-1.5.1/src/tlnt/core/clients/mekari/constants.py +174 -0
  37. tlnt_cli-1.5.1/src/tlnt/core/config.py +53 -0
  38. tlnt_cli-1.5.1/src/tlnt/core/http_client.py +110 -0
  39. tlnt_cli-1.5.1/src/tlnt/core/logs.py +34 -0
  40. tlnt_cli-1.5.1/src/tlnt/core/models.py +84 -0
  41. tlnt_cli-1.5.1/src/tlnt/core/play_store.py +85 -0
  42. tlnt_cli-1.5.1/src/tlnt/core/services/__init__.py +46 -0
  43. tlnt_cli-1.5.1/src/tlnt/core/services/attendance.py +213 -0
  44. tlnt_cli-1.5.1/src/tlnt/core/services/calendar.py +54 -0
  45. tlnt_cli-1.5.1/src/tlnt/core/services/login.py +100 -0
  46. tlnt_cli-1.5.1/src/tlnt/core/services/logout.py +38 -0
  47. tlnt_cli-1.5.1/src/tlnt/core/services/notifications.py +97 -0
  48. tlnt_cli-1.5.1/src/tlnt/core/services/profile.py +11 -0
  49. tlnt_cli-1.5.1/src/tlnt/core/services/setup.py +85 -0
  50. tlnt_cli-1.5.1/src/tlnt/core/services/status.py +35 -0
  51. tlnt_cli-1.5.1/src/tlnt/core/services/timeoff.py +146 -0
  52. tlnt_cli-1.5.1/src/tlnt/core/session.py +189 -0
  53. tlnt_cli-1.5.1/src/tlnt/core/user_agent.py +71 -0
  54. tlnt_cli-1.5.1/src/tlnt/mcp/__init__.py +0 -0
  55. tlnt_cli-1.5.1/src/tlnt/mcp/main.py +176 -0
tlnt_cli-1.5.1/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 fathiraz arthuro
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,315 @@
1
+ Metadata-Version: 2.4
2
+ Name: tlnt-cli
3
+ Version: 1.5.1
4
+ Summary: CLI wrapper for HRIS attendance and employment workflows.
5
+ Author: Fathiraz Arthuro
6
+ License-Expression: MIT
7
+ License-File: LICENSE
8
+ Requires-Dist: httpx>=0.28,<0.29
9
+ Requires-Dist: keyring>=25,<26
10
+ Requires-Dist: loguru>=0.7,<1
11
+ Requires-Dist: mcp>=2.0,<3
12
+ Requires-Dist: platformdirs>=4.3,<5
13
+ Requires-Dist: playwright>=1.50,<2
14
+ Requires-Dist: rich>=14,<16
15
+ Requires-Dist: rich-pixels>=3,<4
16
+ Requires-Dist: typer>=0.20,<1
17
+ Requires-Python: >=3.11, <3.15
18
+ Description-Content-Type: text/markdown
19
+
20
+ ![tlnt CLI logo](assets/logo.png)
21
+
22
+ # tlnt
23
+
24
+ ![CI](https://github.com/fathirazarthuro/tlnt/actions/workflows/ci.yml/badge.svg)
25
+ ![License](https://img.shields.io/github/license/fathirazarthuro/tlnt)
26
+
27
+ `tlnt` is a macOS Apple Silicon CLI for Mekari Talenta employment data,
28
+ notifications, attendance summaries and previews, and human-confirmed attendance actions.
29
+
30
+ > [!WARNING]
31
+ > `tlnt` is an unofficial, independent research and educational project. It
32
+ > is not affiliated with Mekari or Talenta. Use it only when your account and
33
+ > the actions you perform are authorized. Read the [full bilingual
34
+ > disclaimer](docs/index.md#disclaimer) before using it.
35
+
36
+ ## Why tlnt?
37
+
38
+ - Inspect employment and notification data from the terminal.
39
+ - Read attendance summaries and metrics.
40
+ - Read time-off data and submit or cancel requests with confirmation.
41
+ - Preview attendance requests before submitting them.
42
+ - Keep login visible and live actions human-confirmed.
43
+ - Warn when a newer tlnt is on PyPI, or when your configured Talenta app
44
+ version differs from Google Play.
45
+ - Update itself with `tlnt update`.
46
+ - Provide stable JSON output and a read-only MCP server for agents.
47
+
48
+ ## Install
49
+
50
+ Install from PyPI with [uv](https://docs.astral.sh/uv/):
51
+
52
+ ```bash
53
+ uv tool install tlnt-cli
54
+ ```
55
+
56
+ Or use `pipx install tlnt-cli` or `pip install tlnt-cli`. PyPI refuses the name
57
+ `tlnt` as too similar to an existing project, so the package is `tlnt-cli`; the
58
+ command is still `tlnt`.
59
+
60
+ For other install methods (`uvx`, from source) and the agent-specific path,
61
+ choose the instructions for your audience:
62
+
63
+ - [For humans](docs/integrations.md#for-humans)
64
+ - [For LLM agents](docs/integrations.md#for-llm-agents)
65
+
66
+ Login uses Playwright to open your installed Google Chrome or Microsoft Edge;
67
+ nothing is downloaded. To use a browser you already run instead, see
68
+ [Sign in with your own browser](#sign-in-with-your-own-browser). To have tlnt
69
+ type your email and password for you, see
70
+ [Sign in from the terminal](#sign-in-from-the-terminal).
71
+
72
+ ### Configure
73
+
74
+ Before first use, create the config file:
75
+
76
+ ```bash
77
+ tlnt setup
78
+ ```
79
+
80
+ It creates `config.json` in the default OS config folder (or the file given
81
+ with `--config PATH`) with every supported key. Ask the project maintainers for
82
+ `client_id` and set it there. Run `tlnt setup` again after `tlnt update`: it
83
+ adds new keys, removes keys tlnt no longer reads, and keeps your values.
84
+
85
+ See [Setup](docs/setup.md) for configuration and login prerequisites.
86
+ `tlnt` never opens login automatically from another command.
87
+
88
+ ### Sign in with your own browser
89
+
90
+ `tlnt login --cdp` attaches to a browser that is already running instead of
91
+ launching one. tlnt opens one tab in it, you sign in on Mekari's page, and only
92
+ that tab is closed. With Chrome, use a dedicated profile folder (Chrome 136 and
93
+ later ignore the DevTools port on the default profile):
94
+
95
+ ```bash
96
+ # terminal 1: leave running
97
+ "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" \
98
+ --remote-debugging-port=9222 --user-data-dir="$HOME/.tlnt-chrome"
99
+ # terminal 2
100
+ tlnt login --cdp 9222
101
+ ```
102
+
103
+ With agent-browser:
104
+
105
+ ```bash
106
+ agent-browser --session tlnt-login --headed open about:blank
107
+ tlnt login --cdp "$(agent-browser --session tlnt-login get cdp-url)"
108
+ agent-browser --session tlnt-login close
109
+ ```
110
+
111
+ See [Setup](docs/setup.md#sign-in-with-a-browser-you-already-run) for details.
112
+
113
+ ### Sign in from the terminal
114
+
115
+ `tlnt login --email you@example.com` asks for your Mekari password with a hidden
116
+ prompt and types both into Mekari's own sign-in page. There is no `--password`
117
+ flag. See [Setup](docs/setup.md#sign-in-from-the-terminal) for hosts with no
118
+ terminal.
119
+
120
+ ## Update tlnt
121
+
122
+ ```bash
123
+ tlnt update
124
+ ```
125
+
126
+ `tlnt update` installs the latest PyPI release with
127
+ `uv tool install tlnt-cli==<version> --force` when it is newer than the installed
128
+ version, and never downgrades. It needs `uv` on `PATH`, prints uv's output, and
129
+ exits with uv's exit code.
130
+
131
+ Installed tlnt 1.5.0 or earlier, when the package was still named `tlnt`?
132
+ Switch once:
133
+
134
+ ```bash
135
+ uv tool install tlnt-cli --force && uv tool uninstall tlnt && uv tool install tlnt-cli --force
136
+ ```
137
+
138
+ If the first install fails, nothing changes. Uninstalling the old package also
139
+ removes the `tlnt` command, so the last install puts it back. After that,
140
+ `tlnt update` works.
141
+
142
+ ## tlnt version check
143
+
144
+ Every command except `mcp` and `update` also checks PyPI for a newer tlnt. If
145
+ one exists, a notice appears on stderr:
146
+
147
+ ```text
148
+ ⚠️ tlnt v1.4.0 is installed, but v1.5.0 is available. Run `tlnt update` to update.
149
+ ```
150
+
151
+ The lookup times out after 3 seconds and its result is cached for 24 hours, a
152
+ failed lookup included, and the check stays silent when PyPI is unreachable. Stdout, `--json` results, and exit codes
153
+ are unchanged. The notice never updates anything by itself.
154
+
155
+ ## Talenta app version check
156
+
157
+ Talenta requests carry the mobile app version from `app_version` in your
158
+ config. Every command except `mcp` and `update` compares it with the latest
159
+ version in the [Talenta Google Play
160
+ listing](https://play.google.com/store/apps/details?id=co.talenta&hl=id). If
161
+ they differ, a notice appears on stderr:
162
+
163
+ ```text
164
+ ⚠️ 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`.
165
+ ```
166
+
167
+ Update `app_version` (and optionally `user_agent_mobile`; see
168
+ [Setup](docs/setup.md)), then log out and log in again. The lookup times out
169
+ after 3 seconds and its result is cached for 24 hours, a failed lookup
170
+ included, and the check stays silent when Google Play is unreachable. Stdout, `--json` results, and exit codes are
171
+ unchanged. The notice never logs out, logs in, or updates anything by itself.
172
+
173
+ ## Modes at a glance
174
+
175
+ | Mode | Flag | Behavior |
176
+ | --- | --- | --- |
177
+ | Machine output | `--json` | Writes one result object to stdout. |
178
+ | Diagnostics | `--verbose` | Adds DEBUG diagnostics without changing stdout. |
179
+ | Safe preview | `--dry-run` | Builds an attendance preview without submitting it. |
180
+ | 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. |
181
+ | Interactive input | `--interactive` | Prompts for missing values on supported commands; refuses to run without a TTY or with `--json`. |
182
+
183
+ Use `--json` when output will be consumed by an agent. Clock-in and
184
+ clock-out confirmation prompts use stdout in human mode and stderr with
185
+ `--json`; diagnostics use stderr.
186
+
187
+ ## Common workflows
188
+
189
+ These examples assume settings come from the default OS config path or
190
+ environment variables. If you use a non-default config file, pass
191
+ `--config PATH` before each command that needs its values.
192
+
193
+ Read employment information:
194
+
195
+ ```bash
196
+ tlnt profile --json
197
+ ```
198
+
199
+ Read notifications and attendance summaries. Summary commands default to the
200
+ local date; use `--date YYYY-MM-DD` to select another day:
201
+
202
+ ```bash
203
+ tlnt notification count --json
204
+ tlnt notification list --page 1 --query "" --status 3 --json
205
+ tlnt notification detail INBOX_ID --json
206
+ tlnt attendance summary-list --json
207
+ tlnt attendance summary-metrics --json
208
+ ```
209
+
210
+ Preview, then explicitly confirm a live attendance action:
211
+
212
+ ```bash
213
+ tlnt attendance clock-in \
214
+ --dry-run --latitude LATITUDE --longitude LONGITUDE --notes "Preview" --json
215
+ tlnt attendance clock-in \
216
+ --latitude LATITUDE --longitude LONGITUDE --notes "On time" --json
217
+ ```
218
+
219
+ Review an attendance request before approval:
220
+
221
+ ```bash
222
+ tlnt notification detail INBOX_ID --json
223
+ tlnt attendance approve INBOX_ID --reason "Reviewed" --json
224
+ ```
225
+
226
+ See [Workflows](docs/workflows.md) for the complete safe procedures.
227
+
228
+ ## Calendar commands
229
+
230
+ These calendar lookups are read-only and use the current Talenta mobile token.
231
+ Filtered commands default to `--limit 10` and `--page 1`; other filters are
232
+ sent only when supplied. `birthday` lists employee birthdays and can be
233
+ filtered to one employee with `--user-id`. `my-birthday` returns your
234
+ own birth date.
235
+
236
+ ```bash
237
+ tlnt calendar holiday --start-date 2026-01-01 --end-date 2026-12-31 --json
238
+ tlnt calendar timeoff --start-date 2026-09-27 --end-date 2026-09-27 --json
239
+ tlnt calendar index --month 2 --year 2026 --json
240
+ tlnt calendar my-birthday --json
241
+ tlnt calendar birthday --start-date 2026-09-27 --end-date 2026-09-27 --json
242
+ tlnt calendar activity --start-date 2026-01-01 --end-date 2026-12-31 --json
243
+ ```
244
+
245
+ Holiday, time-off, index, birthday, and activity commands also accept
246
+ `--start-date`, `--end-date`, `--limit`, `--month`, `--year`,
247
+ `--page`, `--id`, `--type`, `--search`, `--date`, and `--user-id`.
248
+ The personal `my-birthday` command has no filters.
249
+
250
+ ## Time-off commands
251
+
252
+ Lookup commands are read-only. Time-off requests, approvals, and cancellations
253
+ require terminal confirmation; declining sends nothing. Balance requests use the signed-in
254
+ profile's company and user IDs.
255
+
256
+ ```bash
257
+ tlnt timeoff types-list --json
258
+ tlnt timeoff balance --json
259
+ tlnt timeoff balance --show-unlimited-balance --json
260
+ tlnt timeoff delegation-list --search "NAME" --json
261
+ tlnt timeoff list --json
262
+ tlnt timeoff detail REQUEST_ID --json
263
+ tlnt timeoff request --date 2026-10-12 --policy-id 4448 --reason "reason"
264
+ tlnt timeoff request --date 2026-10-12 --policy-id 4448 --reason "reason" --half-day after --schedule-in 13:00 --schedule-out 18:00
265
+ 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
266
+ tlnt timeoff cancel REQUEST_ID
267
+ tlnt timeoff approve INBOX_ID --reason "Reviewed"
268
+ ```
269
+
270
+ See [Commands](docs/commands.md#time-off-data) for filters, defaults, and half-day details.
271
+
272
+ ## Safety contract
273
+
274
+ - Do not open the login flow automatically.
275
+ - Never ask the user for their Mekari password. Only they start
276
+ `tlnt login --email`, and the password comes from a hidden prompt or from
277
+ `TALENTA_PASSWORD` in the host's own environment.
278
+ - Live clock-in, clock-out, approval, time-off requests, and cancellations always require terminal confirmation.
279
+ - `--dry-run` never submits attendance.
280
+ - MCP cannot log in, log out, approve attendance, or submit attendance.
281
+ - The version checks only read public listings (PyPI and Google Play), never
282
+ send your session or config, and never log out, log in, or update for you.
283
+ - Never print passwords, bearer tokens, cookies, authorization codes, request
284
+ bodies, selfie contents, or real employee data.
285
+ - If `status` returns `session_missing`, `session_invalid`,
286
+ `mobile_token_missing`, or `mobile_token_expired`, ask
287
+ the user to run login explicitly.
288
+
289
+ ## Documentation
290
+
291
+ - [Docs site](https://tlnt-docs.vercel.app)
292
+ - [Cookbook](docs/cookbook.md)
293
+ - [Setup](docs/setup.md)
294
+ - [Commands and JSON contract](docs/commands.md)
295
+ - [Workflows](docs/workflows.md)
296
+ - [AI agent integrations](docs/integrations.md)
297
+ - [Security](docs/security.md)
298
+ - [Contributing](docs/contributing.md)
299
+ - [Agent skill](skills/tlnt-cli/SKILL.md)
300
+
301
+ ## Troubleshooting
302
+
303
+ Login drives your installed Google Chrome or Microsoft Edge through
304
+ Playwright, so one of them must be installed, unless you attach to a browser you
305
+ already run with `tlnt login --cdp` (see [Setup](docs/setup.md#login)). Use `tlnt status --json` to inspect the local session without
306
+ contacting Talenta. Read [Security](docs/security.md) before removing a
307
+ session with `logout`. If the saved token already expired, `logout` still
308
+ removes the local session. If a command returns `mobile_token_expired` while
309
+ `tlnt login` says `Already logged in`, run `tlnt logout` and then
310
+ `tlnt login`. If a command prints the Google Play version notice,
311
+ see [App version check](#talenta-app-version-check).
312
+
313
+ ## License
314
+
315
+ `tlnt` is licensed under the [MIT License](LICENSE).
@@ -0,0 +1,296 @@
1
+ ![tlnt CLI logo](assets/logo.png)
2
+
3
+ # tlnt
4
+
5
+ ![CI](https://github.com/fathirazarthuro/tlnt/actions/workflows/ci.yml/badge.svg)
6
+ ![License](https://img.shields.io/github/license/fathirazarthuro/tlnt)
7
+
8
+ `tlnt` is a macOS Apple Silicon CLI for Mekari Talenta employment data,
9
+ notifications, attendance summaries and previews, and human-confirmed attendance actions.
10
+
11
+ > [!WARNING]
12
+ > `tlnt` is an unofficial, independent research and educational project. It
13
+ > is not affiliated with Mekari or Talenta. Use it only when your account and
14
+ > the actions you perform are authorized. Read the [full bilingual
15
+ > disclaimer](docs/index.md#disclaimer) before using it.
16
+
17
+ ## Why tlnt?
18
+
19
+ - Inspect employment and notification data from the terminal.
20
+ - Read attendance summaries and metrics.
21
+ - Read time-off data and submit or cancel requests with confirmation.
22
+ - Preview attendance requests before submitting them.
23
+ - Keep login visible and live actions human-confirmed.
24
+ - Warn when a newer tlnt is on PyPI, or when your configured Talenta app
25
+ version differs from Google Play.
26
+ - Update itself with `tlnt update`.
27
+ - Provide stable JSON output and a read-only MCP server for agents.
28
+
29
+ ## Install
30
+
31
+ Install from PyPI with [uv](https://docs.astral.sh/uv/):
32
+
33
+ ```bash
34
+ uv tool install tlnt-cli
35
+ ```
36
+
37
+ Or use `pipx install tlnt-cli` or `pip install tlnt-cli`. PyPI refuses the name
38
+ `tlnt` as too similar to an existing project, so the package is `tlnt-cli`; the
39
+ command is still `tlnt`.
40
+
41
+ For other install methods (`uvx`, from source) and the agent-specific path,
42
+ choose the instructions for your audience:
43
+
44
+ - [For humans](docs/integrations.md#for-humans)
45
+ - [For LLM agents](docs/integrations.md#for-llm-agents)
46
+
47
+ Login uses Playwright to open your installed Google Chrome or Microsoft Edge;
48
+ nothing is downloaded. To use a browser you already run instead, see
49
+ [Sign in with your own browser](#sign-in-with-your-own-browser). To have tlnt
50
+ type your email and password for you, see
51
+ [Sign in from the terminal](#sign-in-from-the-terminal).
52
+
53
+ ### Configure
54
+
55
+ Before first use, create the config file:
56
+
57
+ ```bash
58
+ tlnt setup
59
+ ```
60
+
61
+ It creates `config.json` in the default OS config folder (or the file given
62
+ with `--config PATH`) with every supported key. Ask the project maintainers for
63
+ `client_id` and set it there. Run `tlnt setup` again after `tlnt update`: it
64
+ adds new keys, removes keys tlnt no longer reads, and keeps your values.
65
+
66
+ See [Setup](docs/setup.md) for configuration and login prerequisites.
67
+ `tlnt` never opens login automatically from another command.
68
+
69
+ ### Sign in with your own browser
70
+
71
+ `tlnt login --cdp` attaches to a browser that is already running instead of
72
+ launching one. tlnt opens one tab in it, you sign in on Mekari's page, and only
73
+ that tab is closed. With Chrome, use a dedicated profile folder (Chrome 136 and
74
+ later ignore the DevTools port on the default profile):
75
+
76
+ ```bash
77
+ # terminal 1: leave running
78
+ "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" \
79
+ --remote-debugging-port=9222 --user-data-dir="$HOME/.tlnt-chrome"
80
+ # terminal 2
81
+ tlnt login --cdp 9222
82
+ ```
83
+
84
+ With agent-browser:
85
+
86
+ ```bash
87
+ agent-browser --session tlnt-login --headed open about:blank
88
+ tlnt login --cdp "$(agent-browser --session tlnt-login get cdp-url)"
89
+ agent-browser --session tlnt-login close
90
+ ```
91
+
92
+ See [Setup](docs/setup.md#sign-in-with-a-browser-you-already-run) for details.
93
+
94
+ ### Sign in from the terminal
95
+
96
+ `tlnt login --email you@example.com` asks for your Mekari password with a hidden
97
+ prompt and types both into Mekari's own sign-in page. There is no `--password`
98
+ flag. See [Setup](docs/setup.md#sign-in-from-the-terminal) for hosts with no
99
+ terminal.
100
+
101
+ ## Update tlnt
102
+
103
+ ```bash
104
+ tlnt update
105
+ ```
106
+
107
+ `tlnt update` installs the latest PyPI release with
108
+ `uv tool install tlnt-cli==<version> --force` when it is newer than the installed
109
+ version, and never downgrades. It needs `uv` on `PATH`, prints uv's output, and
110
+ exits with uv's exit code.
111
+
112
+ Installed tlnt 1.5.0 or earlier, when the package was still named `tlnt`?
113
+ Switch once:
114
+
115
+ ```bash
116
+ uv tool install tlnt-cli --force && uv tool uninstall tlnt && uv tool install tlnt-cli --force
117
+ ```
118
+
119
+ If the first install fails, nothing changes. Uninstalling the old package also
120
+ removes the `tlnt` command, so the last install puts it back. After that,
121
+ `tlnt update` works.
122
+
123
+ ## tlnt version check
124
+
125
+ Every command except `mcp` and `update` also checks PyPI for a newer tlnt. If
126
+ one exists, a notice appears on stderr:
127
+
128
+ ```text
129
+ ⚠️ tlnt v1.4.0 is installed, but v1.5.0 is available. Run `tlnt update` to update.
130
+ ```
131
+
132
+ The lookup times out after 3 seconds and its result is cached for 24 hours, a
133
+ failed lookup included, and the check stays silent when PyPI is unreachable. Stdout, `--json` results, and exit codes
134
+ are unchanged. The notice never updates anything by itself.
135
+
136
+ ## Talenta app version check
137
+
138
+ Talenta requests carry the mobile app version from `app_version` in your
139
+ config. Every command except `mcp` and `update` compares it with the latest
140
+ version in the [Talenta Google Play
141
+ listing](https://play.google.com/store/apps/details?id=co.talenta&hl=id). If
142
+ they differ, a notice appears on stderr:
143
+
144
+ ```text
145
+ ⚠️ 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`.
146
+ ```
147
+
148
+ Update `app_version` (and optionally `user_agent_mobile`; see
149
+ [Setup](docs/setup.md)), then log out and log in again. The lookup times out
150
+ after 3 seconds and its result is cached for 24 hours, a failed lookup
151
+ included, and the check stays silent when Google Play is unreachable. Stdout, `--json` results, and exit codes are
152
+ unchanged. The notice never logs out, logs in, or updates anything by itself.
153
+
154
+ ## Modes at a glance
155
+
156
+ | Mode | Flag | Behavior |
157
+ | --- | --- | --- |
158
+ | Machine output | `--json` | Writes one result object to stdout. |
159
+ | Diagnostics | `--verbose` | Adds DEBUG diagnostics without changing stdout. |
160
+ | Safe preview | `--dry-run` | Builds an attendance preview without submitting it. |
161
+ | 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. |
162
+ | Interactive input | `--interactive` | Prompts for missing values on supported commands; refuses to run without a TTY or with `--json`. |
163
+
164
+ Use `--json` when output will be consumed by an agent. Clock-in and
165
+ clock-out confirmation prompts use stdout in human mode and stderr with
166
+ `--json`; diagnostics use stderr.
167
+
168
+ ## Common workflows
169
+
170
+ These examples assume settings come from the default OS config path or
171
+ environment variables. If you use a non-default config file, pass
172
+ `--config PATH` before each command that needs its values.
173
+
174
+ Read employment information:
175
+
176
+ ```bash
177
+ tlnt profile --json
178
+ ```
179
+
180
+ Read notifications and attendance summaries. Summary commands default to the
181
+ local date; use `--date YYYY-MM-DD` to select another day:
182
+
183
+ ```bash
184
+ tlnt notification count --json
185
+ tlnt notification list --page 1 --query "" --status 3 --json
186
+ tlnt notification detail INBOX_ID --json
187
+ tlnt attendance summary-list --json
188
+ tlnt attendance summary-metrics --json
189
+ ```
190
+
191
+ Preview, then explicitly confirm a live attendance action:
192
+
193
+ ```bash
194
+ tlnt attendance clock-in \
195
+ --dry-run --latitude LATITUDE --longitude LONGITUDE --notes "Preview" --json
196
+ tlnt attendance clock-in \
197
+ --latitude LATITUDE --longitude LONGITUDE --notes "On time" --json
198
+ ```
199
+
200
+ Review an attendance request before approval:
201
+
202
+ ```bash
203
+ tlnt notification detail INBOX_ID --json
204
+ tlnt attendance approve INBOX_ID --reason "Reviewed" --json
205
+ ```
206
+
207
+ See [Workflows](docs/workflows.md) for the complete safe procedures.
208
+
209
+ ## Calendar commands
210
+
211
+ These calendar lookups are read-only and use the current Talenta mobile token.
212
+ Filtered commands default to `--limit 10` and `--page 1`; other filters are
213
+ sent only when supplied. `birthday` lists employee birthdays and can be
214
+ filtered to one employee with `--user-id`. `my-birthday` returns your
215
+ own birth date.
216
+
217
+ ```bash
218
+ tlnt calendar holiday --start-date 2026-01-01 --end-date 2026-12-31 --json
219
+ tlnt calendar timeoff --start-date 2026-09-27 --end-date 2026-09-27 --json
220
+ tlnt calendar index --month 2 --year 2026 --json
221
+ tlnt calendar my-birthday --json
222
+ tlnt calendar birthday --start-date 2026-09-27 --end-date 2026-09-27 --json
223
+ tlnt calendar activity --start-date 2026-01-01 --end-date 2026-12-31 --json
224
+ ```
225
+
226
+ Holiday, time-off, index, birthday, and activity commands also accept
227
+ `--start-date`, `--end-date`, `--limit`, `--month`, `--year`,
228
+ `--page`, `--id`, `--type`, `--search`, `--date`, and `--user-id`.
229
+ The personal `my-birthday` command has no filters.
230
+
231
+ ## Time-off commands
232
+
233
+ Lookup commands are read-only. Time-off requests, approvals, and cancellations
234
+ require terminal confirmation; declining sends nothing. Balance requests use the signed-in
235
+ profile's company and user IDs.
236
+
237
+ ```bash
238
+ tlnt timeoff types-list --json
239
+ tlnt timeoff balance --json
240
+ tlnt timeoff balance --show-unlimited-balance --json
241
+ tlnt timeoff delegation-list --search "NAME" --json
242
+ tlnt timeoff list --json
243
+ tlnt timeoff detail REQUEST_ID --json
244
+ tlnt timeoff request --date 2026-10-12 --policy-id 4448 --reason "reason"
245
+ tlnt timeoff request --date 2026-10-12 --policy-id 4448 --reason "reason" --half-day after --schedule-in 13:00 --schedule-out 18:00
246
+ 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
247
+ tlnt timeoff cancel REQUEST_ID
248
+ tlnt timeoff approve INBOX_ID --reason "Reviewed"
249
+ ```
250
+
251
+ See [Commands](docs/commands.md#time-off-data) for filters, defaults, and half-day details.
252
+
253
+ ## Safety contract
254
+
255
+ - Do not open the login flow automatically.
256
+ - Never ask the user for their Mekari password. Only they start
257
+ `tlnt login --email`, and the password comes from a hidden prompt or from
258
+ `TALENTA_PASSWORD` in the host's own environment.
259
+ - Live clock-in, clock-out, approval, time-off requests, and cancellations always require terminal confirmation.
260
+ - `--dry-run` never submits attendance.
261
+ - MCP cannot log in, log out, approve attendance, or submit attendance.
262
+ - The version checks only read public listings (PyPI and Google Play), never
263
+ send your session or config, and never log out, log in, or update for you.
264
+ - Never print passwords, bearer tokens, cookies, authorization codes, request
265
+ bodies, selfie contents, or real employee data.
266
+ - If `status` returns `session_missing`, `session_invalid`,
267
+ `mobile_token_missing`, or `mobile_token_expired`, ask
268
+ the user to run login explicitly.
269
+
270
+ ## Documentation
271
+
272
+ - [Docs site](https://tlnt-docs.vercel.app)
273
+ - [Cookbook](docs/cookbook.md)
274
+ - [Setup](docs/setup.md)
275
+ - [Commands and JSON contract](docs/commands.md)
276
+ - [Workflows](docs/workflows.md)
277
+ - [AI agent integrations](docs/integrations.md)
278
+ - [Security](docs/security.md)
279
+ - [Contributing](docs/contributing.md)
280
+ - [Agent skill](skills/tlnt-cli/SKILL.md)
281
+
282
+ ## Troubleshooting
283
+
284
+ Login drives your installed Google Chrome or Microsoft Edge through
285
+ Playwright, so one of them must be installed, unless you attach to a browser you
286
+ already run with `tlnt login --cdp` (see [Setup](docs/setup.md#login)). Use `tlnt status --json` to inspect the local session without
287
+ contacting Talenta. Read [Security](docs/security.md) before removing a
288
+ session with `logout`. If the saved token already expired, `logout` still
289
+ removes the local session. If a command returns `mobile_token_expired` while
290
+ `tlnt login` says `Already logged in`, run `tlnt logout` and then
291
+ `tlnt login`. If a command prints the Google Play version notice,
292
+ see [App version check](#talenta-app-version-check).
293
+
294
+ ## License
295
+
296
+ `tlnt` is licensed under the [MIT License](LICENSE).
@@ -0,0 +1,43 @@
1
+ [build-system]
2
+ requires = ["uv_build>=0.9,<0.13"]
3
+ build-backend = "uv_build"
4
+
5
+ [project]
6
+ name = "tlnt-cli"
7
+ version = "1.5.1"
8
+ description = "CLI wrapper for HRIS attendance and employment workflows."
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ license-files = ["LICENSE"]
12
+ requires-python = ">=3.11,<3.15"
13
+ dependencies = [
14
+ "httpx>=0.28,<0.29",
15
+ "keyring>=25,<26",
16
+ "loguru>=0.7,<1",
17
+ "mcp>=2.0,<3",
18
+ "platformdirs>=4.3,<5",
19
+ "playwright>=1.50,<2",
20
+ "rich>=14,<16",
21
+ "rich-pixels>=3,<4",
22
+ "typer>=0.20,<1",
23
+ ]
24
+
25
+ [[project.authors]]
26
+ name = "Fathiraz Arthuro"
27
+
28
+ [project.scripts]
29
+ tlnt = "tlnt.cli.main:main"
30
+
31
+ [dependency-groups]
32
+ dev = ["pytest>=9,<10"]
33
+ docs = [
34
+ "mkdocs>=1.6,<2",
35
+ "mkdocs-shadcn>=0.9,<1",
36
+ ]
37
+
38
+ [tool.uv.build-backend]
39
+ module-name = "tlnt"
40
+
41
+ [tool.pytest.ini_options]
42
+ addopts = "-q"
43
+ pythonpath = ["src"]