raillog-cli 0.1.0__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.
@@ -0,0 +1,87 @@
1
+ Metadata-Version: 2.4
2
+ Name: raillog-cli
3
+ Version: 0.1.0
4
+ Summary: CLI for Raillog V2.0 — railway construction logistics planning
5
+ Author-email: Boschetti Engineering <info@boschetti-engineering.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/boschetti-engineering/raillog
8
+ Project-URL: Bug Tracker, https://github.com/boschetti-engineering/raillog/issues
9
+ Keywords: railway,logistics,planning,cli,construction
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Environment :: Console
12
+ Classifier: Intended Audience :: End Users/Desktop
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: 3.13
17
+ Classifier: Topic :: Utilities
18
+ Requires-Python: >=3.11
19
+ Description-Content-Type: text/markdown
20
+ Requires-Dist: click>=8.1
21
+ Requires-Dist: httpx>=0.27
22
+ Requires-Dist: supabase>=2.7
23
+ Requires-Dist: rich>=13.7
24
+ Requires-Dist: python-dateutil>=2.9
25
+
26
+ # raillog-cli
27
+
28
+ Command-line interface for **Raillog V2.0** — a spatiotemporal logistics planning system for railway construction sites.
29
+
30
+ Manages waggons, Bauzüge (construction train groups), stations, tracks, and Fahrten (trips) within a time-bounded project. The core question the system answers: *"Where is waggon X at time T, and on which track?"*
31
+
32
+ ## Install
33
+
34
+ ```bash
35
+ pip install raillog-cli
36
+ ```
37
+
38
+ Requires Python 3.11+. Connects to a Supabase backend — you need a Raillog project URL and credentials.
39
+
40
+ ## Quick start
41
+
42
+ ```bash
43
+ raillog auth login
44
+ raillog project list
45
+ raillog project select <n>
46
+ raillog context
47
+ ```
48
+
49
+ ## Agent integration (Claude Code, Cursor, Codex, Gemini, opencode)
50
+
51
+ After install, run once in your project directory:
52
+
53
+ ```bash
54
+ raillog install-skill
55
+ ```
56
+
57
+ This writes:
58
+ - `~/.claude/skills/raillog.md` — Claude Code skill (auto-loaded)
59
+ - `~/.claude/CLAUDE.md` — trigger phrase added
60
+ - `./AGENTS.md` — skill file for Cursor, Codex, Gemini CLI, opencode
61
+
62
+ For Cursor specifically, copy `AGENTS.md` to `.cursor/rules/raillog.mdc`.
63
+
64
+ ## Commands
65
+
66
+ ```
67
+ raillog auth login, status, refresh, logout
68
+ raillog project list, select, show, create
69
+ raillog station list, show, create, update, delete, impact
70
+ raillog track list, show, create, update, delete, impact, occupation
71
+ raillog waggon list, show, create, update, delete, impact, types,
72
+ position, history, set-zustand, zustand
73
+ raillog bauzug list, show, create, update, compose, delete, impact,
74
+ check-departure, history
75
+ raillog travel list, show, create, update, delete, impact, validate
76
+ raillog restriction list, show, create, delete
77
+ raillog query suggest-track, track-occupation, track-capacity,
78
+ waggon-availability, conflicts
79
+ raillog install-skill
80
+ ```
81
+
82
+ All write commands support `--dry-run` and `--yes`.
83
+ All list/query commands support `--json` for agent consumption.
84
+
85
+ ## License
86
+
87
+ MIT
@@ -0,0 +1,62 @@
1
+ # raillog-cli
2
+
3
+ Command-line interface for **Raillog V2.0** — a spatiotemporal logistics planning system for railway construction sites.
4
+
5
+ Manages waggons, Bauzüge (construction train groups), stations, tracks, and Fahrten (trips) within a time-bounded project. The core question the system answers: *"Where is waggon X at time T, and on which track?"*
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ pip install raillog-cli
11
+ ```
12
+
13
+ Requires Python 3.11+. Connects to a Supabase backend — you need a Raillog project URL and credentials.
14
+
15
+ ## Quick start
16
+
17
+ ```bash
18
+ raillog auth login
19
+ raillog project list
20
+ raillog project select <n>
21
+ raillog context
22
+ ```
23
+
24
+ ## Agent integration (Claude Code, Cursor, Codex, Gemini, opencode)
25
+
26
+ After install, run once in your project directory:
27
+
28
+ ```bash
29
+ raillog install-skill
30
+ ```
31
+
32
+ This writes:
33
+ - `~/.claude/skills/raillog.md` — Claude Code skill (auto-loaded)
34
+ - `~/.claude/CLAUDE.md` — trigger phrase added
35
+ - `./AGENTS.md` — skill file for Cursor, Codex, Gemini CLI, opencode
36
+
37
+ For Cursor specifically, copy `AGENTS.md` to `.cursor/rules/raillog.mdc`.
38
+
39
+ ## Commands
40
+
41
+ ```
42
+ raillog auth login, status, refresh, logout
43
+ raillog project list, select, show, create
44
+ raillog station list, show, create, update, delete, impact
45
+ raillog track list, show, create, update, delete, impact, occupation
46
+ raillog waggon list, show, create, update, delete, impact, types,
47
+ position, history, set-zustand, zustand
48
+ raillog bauzug list, show, create, update, compose, delete, impact,
49
+ check-departure, history
50
+ raillog travel list, show, create, update, delete, impact, validate
51
+ raillog restriction list, show, create, delete
52
+ raillog query suggest-track, track-occupation, track-capacity,
53
+ waggon-availability, conflicts
54
+ raillog install-skill
55
+ ```
56
+
57
+ All write commands support `--dry-run` and `--yes`.
58
+ All list/query commands support `--json` for agent consumption.
59
+
60
+ ## License
61
+
62
+ MIT
@@ -0,0 +1,46 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "raillog-cli"
7
+ version = "0.1.0"
8
+ description = "CLI for Raillog V2.0 — railway construction logistics planning"
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ authors = [
12
+ { name = "Boschetti Engineering", email = "info@boschetti-engineering.com" }
13
+ ]
14
+ keywords = ["railway", "logistics", "planning", "cli", "construction"]
15
+ classifiers = [
16
+ "Development Status :: 4 - Beta",
17
+ "Environment :: Console",
18
+ "Intended Audience :: End Users/Desktop",
19
+ "Programming Language :: Python :: 3",
20
+ "Programming Language :: Python :: 3.11",
21
+ "Programming Language :: Python :: 3.12",
22
+ "Programming Language :: Python :: 3.13",
23
+ "Topic :: Utilities",
24
+ ]
25
+ requires-python = ">=3.11"
26
+ dependencies = [
27
+ "click>=8.1",
28
+ "httpx>=0.27",
29
+ "supabase>=2.7",
30
+ "rich>=13.7",
31
+ "python-dateutil>=2.9",
32
+ ]
33
+
34
+ [project.urls]
35
+ Homepage = "https://github.com/boschetti-engineering/raillog"
36
+ "Bug Tracker" = "https://github.com/boschetti-engineering/raillog/issues"
37
+
38
+ [project.scripts]
39
+ raillog = "raillog.cli:cli"
40
+
41
+ [tool.setuptools.packages.find]
42
+ where = ["."]
43
+ include = ["raillog*"]
44
+
45
+ [tool.setuptools.package-data]
46
+ raillog = ["data/AGENTS.md"]
@@ -0,0 +1 @@
1
+ __version__ = "0.1.0"
@@ -0,0 +1,54 @@
1
+ """
2
+ raillog — main CLI entry point.
3
+
4
+ Registers all command groups. This is the `raillog` command installed by pip.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import click
10
+ from rich.console import Console
11
+
12
+ from raillog import __version__
13
+ from raillog.cmd_auth import auth_group
14
+ from raillog.cmd_projects import project_group
15
+ from raillog.cmd_context import context_cmd
16
+ from raillog.cmd_stations import station_group
17
+ from raillog.cmd_tracks import track_group
18
+ from raillog.cmd_bauzuege import bauzug_group
19
+ from raillog.cmd_waggons import waggon_group
20
+ from raillog.cmd_travels import travel_group
21
+ from raillog.cmd_restrictions import restriction_group
22
+ from raillog.cmd_queries import query_group
23
+ from raillog.cmd_install import install_skill
24
+
25
+ console = Console()
26
+
27
+
28
+ @click.group()
29
+ @click.version_option(__version__, prog_name="raillog")
30
+ def cli() -> None:
31
+ """
32
+ Raillog V2.0 — railway construction logistics CLI.
33
+
34
+ \b
35
+ Quick start:
36
+ raillog auth login
37
+ raillog project list
38
+ raillog project select <n>
39
+ raillog context
40
+ """
41
+
42
+
43
+ # ── Register all command groups ───────────────────────────────────────────────
44
+ cli.add_command(auth_group)
45
+ cli.add_command(project_group)
46
+ cli.add_command(context_cmd)
47
+ cli.add_command(station_group)
48
+ cli.add_command(track_group)
49
+ cli.add_command(bauzug_group)
50
+ cli.add_command(waggon_group)
51
+ cli.add_command(travel_group)
52
+ cli.add_command(restriction_group)
53
+ cli.add_command(query_group)
54
+ cli.add_command(install_skill)
@@ -0,0 +1,36 @@
1
+ """
2
+ Supabase client factory.
3
+
4
+ Builds a supabase-py client and injects the stored JWT so every
5
+ request is authenticated as the logged-in user (respecting RLS).
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ from supabase import Client, create_client
11
+
12
+ SUPABASE_URL = "https://ouilcwrgxsirpvkzsdkq.supabase.co"
13
+ SUPABASE_ANON_KEY = (
14
+ "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9"
15
+ ".eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6Im91aWxjd3JneHNpcnB2a3pzZGtxIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NjU4MzMzNzYsImV4cCI6MjA4MTQwOTM3Nn0"
16
+ ".WRR4puUXDvS46w7rsc1sHT6cz8_A1pL-1yzK47v7aqI"
17
+ )
18
+
19
+
20
+ def get_client(access_token: str | None = None) -> Client:
21
+ """
22
+ Return a Supabase client.
23
+ If access_token is provided, set it on the client so RLS applies.
24
+ """
25
+ sb = create_client(SUPABASE_URL, SUPABASE_ANON_KEY)
26
+ if access_token:
27
+ # Inject user JWT — required for RLS to work correctly
28
+ sb.postgrest.auth(access_token)
29
+ return sb
30
+
31
+
32
+ def authed_client() -> Client:
33
+ """Shortcut: load session and return authenticated client."""
34
+ from raillog import session as sess
35
+ s = sess.require_auth()
36
+ return get_client(s["access_token"])
@@ -0,0 +1,92 @@
1
+ """raillog auth {login,status,logout}"""
2
+
3
+ from __future__ import annotations
4
+
5
+ import time
6
+
7
+ import click
8
+ from rich.console import Console
9
+
10
+ from raillog import session as sess
11
+ from raillog.client import get_client, SUPABASE_URL
12
+
13
+ console = Console()
14
+
15
+
16
+ @click.group("auth")
17
+ def auth_group() -> None:
18
+ """Authenticate with Raillog (Supabase)."""
19
+
20
+
21
+ @auth_group.command("login")
22
+ def auth_login() -> None:
23
+ """Log in with email and password."""
24
+ console.print("[bold]Raillog Login[/bold]")
25
+ email = click.prompt("Email")
26
+ password = click.prompt("Password", hide_input=True)
27
+
28
+ sb = get_client()
29
+ try:
30
+ result = sb.auth.sign_in_with_password({"email": email, "password": password})
31
+ except Exception as e:
32
+ raise SystemExit(f"Login failed: {e}") from e
33
+
34
+ if not result.session:
35
+ raise SystemExit("Login failed: no session returned.")
36
+
37
+ s = result.session
38
+ user = result.user
39
+
40
+ sess.save({
41
+ "access_token": s.access_token,
42
+ "refresh_token": s.refresh_token,
43
+ "expires_at": s.expires_at or int(time.time()) + 3600,
44
+ "user_id": str(user.id) if user else "",
45
+ "user_email": user.email or email,
46
+ "project_id": None,
47
+ "project_name": None,
48
+ "access_level": None,
49
+ })
50
+
51
+ console.print(f"[green]Logged in as[/green] [bold]{user.email}[/bold]")
52
+ console.print("Run [cyan]raillog project list[/cyan] to select a project.")
53
+
54
+
55
+ @auth_group.command("status")
56
+ def auth_status() -> None:
57
+ """Show current authentication status."""
58
+ s = sess.load()
59
+ if not s:
60
+ console.print("[red]Not authenticated.[/red] Run: raillog auth login")
61
+ return
62
+
63
+ if not sess.is_valid(s):
64
+ console.print("[yellow]Session expired.[/yellow] Run: raillog auth login")
65
+ return
66
+
67
+ remaining = s.get("expires_at", 0) - int(time.time())
68
+ hours = remaining // 3600
69
+ console.print(f"[green]Authenticated[/green] as [bold]{s.get('user_email')}[/bold]")
70
+ console.print(f"Session expires in ~{hours}h")
71
+ if s.get("project_id"):
72
+ console.print(f"Active project: [bold]{s.get('project_name')}[/bold] ({s.get('project_id')})")
73
+ else:
74
+ console.print("[dim]No project selected.[/dim]")
75
+
76
+
77
+ @auth_group.command("refresh")
78
+ def auth_refresh() -> None:
79
+ """Silently renew the session using the stored refresh token."""
80
+ if sess._try_refresh():
81
+ s = sess.load()
82
+ remaining = ((s or {}).get("expires_at", 0) - int(time.time())) // 3600
83
+ console.print(f"[green]Session refreshed.[/green] Expires in ~{remaining}h")
84
+ else:
85
+ raise SystemExit("Refresh failed — run: raillog auth login")
86
+
87
+
88
+ @auth_group.command("logout")
89
+ def auth_logout() -> None:
90
+ """Clear the local session."""
91
+ sess.clear()
92
+ console.print("[green]Logged out.[/green]")