From b9384156afa6d4f342056fc71f95511d9f455979 Mon Sep 17 00:00:00 2001 From: Sion Smith Date: Tue, 12 May 2026 14:05:27 +0100 Subject: [PATCH 1/3] Pin skills installer package --- README.md | 13 +++++++++++++ src/cli/skill.rs | 8 ++++---- src/commands/skill.rs | 9 ++++++--- tests/cli_integration.rs | 2 +- 4 files changed, 24 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index a18b3d0..5bcb8b8 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # keito +[![CI](https://github.com/osodevops/keito-cli/actions/workflows/test.yml/badge.svg)](https://github.com/osodevops/keito-cli/actions/workflows/test.yml) + Track billable time against the [Keito](https://keito.ai) platform — from the terminal or from an AI agent.

@@ -87,6 +89,17 @@ keito time stop --json Exit codes tell you exactly what happened — no need to parse error messages. See [Exit Codes](#exit-codes) below. +## Agent Skill + +The Keito Agent Skill is installed from the GitHub skill repo, not from an npm package: + +```sh +keito auth login +keito skill install +``` + +`keito skill install` uses `npx` only to run the open skills installer. The installer package is pinned to `skills@1.5.6` by default and can be overridden intentionally with `KEITO_SKILLS_PACKAGE`. + ## Features - **Dual output** — human-readable tables (TTY) or JSON (piped / `--json`) diff --git a/src/cli/skill.rs b/src/cli/skill.rs index f51c7ce..ae08dc9 100644 --- a/src/cli/skill.rs +++ b/src/cli/skill.rs @@ -20,14 +20,14 @@ pub struct SkillCommand { pub enum SkillSubcommand { /// Install the Keito Skill and configure supported agent hooks #[command(long_about = "\ -Install the Keito Skill via the open skills CLI, then run the installed hook -installer for each selected agent. +Install the Keito Skill with the pinned open skills installer package, then run +the installed hook installer for each selected agent. By default this configures both Codex and Claude Code. The skill still needs per-repository setup after installation: cd into a client repo and run /track-time-keito to select its Keito client, project, and task.")] Install { - /// Skill source for npx skills add + /// Skill source for the skills installer #[arg( long, default_value = "keito-ai/keito-skill", @@ -39,7 +39,7 @@ per-repository setup after installation: cd into a client repo and run #[arg(long, value_enum)] agent: Vec, - /// Skip running npx skills add and only run hook installers if present + /// Skip the skills installer and only run hook installers if present #[arg(long)] skip_skills_add: bool, }, diff --git a/src/commands/skill.rs b/src/commands/skill.rs index d5900fa..2cb081c 100644 --- a/src/commands/skill.rs +++ b/src/commands/skill.rs @@ -10,6 +10,7 @@ use crate::error::AppError; use crate::output::OutputMode; const SKILL_NAME: &str = "keito-time-track"; +const DEFAULT_SKILLS_PACKAGE: &str = "skills@1.5.6"; #[derive(Debug, Serialize)] struct SkillStatus { @@ -141,10 +142,12 @@ fn default_agents() -> Vec { } fn run_skills_add(source: &str, agent: SkillAgent, show_output: bool) -> Result<(), AppError> { + let skills_package = + std::env::var("KEITO_SKILLS_PACKAGE").unwrap_or_else(|_| DEFAULT_SKILLS_PACKAGE.into()); let status = ProcessCommand::new("npx") .args([ "--yes", - "skills@latest", + &skills_package, "add", source, "-g", @@ -159,11 +162,11 @@ fn run_skills_add(source: &str, agent: SkillAgent, show_output: bool) -> Result< .stdout(child_stdio(show_output)) .stderr(child_stdio(show_output)) .status() - .map_err(|e| AppError::Config(format!("Failed to run npx skills: {e}")))?; + .map_err(|e| AppError::Config(format!("Failed to run the skills installer: {e}")))?; if !status.success() { return Err(AppError::Config(format!( - "npx skills add failed for {}", + "Skills installer failed for {}", agent.display_name() ))); } diff --git a/tests/cli_integration.rs b/tests/cli_integration.rs index 71eac84..c0a6fc4 100644 --- a/tests/cli_integration.rs +++ b/tests/cli_integration.rs @@ -287,7 +287,7 @@ fn skill_install_configures_agent_hooks_with_fake_skills_cli() { assert!(!output_text.contains("fake claude installer output")); let log = fs::read_to_string(npx_log).unwrap(); - assert!(log.contains("skills@latest add /tmp/keito-skill")); + assert!(log.contains("skills@1.5.6 add /tmp/keito-skill")); assert!(log.contains("-a codex")); assert!(log.contains("-a claude-code")); assert!(temp_dir.path().join(".codex/hooks.json").exists()); From 54528d5cd62b7ddf3bc266cacdba1048512fc387 Mon Sep 17 00:00:00 2001 From: Sion Smith Date: Tue, 12 May 2026 14:17:28 +0100 Subject: [PATCH 2/3] Bump version for installer pinning --- CHANGELOG.md | 7 +++++++ Cargo.lock | 2 +- Cargo.toml | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 363b00f..03ad87d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/), and this project adheres to [Semantic Versioning](https://semver.org/). +## [0.1.6] - 2026-05-12 + +### Changed + +- Pin the Agent Skill installer package to `skills@1.5.6` instead of resolving a floating installer tag. +- Clarify CLI help and README wording so the skill remains GitHub-sourced and npm is only used for the pinned installer hop. + ## [0.1.5] - 2026-05-12 ### Added diff --git a/Cargo.lock b/Cargo.lock index 11c9b3e..e741ec0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -872,7 +872,7 @@ dependencies = [ [[package]] name = "keito-cli" -version = "0.1.5" +version = "0.1.6" dependencies = [ "assert_cmd", "chrono", diff --git a/Cargo.toml b/Cargo.toml index 9ca8d1a..d1618f5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "keito-cli" -version = "0.1.5" +version = "0.1.6" edition = "2021" description = "CLI for AI agents and humans to track billable time against the Keito platform" license = "MIT" From d8f65573f4780c558b1fbd2b030d8cad4f1a6794 Mon Sep 17 00:00:00 2001 From: Sion Smith Date: Tue, 12 May 2026 14:44:00 +0100 Subject: [PATCH 3/3] Use public skill repository source --- src/cli/skill.rs | 2 +- src/commands/skill.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cli/skill.rs b/src/cli/skill.rs index ae08dc9..cc36116 100644 --- a/src/cli/skill.rs +++ b/src/cli/skill.rs @@ -30,7 +30,7 @@ per-repository setup after installation: cd into a client repo and run /// Skill source for the skills installer #[arg( long, - default_value = "keito-ai/keito-skill", + default_value = "osodevops/keito-skill", env = "KEITO_SKILL_SOURCE" )] source: String, diff --git a/src/commands/skill.rs b/src/commands/skill.rs index 2cb081c..741d2bc 100644 --- a/src/commands/skill.rs +++ b/src/commands/skill.rs @@ -59,7 +59,7 @@ pub async fn run( pub async fn install_defaults(global: &GlobalFlags, mode: OutputMode) -> Result<(), AppError> { let source = - std::env::var("KEITO_SKILL_SOURCE").unwrap_or_else(|_| "keito-ai/keito-skill".into()); + std::env::var("KEITO_SKILL_SOURCE").unwrap_or_else(|_| "osodevops/keito-skill".into()); install(global, mode, &source, default_agents(), false).await }