operx-cli 0.2.0__tar.gz → 0.2.2__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 (48) hide show
  1. {operx_cli-0.2.0/operx_cli.egg-info → operx_cli-0.2.2}/PKG-INFO +25 -7
  2. operx_cli-0.2.0/PKG-INFO → operx_cli-0.2.2/README.md +195 -191
  3. operx_cli-0.2.2/operx_cli/AGENTES.md +134 -0
  4. {operx_cli-0.2.0 → operx_cli-0.2.2}/operx_cli/__init__.py +1 -1
  5. operx_cli-0.2.2/operx_cli/agent_guide.py +57 -0
  6. {operx_cli-0.2.0 → operx_cli-0.2.2}/operx_cli/app.py +7 -0
  7. {operx_cli-0.2.0 → operx_cli-0.2.2}/operx_cli/commands/account.py +2 -1
  8. {operx_cli-0.2.0 → operx_cli-0.2.2}/operx_cli/shell.py +14 -3
  9. {operx_cli-0.2.0 → operx_cli-0.2.2}/operx_cli/welcome.py +2 -0
  10. operx_cli-0.2.0/README.md → operx_cli-0.2.2/operx_cli.egg-info/PKG-INFO +209 -177
  11. {operx_cli-0.2.0 → operx_cli-0.2.2}/operx_cli.egg-info/SOURCES.txt +3 -0
  12. {operx_cli-0.2.0 → operx_cli-0.2.2}/pyproject.toml +5 -1
  13. operx_cli-0.2.2/tests/test_agentes.py +44 -0
  14. {operx_cli-0.2.0 → operx_cli-0.2.2}/tests/test_app.py +3 -0
  15. {operx_cli-0.2.0 → operx_cli-0.2.2}/tests/test_shell.py +43 -0
  16. {operx_cli-0.2.0 → operx_cli-0.2.2}/tests/test_welcome.py +7 -0
  17. {operx_cli-0.2.0 → operx_cli-0.2.2}/operx_cli/browser_login.py +0 -0
  18. {operx_cli-0.2.0 → operx_cli-0.2.2}/operx_cli/client.py +0 -0
  19. {operx_cli-0.2.0 → operx_cli-0.2.2}/operx_cli/commands/__init__.py +0 -0
  20. {operx_cli-0.2.0 → operx_cli-0.2.2}/operx_cli/commands/common.py +0 -0
  21. {operx_cli-0.2.0 → operx_cli-0.2.2}/operx_cli/commands/inventario.py +0 -0
  22. {operx_cli-0.2.0 → operx_cli-0.2.2}/operx_cli/commands/lecturas.py +0 -0
  23. {operx_cli-0.2.0 → operx_cli-0.2.2}/operx_cli/commands/ordenes.py +0 -0
  24. {operx_cli-0.2.0 → operx_cli-0.2.2}/operx_cli/commands/personas.py +0 -0
  25. {operx_cli-0.2.0 → operx_cli-0.2.2}/operx_cli/commands/raw.py +0 -0
  26. {operx_cli-0.2.0 → operx_cli-0.2.2}/operx_cli/commands/registros.py +0 -0
  27. {operx_cli-0.2.0 → operx_cli-0.2.2}/operx_cli/commands/search.py +0 -0
  28. {operx_cli-0.2.0 → operx_cli-0.2.2}/operx_cli/lookup.py +0 -0
  29. {operx_cli-0.2.0 → operx_cli-0.2.2}/operx_cli/output.py +0 -0
  30. {operx_cli-0.2.0 → operx_cli-0.2.2}/operx_cli/settings.py +0 -0
  31. {operx_cli-0.2.0 → operx_cli-0.2.2}/operx_cli/spreadsheet.py +0 -0
  32. {operx_cli-0.2.0 → operx_cli-0.2.2}/operx_cli/values.py +0 -0
  33. {operx_cli-0.2.0 → operx_cli-0.2.2}/operx_cli.egg-info/dependency_links.txt +0 -0
  34. {operx_cli-0.2.0 → operx_cli-0.2.2}/operx_cli.egg-info/entry_points.txt +0 -0
  35. {operx_cli-0.2.0 → operx_cli-0.2.2}/operx_cli.egg-info/requires.txt +0 -0
  36. {operx_cli-0.2.0 → operx_cli-0.2.2}/operx_cli.egg-info/top_level.txt +0 -0
  37. {operx_cli-0.2.0 → operx_cli-0.2.2}/setup.cfg +0 -0
  38. {operx_cli-0.2.0 → operx_cli-0.2.2}/tests/test_client.py +0 -0
  39. {operx_cli-0.2.0 → operx_cli-0.2.2}/tests/test_inventario_lecturas.py +0 -0
  40. {operx_cli-0.2.0 → operx_cli-0.2.2}/tests/test_login.py +0 -0
  41. {operx_cli-0.2.0 → operx_cli-0.2.2}/tests/test_lookup.py +0 -0
  42. {operx_cli-0.2.0 → operx_cli-0.2.2}/tests/test_ordenes.py +0 -0
  43. {operx_cli-0.2.0 → operx_cli-0.2.2}/tests/test_output.py +0 -0
  44. {operx_cli-0.2.0 → operx_cli-0.2.2}/tests/test_personas.py +0 -0
  45. {operx_cli-0.2.0 → operx_cli-0.2.2}/tests/test_registros.py +0 -0
  46. {operx_cli-0.2.0 → operx_cli-0.2.2}/tests/test_settings.py +0 -0
  47. {operx_cli-0.2.0 → operx_cli-0.2.2}/tests/test_spreadsheet.py +0 -0
  48. {operx_cli-0.2.0 → operx_cli-0.2.2}/tests/test_values.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: operx-cli
3
- Version: 0.2.0
3
+ Version: 0.2.2
4
4
  Summary: La línea de comandos de OperX: tu empresa desde la terminal, con tu token de API.
5
5
  Requires-Python: >=3.10
6
6
  Description-Content-Type: text/markdown
@@ -47,7 +47,8 @@ operx login
47
47
  1. La terminal muestra un código y abre el navegador en la página de OperX.
48
48
  2. Entras como siempre. La página dice qué terminal pide acceso: apruébalo solo
49
49
  si acabas de escribir `operx login` en tu propio computador y el código es
50
- el mismo. Escribe tu contraseña y elige *Solo lectura* o *Lectura y
50
+ el mismo. Escribe el código de 6 dígitos de tu app de autenticación (o tu
51
+ contraseña, si no usas una) y elige *Solo lectura* o *Lectura y
51
52
  escritura*.
52
53
  3. Vuelve a la terminal: ya entraste. Nunca ves ni copias un token.
53
54
 
@@ -161,6 +162,13 @@ operx api POST work-orders/1234/attachments/ -a file=foto.jpg -d '{"file_type":
161
162
  En Git Bash, una dirección que empieza por `/` se vuelve una ruta de Windows:
162
163
  escríbela sin la barra inicial, como arriba.
163
164
 
165
+ ## Para agentes de IA
166
+
167
+ `operx agentes` imprime una guía para un agente de IA (Claude, ChatGPT,
168
+ Copilot, Codex…): las reglas para usar `operx` bien (leer con `--json`,
169
+ preguntar antes de escribir, no tocar tokens) y cada comando con sus opciones.
170
+ Dile a tu agente: «Ejecuta `operx agentes` y sigue esa guía».
171
+
164
172
  ## Para desarrollar
165
173
 
166
174
  ```sh
@@ -180,12 +188,22 @@ si algo falla, se sube la siguiente.
180
188
  1. Sube el número en `pyproject.toml` y en `operx_cli/__init__.py`.
181
189
  2. Las funciones nuevas del servidor (como `operx login`) tienen que estar ya
182
190
  desplegadas en producción antes de publicar: el paquete nuevo las llama.
183
- 3. Desde `cli/`, con un entorno que tenga `build` y `twine`:
191
+ 3. Desde `cli/`:
184
192
 
185
193
  ```sh
186
- python -m build
187
- python -m twine upload dist/* # usuario __token__, y el token del proyecto
194
+ uv build --clear
195
+ uv publish
188
196
  ```
189
197
 
190
- El token de PyPI es secreto: se escribe en tu terminal, nunca en un archivo del
191
- repositorio ni en un chat.
198
+ `uv publish` toma el token de PyPI de la variable de entorno
199
+ `UV_PUBLISH_TOKEN`. Usa un token solo del proyecto `operx-cli` (PyPI › Account
200
+ settings › API tokens). Se guarda una vez, en tu usuario de Windows, desde
201
+ PowerShell; lo pegas donde lo pide y no se ve:
202
+
203
+ ```powershell
204
+ $token = Read-Host "Token de PyPI" -AsSecureString
205
+ [Environment]::SetEnvironmentVariable("UV_PUBLISH_TOKEN", [Net.NetworkCredential]::new("", $token).Password, "User")
206
+ ```
207
+
208
+ Las terminales que abras después ya lo tienen. El token es secreto: nunca va
209
+ en un archivo del repositorio ni en un chat.
@@ -1,191 +1,195 @@
1
- Metadata-Version: 2.4
2
- Name: operx-cli
3
- Version: 0.2.0
4
- Summary: La línea de comandos de OperX: tu empresa desde la terminal, con tu token de API.
5
- Requires-Python: >=3.10
6
- Description-Content-Type: text/markdown
7
- Requires-Dist: typer>=0.27
8
- Requires-Dist: httpx>=0.28
9
- Requires-Dist: keyring>=25
10
- Requires-Dist: openpyxl>=3.1
11
- Requires-Dist: prompt_toolkit>=3.0
12
- Provides-Extra: test
13
- Requires-Dist: pytest>=8; extra == "test"
14
-
15
- # operx: OperX desde la terminal
16
-
17
- `operx` usa la API de OperX con tu token personal: lo mismo que puedes hacer
18
- en la app, desde una terminal, un script o una tarea programada. Actúa como
19
- tú, con tu rol, y solo en tu empresa.
20
-
21
- ## Instalar
22
-
23
- Windows (PowerShell):
24
-
25
- ```powershell
26
- powershell -c "irm https://astral.sh/uv/install.ps1 | iex"; uv tool install operx-cli
27
- ```
28
-
29
- Mac y Linux:
30
-
31
- ```sh
32
- curl -LsSf https://astral.sh/uv/install.sh | sh && uv tool install operx-cli
33
- ```
34
-
35
- `uv` instala su propio Python, así que no necesitas tener uno. Si ya tienes
36
- Python 3.10 o más nuevo, también sirve `pipx install operx-cli`. Abre una
37
- terminal nueva y comprueba con `operx --version`.
38
-
39
- Para actualizar: `uv tool upgrade operx-cli`.
40
-
41
- ## Entrar
42
-
43
- ```sh
44
- operx login
45
- ```
46
-
47
- 1. La terminal muestra un código y abre el navegador en la página de OperX.
48
- 2. Entras como siempre. La página dice qué terminal pide acceso: apruébalo solo
49
- si acabas de escribir `operx login` en tu propio computador y el código es
50
- el mismo. Escribe tu contraseña y elige *Solo lectura* o *Lectura y
51
- escritura*.
52
- 3. Vuelve a la terminal: ya entraste. Nunca ves ni copias un token.
53
-
54
- Tu rol necesita el permiso «Acceso por API» (Ajustes › Usuarios y acceso ›
55
- Roles); un administrador lo da. El acceso dura 90 días y lo ves, y puedes
56
- revocarlo, en el menú de tu cuenta › Acceso por API.
57
-
58
- El token queda en el llavero del sistema (en Windows, el Administrador de
59
- credenciales), nunca en un archivo. En un servidor sin navegador ni llavero:
60
- `operx login --token` te deja pegar un token creado en Acceso por API, o puedes
61
- usar variables de entorno: `OPERX_TOKEN` (el token) y, si no es producción,
62
- `OPERX_DIRECCION`.
63
-
64
- Para otra dirección u otra empresa, usa un perfil:
65
-
66
- ```sh
67
- operx --perfil pruebas login --direccion https://…
68
- operx --perfil pruebas ordenes listar
69
- ```
70
-
71
- `operx logout` borra el token de este equipo; para que deje de funcionar,
72
- revócalo en Acceso por API.
73
-
74
- ## Modo interactivo
75
-
76
- Escribe `operx` solo, en una terminal, y se abre la pantalla de bienvenida
77
- (quién eres y los números de hoy: órdenes abiertas, vencidas, artículos bajo
78
- el mínimo) con un prompt. Ahí escribes los comandos sin el `operx`, con
79
- Tab para completar y ↑ para repetir lo anterior:
80
-
81
- ```
82
- operx › ordenes listar --vencidas
83
- operx › buscar "bomba"
84
- operx › ayuda
85
- operx › salir
86
- ```
87
-
88
- `salir` (o Ctrl+D) termina la sesión sin borrar tu token. En un script o una
89
- tubería, `operx` solo muestra la ayuda y no espera a nadie.
90
-
91
- ## Comandos
92
-
93
- ```sh
94
- operx buscar "bomba" # como la barra de búsqueda de la app
95
-
96
- operx ordenes listar --estado en-progreso --asignada-a yo
97
- operx ordenes ver 1234
98
- operx ordenes crear --titulo "Cambio de rodamiento" --equipo BOM-04 --prioridad alta --vence 30/10/2026
99
- operx ordenes estado 1234 completada
100
- operx ordenes asignar 1234 "Pedro Pérez"
101
- operx ordenes comentar 1234 "Llegó el repuesto"
102
-
103
- operx equipos listar --buscar compresor
104
- operx equipos ver BOM-04
105
- operx equipos crear --nombre "Bomba 4" --codigo BOM-04 --lugar "Planta Norte"
106
- operx clientes listar
107
- operx clientes crear --nombre "Acme S.A.S." --nit 900123456
108
- operx clientes crear --nombre "Filtros Ltda" --rol proveedor
109
- operx lugares listar
110
-
111
- operx inventario existencias --buscar filtro
112
- operx inventario entrada --articulo FIL-010 --lugar "Bodega central" --cantidad 10 --costo-unitario 1.500,50
113
- operx inventario salida --articulo FIL-010 --lugar "Bodega central" --cantidad 2 --motivo Consumo
114
-
115
- operx lecturas puntos BOM-04
116
- operx lecturas registrar --punto 12 --valor 73,4
117
-
118
- operx personas importar empleados.xlsx # revisa el archivo, no guarda
119
- operx personas importar empleados.xlsx --confirmar # guarda si ninguna fila tiene errores
120
- ```
121
-
122
- `operx --help` y `operx ordenes --help` muestran todas las opciones.
123
-
124
- - Los equipos, lugares, clientes, artículos y personas se nombran por su
125
- código o su nombre exacto. Si dos se llaman igual, `operx` lo dice y pide
126
- el id.
127
- - Los números y las fechas se escriben como en la app: `73,4`, `1.500,50`,
128
- `30/10/2026`, `22/10/2026 08:00`.
129
- - Las listas muestran la primera página; `--todas` las trae todas.
130
- - `--json` da todo lo que responde la API; `--csv` da un CSV que Excel abre
131
- bien (`operx equipos listar --todas --csv > equipos.csv`).
132
-
133
- ### Antes de escribir
134
-
135
- Todo lo que crea o cambia algo pregunta antes. En un script o una tarea
136
- programada no hay a quién preguntar: agrega `--si`. Cada escritura queda en
137
- el historial del token (Acceso por API › el token › Actividad) marcada como
138
- hecha desde la CLI.
139
-
140
- ### Importar personas
141
-
142
- La primera columna con el nombre basta. `operx` reconoce las columnas
143
- Nombres, Apellidos, Código, Cargo, Tipo de contrato, Fecha de ingreso, Fin de
144
- contrato, Celular, Sede y las de contacto de emergencia, con o sin tildes.
145
- Una columna con otro nombre se indica con `--mapa "Tu columna=campo"`.
146
- Nadie recibe acceso a la app al importarlo: las invitaciones se envían en
147
- Usuarios y acceso.
148
-
149
- ### Cualquier otra llamada
150
-
151
- Lo que no tiene comando propio se hace con `operx api`, con las direcciones
152
- de Acceso por API › Documentación (sin `/api/v1/`):
153
-
154
- ```sh
155
- operx api GET pm/schedules/ -q search=compresor
156
- operx api POST contacts/ -d @contacto.json
157
- operx api GET work-orders/export/ -o ordenes.csv
158
- operx api POST work-orders/1234/attachments/ -a file=foto.jpg -d '{"file_type": "photo"}'
159
- ```
160
-
161
- En Git Bash, una dirección que empieza por `/` se vuelve una ruta de Windows:
162
- escríbela sin la barra inicial, como arriba.
163
-
164
- ## Para desarrollar
165
-
166
- ```sh
167
- cd cli
168
- python -m venv .venv && .venv/Scripts/python -m pip install -e ".[test]"
169
- .venv/Scripts/python -m pytest
170
- ```
171
-
172
- `operx_cli/client.py` es lo único que habla con la red; el servidor MCP lo
173
- usará igual.
174
-
175
- ### Publicar una versión
176
-
177
- El paquete es `operx-cli` en PyPI. Una versión publicada no se puede reemplazar:
178
- si algo falla, se sube la siguiente.
179
-
180
- 1. Sube el número en `pyproject.toml` y en `operx_cli/__init__.py`.
181
- 2. Las funciones nuevas del servidor (como `operx login`) tienen que estar ya
182
- desplegadas en producción antes de publicar: el paquete nuevo las llama.
183
- 3. Desde `cli/`, con un entorno que tenga `build` y `twine`:
184
-
185
- ```sh
186
- python -m build
187
- python -m twine upload dist/* # usuario __token__, y el token del proyecto
188
- ```
189
-
190
- El token de PyPI es secreto: se escribe en tu terminal, nunca en un archivo del
191
- repositorio ni en un chat.
1
+ # operx: OperX desde la terminal
2
+
3
+ `operx` usa la API de OperX con tu token personal: lo mismo que puedes hacer
4
+ en la app, desde una terminal, un script o una tarea programada. Actúa como
5
+ tú, con tu rol, y solo en tu empresa.
6
+
7
+ ## Instalar
8
+
9
+ Windows (PowerShell):
10
+
11
+ ```powershell
12
+ powershell -c "irm https://astral.sh/uv/install.ps1 | iex"; uv tool install operx-cli
13
+ ```
14
+
15
+ Mac y Linux:
16
+
17
+ ```sh
18
+ curl -LsSf https://astral.sh/uv/install.sh | sh && uv tool install operx-cli
19
+ ```
20
+
21
+ `uv` instala su propio Python, así que no necesitas tener uno. Si ya tienes
22
+ Python 3.10 o más nuevo, también sirve `pipx install operx-cli`. Abre una
23
+ terminal nueva y comprueba con `operx --version`.
24
+
25
+ Para actualizar: `uv tool upgrade operx-cli`.
26
+
27
+ ## Entrar
28
+
29
+ ```sh
30
+ operx login
31
+ ```
32
+
33
+ 1. La terminal muestra un código y abre el navegador en la página de OperX.
34
+ 2. Entras como siempre. La página dice qué terminal pide acceso: apruébalo solo
35
+ si acabas de escribir `operx login` en tu propio computador y el código es
36
+ el mismo. Escribe el código de 6 dígitos de tu app de autenticación (o tu
37
+ contraseña, si no usas una) y elige *Solo lectura* o *Lectura y
38
+ escritura*.
39
+ 3. Vuelve a la terminal: ya entraste. Nunca ves ni copias un token.
40
+
41
+ Tu rol necesita el permiso «Acceso por API» (Ajustes › Usuarios y acceso ›
42
+ Roles); un administrador lo da. El acceso dura 90 días y lo ves, y puedes
43
+ revocarlo, en el menú de tu cuenta › Acceso por API.
44
+
45
+ El token queda en el llavero del sistema (en Windows, el Administrador de
46
+ credenciales), nunca en un archivo. En un servidor sin navegador ni llavero:
47
+ `operx login --token` te deja pegar un token creado en Acceso por API, o puedes
48
+ usar variables de entorno: `OPERX_TOKEN` (el token) y, si no es producción,
49
+ `OPERX_DIRECCION`.
50
+
51
+ Para otra dirección u otra empresa, usa un perfil:
52
+
53
+ ```sh
54
+ operx --perfil pruebas login --direccion https://…
55
+ operx --perfil pruebas ordenes listar
56
+ ```
57
+
58
+ `operx logout` borra el token de este equipo; para que deje de funcionar,
59
+ revócalo en Acceso por API.
60
+
61
+ ## Modo interactivo
62
+
63
+ Escribe `operx` solo, en una terminal, y se abre la pantalla de bienvenida
64
+ (quién eres y los números de hoy: órdenes abiertas, vencidas, artículos bajo
65
+ el mínimo) con un prompt. Ahí escribes los comandos sin el `operx`, con
66
+ Tab para completar y ↑ para repetir lo anterior:
67
+
68
+ ```
69
+ operx › ordenes listar --vencidas
70
+ operx › buscar "bomba"
71
+ operx › ayuda
72
+ operx › salir
73
+ ```
74
+
75
+ `salir` (o Ctrl+D) termina la sesión sin borrar tu token. En un script o una
76
+ tubería, `operx` solo muestra la ayuda y no espera a nadie.
77
+
78
+ ## Comandos
79
+
80
+ ```sh
81
+ operx buscar "bomba" # como la barra de búsqueda de la app
82
+
83
+ operx ordenes listar --estado en-progreso --asignada-a yo
84
+ operx ordenes ver 1234
85
+ operx ordenes crear --titulo "Cambio de rodamiento" --equipo BOM-04 --prioridad alta --vence 30/10/2026
86
+ operx ordenes estado 1234 completada
87
+ operx ordenes asignar 1234 "Pedro Pérez"
88
+ operx ordenes comentar 1234 "Llegó el repuesto"
89
+
90
+ operx equipos listar --buscar compresor
91
+ operx equipos ver BOM-04
92
+ operx equipos crear --nombre "Bomba 4" --codigo BOM-04 --lugar "Planta Norte"
93
+ operx clientes listar
94
+ operx clientes crear --nombre "Acme S.A.S." --nit 900123456
95
+ operx clientes crear --nombre "Filtros Ltda" --rol proveedor
96
+ operx lugares listar
97
+
98
+ operx inventario existencias --buscar filtro
99
+ operx inventario entrada --articulo FIL-010 --lugar "Bodega central" --cantidad 10 --costo-unitario 1.500,50
100
+ operx inventario salida --articulo FIL-010 --lugar "Bodega central" --cantidad 2 --motivo Consumo
101
+
102
+ operx lecturas puntos BOM-04
103
+ operx lecturas registrar --punto 12 --valor 73,4
104
+
105
+ operx personas importar empleados.xlsx # revisa el archivo, no guarda
106
+ operx personas importar empleados.xlsx --confirmar # guarda si ninguna fila tiene errores
107
+ ```
108
+
109
+ `operx --help` y `operx ordenes --help` muestran todas las opciones.
110
+
111
+ - Los equipos, lugares, clientes, artículos y personas se nombran por su
112
+ código o su nombre exacto. Si dos se llaman igual, `operx` lo dice y pide
113
+ el id.
114
+ - Los números y las fechas se escriben como en la app: `73,4`, `1.500,50`,
115
+ `30/10/2026`, `22/10/2026 08:00`.
116
+ - Las listas muestran la primera página; `--todas` las trae todas.
117
+ - `--json` da todo lo que responde la API; `--csv` da un CSV que Excel abre
118
+ bien (`operx equipos listar --todas --csv > equipos.csv`).
119
+
120
+ ### Antes de escribir
121
+
122
+ Todo lo que crea o cambia algo pregunta antes. En un script o una tarea
123
+ programada no hay a quién preguntar: agrega `--si`. Cada escritura queda en
124
+ el historial del token (Acceso por API › el token › Actividad) marcada como
125
+ hecha desde la CLI.
126
+
127
+ ### Importar personas
128
+
129
+ La primera columna con el nombre basta. `operx` reconoce las columnas
130
+ Nombres, Apellidos, Código, Cargo, Tipo de contrato, Fecha de ingreso, Fin de
131
+ contrato, Celular, Sede y las de contacto de emergencia, con o sin tildes.
132
+ Una columna con otro nombre se indica con `--mapa "Tu columna=campo"`.
133
+ Nadie recibe acceso a la app al importarlo: las invitaciones se envían en
134
+ Usuarios y acceso.
135
+
136
+ ### Cualquier otra llamada
137
+
138
+ Lo que no tiene comando propio se hace con `operx api`, con las direcciones
139
+ de Acceso por API › Documentación (sin `/api/v1/`):
140
+
141
+ ```sh
142
+ operx api GET pm/schedules/ -q search=compresor
143
+ operx api POST contacts/ -d @contacto.json
144
+ operx api GET work-orders/export/ -o ordenes.csv
145
+ operx api POST work-orders/1234/attachments/ -a file=foto.jpg -d '{"file_type": "photo"}'
146
+ ```
147
+
148
+ En Git Bash, una dirección que empieza por `/` se vuelve una ruta de Windows:
149
+ escríbela sin la barra inicial, como arriba.
150
+
151
+ ## Para agentes de IA
152
+
153
+ `operx agentes` imprime una guía para un agente de IA (Claude, ChatGPT,
154
+ Copilot, Codex…): las reglas para usar `operx` bien (leer con `--json`,
155
+ preguntar antes de escribir, no tocar tokens) y cada comando con sus opciones.
156
+ Dile a tu agente: «Ejecuta `operx agentes` y sigue esa guía».
157
+
158
+ ## Para desarrollar
159
+
160
+ ```sh
161
+ cd cli
162
+ python -m venv .venv && .venv/Scripts/python -m pip install -e ".[test]"
163
+ .venv/Scripts/python -m pytest
164
+ ```
165
+
166
+ `operx_cli/client.py` es lo único que habla con la red; el servidor MCP lo
167
+ usará igual.
168
+
169
+ ### Publicar una versión
170
+
171
+ El paquete es `operx-cli` en PyPI. Una versión publicada no se puede reemplazar:
172
+ si algo falla, se sube la siguiente.
173
+
174
+ 1. Sube el número en `pyproject.toml` y en `operx_cli/__init__.py`.
175
+ 2. Las funciones nuevas del servidor (como `operx login`) tienen que estar ya
176
+ desplegadas en producción antes de publicar: el paquete nuevo las llama.
177
+ 3. Desde `cli/`:
178
+
179
+ ```sh
180
+ uv build --clear
181
+ uv publish
182
+ ```
183
+
184
+ `uv publish` toma el token de PyPI de la variable de entorno
185
+ `UV_PUBLISH_TOKEN`. Usa un token solo del proyecto `operx-cli` (PyPI › Account
186
+ settings › API tokens). Se guarda una vez, en tu usuario de Windows, desde
187
+ PowerShell; lo pegas donde lo pide y no se ve:
188
+
189
+ ```powershell
190
+ $token = Read-Host "Token de PyPI" -AsSecureString
191
+ [Environment]::SetEnvironmentVariable("UV_PUBLISH_TOKEN", [Net.NetworkCredential]::new("", $token).Password, "User")
192
+ ```
193
+
194
+ Las terminales que abras después ya lo tienen. El token es secreto: nunca va
195
+ en un archivo del repositorio ni en un chat.
@@ -0,0 +1,134 @@
1
+ # operx para agentes de IA
2
+
3
+ Esta guía es para un agente de IA (Claude, ChatGPT, Copilot, Codex…) que usa
4
+ `operx` en nombre de una persona. `operx` llama a la API de OperX con el token
5
+ de esa persona: actúa como ella, con su rol, y solo en su empresa. Cada
6
+ llamada queda en el historial del token, marcada como hecha desde la CLI.
7
+
8
+ ## Reglas
9
+
10
+ 1. Escribe siempre el comando completo (`operx ordenes listar …`). No abras el
11
+ modo interactivo: `operx` solo, fuera de una terminal, solo muestra la ayuda.
12
+ 2. Lee con `--json`: es lo que responde la API, completo. Las tablas son para
13
+ personas.
14
+ 3. Antes de crear o cambiar algo, dile a la persona qué vas a hacer y espera
15
+ su sí. Con su sí, agrega `--si`: sin él, toda escritura falla fuera de una
16
+ terminal.
17
+ 4. Nunca pidas, muestres ni guardes un token o una contraseña. Si no hay
18
+ sesión, pídele a la persona que ejecute `operx login`.
19
+ 5. Si una escritura dice que la API no respondió a tiempo, no la repitas:
20
+ consulta primero si quedó hecha.
21
+ 6. Si un nombre coincide con varios registros, `operx` lo dice con sus ids:
22
+ usa el id, no adivines.
23
+ 7. Usa un comando propio cuando exista; `operx api` es para lo demás.
24
+
25
+ ## Entrar
26
+
27
+ - Empieza con `operx cuenta --json`: quién es la persona, su empresa, su rol
28
+ y los productos de la empresa (`products`).
29
+ - Si responde «No has entrado», la persona ejecuta `operx login`: se abre su
30
+ navegador, aprueba con su código y la terminal queda conectada 90 días.
31
+ Puedes ejecutarlo tú si la persona está frente al computador: espera hasta
32
+ 10 minutos a que apruebe.
33
+ - En un servidor sin navegador, la persona pone el token en la variable de
34
+ entorno `OPERX_TOKEN` (y `OPERX_DIRECCION` si no es producción).
35
+ - `--perfil NOMBRE` (o `OPERX_PERFIL`) usa otra empresa u otra dirección.
36
+
37
+ ## Leer
38
+
39
+ - Las listas traen la primera página y avisan en stderr cuántas filas hay en
40
+ total. `--todas` las trae todas.
41
+ - `--buscar TEXTO` filtra en el servidor. `operx buscar TEXTO --json` busca en
42
+ todo (órdenes, equipos, clientes, lugares y personas), desde 2 letras.
43
+ - `ver` da un registro completo: `operx ordenes ver 1234 --json`.
44
+ - En `--json` los valores van como los manda la API, en inglés: el `status`
45
+ de una orden es `open`, `in_progress`, `on_hold`, `completed`, `verified` o
46
+ `cancelled`, y su `priority` es `low`, `medium`, `high` o `critical`. Las
47
+ opciones de los comandos van en español: `--estado en-progreso`.
48
+ - Los resultados van a stdout y los avisos a stderr:
49
+ `operx equipos listar --todas --json > equipos.json` guarda solo los datos.
50
+ - `--csv` da un CSV para Excel (separado por punto y coma, con decimales con
51
+ coma).
52
+
53
+ ## Escribir
54
+
55
+ - Escriben: `ordenes crear`, `ordenes estado`, `ordenes asignar`,
56
+ `ordenes comentar`, `equipos crear`, `clientes crear`, `inventario entrada`,
57
+ `inventario salida`, `lecturas registrar`, `personas importar --confirmar`,
58
+ y `operx api` con POST, PUT, PATCH o DELETE. Todos llevan `--si`.
59
+ - `operx personas importar ARCHIVO` sin `--confirmar` solo revisa el archivo
60
+ y no guarda nada: hazlo primero y muéstrale el resultado a la persona.
61
+ - Un acceso de solo lectura no escribe: la API responde 403.
62
+ - Una orden se verifica en la app, nunca por la API. Un token nunca firma ni
63
+ aprueba, y la API nunca abre resultados médicos, nómina, quejas de
64
+ convivencia ni los archivos del SG-SST. Si algo responde 403, dile a la
65
+ persona que lo haga en la app (operx.pro).
66
+
67
+ ## Nombres, números y fechas
68
+
69
+ - Equipos, lugares, clientes, artículos y personas se nombran por su código o
70
+ su nombre exacto (sin importar mayúsculas), o por su id. Un nombre a medias
71
+ no sirve: busca primero con `listar --buscar` o `operx buscar`.
72
+ - `yo` es la persona dueña del token: `--asignada-a yo`, `--asignar-a yo`.
73
+ `operx ordenes asignar 1234 nadie` quita la asignación.
74
+ - Números como en la app: `73,4` o `1.500,50` (también `73.4`).
75
+ - Fechas con el día primero: `30/10/2026`; con hora: `22/10/2026 08:00`.
76
+ También sirven `2026-10-30` y `2026-10-22T08:00`. La hora es la del
77
+ computador.
78
+
79
+ ## Errores
80
+
81
+ | Código de salida | Qué pasó |
82
+ |---|---|
83
+ | 0 | Funcionó. |
84
+ | 1 | `operx` o la API lo rechazó. El motivo va en stderr, en una línea que empieza por `Error:`. |
85
+ | 2 | El comando está mal escrito: una opción que no existe o un dato que falta. Mira `operx COMANDO --help`. |
86
+
87
+ Lo que responde la API:
88
+
89
+ - **401**: el acceso venció o lo revocaron. La persona ejecuta `operx login`.
90
+ - **403**: el rol de la persona no lo permite, el acceso es de solo lectura,
91
+ la empresa no tiene ese producto, o un token no puede hacer eso.
92
+ - **404**: no existe, o la persona no lo puede ver.
93
+ - **400**: un dato no sirve. El mensaje dice cuál y por qué.
94
+ - **429**: demasiadas llamadas (120 por minuto por token, 600 por empresa).
95
+ `operx` espera y reintenta solo, hasta 3 veces.
96
+
97
+ ## Cualquier otra llamada: `operx api`
98
+
99
+ `operx api MÉTODO RUTA` hace cualquier llamada que el token pueda hacer y
100
+ responde el JSON de la API. Las rutas están en la app, en Acceso por API ›
101
+ Documentación; escríbelas sin `/api/v1/` y sin barra inicial.
102
+
103
+ - `-q nombre=valor`: un filtro. Se repite.
104
+ - `-d '{"campo": "valor"}'` o `-d @archivo.json`: el cuerpo de la llamada.
105
+ - `-a campo=ruta`: un archivo a subir. Se repite.
106
+ - `--todas`: todas las páginas de un GET.
107
+ - `-o archivo`: guarda una respuesta que es un archivo (CSV, PDF).
108
+
109
+ ```sh
110
+ operx api GET pm/schedules/ -q search=compresor
111
+ operx api POST contacts/ -d @contacto.json --si
112
+ operx api GET work-orders/export/ -o ordenes.csv
113
+ ```
114
+
115
+ ## Recetas
116
+
117
+ ```sh
118
+ # Las órdenes vencidas de la persona
119
+ operx ordenes listar --vencidas --asignada-a yo --todas --json
120
+
121
+ # Pasar una orden a completada, después de su sí
122
+ operx ordenes estado 1234 completada --si
123
+
124
+ # Registrar una lectura: primero el número del punto
125
+ operx lecturas puntos BOM-04 --json
126
+ operx lecturas registrar --punto 12 --valor 73,4 --si
127
+
128
+ # Sacar stock: primero el código y el lugar exactos
129
+ operx inventario existencias --buscar filtro --json
130
+ operx inventario salida --articulo FIL-010 --lugar "Bodega central" --cantidad 2 --motivo Consumo --si
131
+
132
+ # Los equipos en un CSV para Excel
133
+ operx equipos listar --todas --csv > equipos.csv
134
+ ```
@@ -2,4 +2,4 @@
2
2
  API (backend/users/api_allowlist.py) from a terminal, with a personal API
3
3
  token."""
4
4
 
5
- __version__ = "0.2.0"
5
+ __version__ = "0.2.2"
@@ -0,0 +1,57 @@
1
+ """`operx agentes`: the guide for AI agents (AGENTES.md), then every command
2
+ with its options, read from the commands themselves so the list matches the
3
+ installed version."""
4
+
5
+ from importlib.resources import files
6
+
7
+ ROOT_TITLE = "operx (opciones de cualquier comando)"
8
+
9
+
10
+ def guide_text(root):
11
+ rules = files("operx_cli").joinpath("AGENTES.md").read_text(encoding="utf-8")
12
+ return rules.rstrip("\n") + "\n\n" + reference(root)
13
+
14
+
15
+ def reference(root):
16
+ lines = ["## Todos los comandos", "", "Cada uno también tiene `--help`.", ""]
17
+ lines += _command_section(ROOT_TITLE, root)
18
+ for path, command in _commands(root, ["operx"]):
19
+ lines += _command_section(" ".join(path), command)
20
+ return "\n".join(lines)
21
+
22
+
23
+ def _commands(group, path):
24
+ """The commands a person can type, group by group, without the hidden ones."""
25
+ for name, command in group.commands.items():
26
+ if getattr(command, "hidden", False):
27
+ continue
28
+ if hasattr(command, "commands"):
29
+ yield from _commands(command, path + [name])
30
+ else:
31
+ yield path + [name], command
32
+
33
+
34
+ def _command_section(title, command):
35
+ lines = [f"### {title}", ""]
36
+ if command.help and title != ROOT_TITLE:
37
+ lines += [command.help.strip(), ""]
38
+ params = [param for param in command.params if not getattr(param, "hidden", False)]
39
+ lines += [f"- {_param_line(param)}" for param in params]
40
+ return lines + ([""] if params else [])
41
+
42
+
43
+ def _param_line(param):
44
+ if param.param_type_name == "argument":
45
+ line = f"`{param.name.upper()}`"
46
+ else:
47
+ line = ", ".join(f"`{opt}`" for opt in param.opts)
48
+ choices = getattr(param.type, "choices", None)
49
+ if choices:
50
+ line = f"`{' '.join(param.opts)} [{'|'.join(str(choice) for choice in choices)}]`"
51
+ elif not getattr(param, "is_flag", False):
52
+ line += " VALOR"
53
+ marks = [mark for mark, on in (("obligatorio", param.required), ("se repite", getattr(param, "multiple", False))) if on]
54
+ if marks:
55
+ line += f" ({', '.join(marks)})"
56
+ help_text = (getattr(param, "help", None) or "").strip()
57
+ return f"{line}: {help_text}" if help_text else line