From a8011e42a1ef39db909698db1f62be709790381d Mon Sep 17 00:00:00 2001 From: Waiming Yuen Date: Thu, 11 Jun 2026 12:01:45 -0700 Subject: [PATCH 1/4] Add rtk --- .github/copilot-instructions.md | 28 ++++++++++++++++++++++++++++ .github/hooks/rtk-rewrite.json | 12 ++++++++++++ .rtk/filters.toml | 13 +++++++++++++ 3 files changed, 53 insertions(+) create mode 100644 .github/hooks/rtk-rewrite.json create mode 100644 .rtk/filters.toml diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 5ed64e51..2e5c1de1 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -68,3 +68,31 @@ Do not deviate from this structure when editing or adding chapter content. | Devcontainer updated | `.devcontainer/devcontainer.json`, Chapter 00 (setup instructions) | | Image or banner changed | `assets/` directory, any README referencing the image | | Copilot CLI version requirements change | Chapter 00, Chapter 01, `.devcontainer/devcontainer.json` | + + +# RTK — Token-Optimized CLI + +**rtk** is a CLI proxy that filters and compresses command outputs, saving 60-90% tokens. + +## Rule + +Always prefix shell commands with `rtk`: + +```bash +# Instead of: Use: +git status rtk git status +git log -10 rtk git log -10 +cargo test rtk cargo test +docker ps rtk docker ps +kubectl get pods rtk kubectl pods +``` + +## Meta commands (use directly) + +```bash +rtk gain # Token savings dashboard +rtk gain --history # Per-command savings history +rtk discover # Find missed rtk opportunities +rtk proxy # Run raw (no filtering) but track usage +``` + \ No newline at end of file diff --git a/.github/hooks/rtk-rewrite.json b/.github/hooks/rtk-rewrite.json new file mode 100644 index 00000000..eb2a5a7f --- /dev/null +++ b/.github/hooks/rtk-rewrite.json @@ -0,0 +1,12 @@ +{ + "hooks": { + "PreToolUse": [ + { + "type": "command", + "command": "rtk hook copilot", + "cwd": ".", + "timeout": 5 + } + ] + } +} diff --git a/.rtk/filters.toml b/.rtk/filters.toml new file mode 100644 index 00000000..d9bd43fe --- /dev/null +++ b/.rtk/filters.toml @@ -0,0 +1,13 @@ +# Project-local RTK filters — commit this file with your repo. +# Filters here override user-global and built-in filters. +# Docs: https://github.com/rtk-ai/rtk#custom-filters +schema_version = 1 + +# Example: suppress build noise from a custom tool +# [filters.my-tool] +# description = "Compact my-tool output" +# match_command = "^my-tool\\s+build" +# strip_ansi = true +# strip_lines_matching = ["^\\s*$", "^Downloading", "^Installing"] +# max_lines = 30 +# on_empty = "my-tool: ok" From bc526dbc63e550f57433a8cccb7f546772f7543c Mon Sep 17 00:00:00 2001 From: Waiming Yuen Date: Thu, 11 Jun 2026 13:39:44 -0700 Subject: [PATCH 2/4] fix(utils): improve user input validation for menu choice and book details --- samples/book-app-project/utils.py | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/samples/book-app-project/utils.py b/samples/book-app-project/utils.py index 4151dcda..e94549db 100644 --- a/samples/book-app-project/utils.py +++ b/samples/book-app-project/utils.py @@ -8,11 +8,34 @@ def print_menu(): def get_user_choice() -> str: - return input("Choose an option (1-5): ").strip() + while True: + choice = input("Choose an option (1-5): ").strip() + if choice in {"1", "2", "3", "4", "5"}: + return choice + print("Invalid choice. Please enter a number between 1 and 5.") def get_book_details(): - title = input("Enter book title: ").strip() + """Prompt the user for book details and return them. + + Prompts (via standard input) for the following fields: + - title: required. The function will re-prompt until a non-empty title is provided. + - author: optional. An empty string is allowed. + - publication year: optional. The function attempts to convert input to int; if conversion + fails the year defaults to 0 and a message is printed. + + Returns: + tuple[str, str, int]: A 3-tuple of (title, author, year). + + Side effects: + - Prints prompts and validation messages to stdout. + """ + while True: + title = input("Enter book title: ").strip() + if title: + break + print("Title cannot be empty. Please enter a title.") + author = input("Enter author: ").strip() year_input = input("Enter publication year: ").strip() From 12c85e809ce76c114bb0b1feb3b90640ba01d4bf Mon Sep 17 00:00:00 2001 From: Waiming Yuen Date: Thu, 11 Jun 2026 13:41:15 -0700 Subject: [PATCH 3/4] WIP: add BookCollection.list_by_year(start, end) and tests Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> From 5015a0f9615784b983db57d8ddb879583b79a082 Mon Sep 17 00:00:00 2001 From: Waiming Yuen Date: Thu, 11 Jun 2026 14:10:38 -0700 Subject: [PATCH 4/4] lesson 2 --- samples/book-app-project/book_app.py | 16 +--------------- samples/book-app-project/utils.py | 13 ++++++++----- 2 files changed, 9 insertions(+), 20 deletions(-) diff --git a/samples/book-app-project/book_app.py b/samples/book-app-project/book_app.py index f0100c2d..2da3733e 100644 --- a/samples/book-app-project/book_app.py +++ b/samples/book-app-project/book_app.py @@ -1,26 +1,12 @@ import sys from books import BookCollection +from utils import show_books # Global collection instance collection = BookCollection() -def show_books(books): - """Display books in a user-friendly format.""" - if not books: - print("No books found.") - return - - print("\nYour Book Collection:\n") - - for index, book in enumerate(books, start=1): - status = "✓" if book.read else " " - print(f"{index}. [{status}] {book.title} by {book.author} ({book.year})") - - print() - - def handle_list(): books = collection.list_books() show_books(books) diff --git a/samples/book-app-project/utils.py b/samples/book-app-project/utils.py index e94549db..ae8d0ae6 100644 --- a/samples/book-app-project/utils.py +++ b/samples/book-app-project/utils.py @@ -48,12 +48,15 @@ def get_book_details(): return title, author, year -def print_books(books): +def show_books(books): if not books: - print("No books in your collection.") + print("No books found.") return - print("\nYour Books:") + print("\nYour Book Collection:\n") + for index, book in enumerate(books, start=1): - status = "✅ Read" if book.read else "📖 Unread" - print(f"{index}. {book.title} by {book.author} ({book.year}) - {status}") + status = "✓" if book.read else " " + print(f"{index}. [{status}] {book.title} by {book.author} ({book.year})") + + print()