Skip to content

Commit e16f03d

Browse files
authored
Merge pull request #16 from osodevops/codex/skill-installer-security
Pin Keito skill installer package
2 parents 5ae19ea + d8f6557 commit e16f03d

7 files changed

Lines changed: 35 additions & 12 deletions

File tree

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/),
66
and this project adheres to [Semantic Versioning](https://semver.org/).
77

8+
## [0.1.6] - 2026-05-12
9+
10+
### Changed
11+
12+
- Pin the Agent Skill installer package to `skills@1.5.6` instead of resolving a floating installer tag.
13+
- Clarify CLI help and README wording so the skill remains GitHub-sourced and npm is only used for the pinned installer hop.
14+
815
## [0.1.5] - 2026-05-12
916

1017
### Added

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "keito-cli"
3-
version = "0.1.5"
3+
version = "0.1.6"
44
edition = "2021"
55
description = "CLI for AI agents and humans to track billable time against the Keito platform"
66
license = "MIT"

README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# keito
22

3+
[![CI](https://github.com/osodevops/keito-cli/actions/workflows/test.yml/badge.svg)](https://github.com/osodevops/keito-cli/actions/workflows/test.yml)
4+
35
Track billable time against the [Keito](https://keito.ai) platform — from the terminal or from an AI agent.
46

57
<p align="center">
@@ -87,6 +89,17 @@ keito time stop --json
8789

8890
Exit codes tell you exactly what happened — no need to parse error messages. See [Exit Codes](#exit-codes) below.
8991

92+
## Agent Skill
93+
94+
The Keito Agent Skill is installed from the GitHub skill repo, not from an npm package:
95+
96+
```sh
97+
keito auth login
98+
keito skill install
99+
```
100+
101+
`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`.
102+
90103
## Features
91104

92105
- **Dual output** — human-readable tables (TTY) or JSON (piped / `--json`)

src/cli/skill.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,17 @@ pub struct SkillCommand {
2020
pub enum SkillSubcommand {
2121
/// Install the Keito Skill and configure supported agent hooks
2222
#[command(long_about = "\
23-
Install the Keito Skill via the open skills CLI, then run the installed hook
24-
installer for each selected agent.
23+
Install the Keito Skill with the pinned open skills installer package, then run
24+
the installed hook installer for each selected agent.
2525
2626
By default this configures both Codex and Claude Code. The skill still needs
2727
per-repository setup after installation: cd into a client repo and run
2828
/track-time-keito to select its Keito client, project, and task.")]
2929
Install {
30-
/// Skill source for npx skills add
30+
/// Skill source for the skills installer
3131
#[arg(
3232
long,
33-
default_value = "keito-ai/keito-skill",
33+
default_value = "osodevops/keito-skill",
3434
env = "KEITO_SKILL_SOURCE"
3535
)]
3636
source: String,
@@ -39,7 +39,7 @@ per-repository setup after installation: cd into a client repo and run
3939
#[arg(long, value_enum)]
4040
agent: Vec<SkillAgent>,
4141

42-
/// Skip running npx skills add and only run hook installers if present
42+
/// Skip the skills installer and only run hook installers if present
4343
#[arg(long)]
4444
skip_skills_add: bool,
4545
},

src/commands/skill.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use crate::error::AppError;
1010
use crate::output::OutputMode;
1111

1212
const SKILL_NAME: &str = "keito-time-track";
13+
const DEFAULT_SKILLS_PACKAGE: &str = "skills@1.5.6";
1314

1415
#[derive(Debug, Serialize)]
1516
struct SkillStatus {
@@ -58,7 +59,7 @@ pub async fn run(
5859

5960
pub async fn install_defaults(global: &GlobalFlags, mode: OutputMode) -> Result<(), AppError> {
6061
let source =
61-
std::env::var("KEITO_SKILL_SOURCE").unwrap_or_else(|_| "keito-ai/keito-skill".into());
62+
std::env::var("KEITO_SKILL_SOURCE").unwrap_or_else(|_| "osodevops/keito-skill".into());
6263
install(global, mode, &source, default_agents(), false).await
6364
}
6465

@@ -141,10 +142,12 @@ fn default_agents() -> Vec<SkillAgent> {
141142
}
142143

143144
fn run_skills_add(source: &str, agent: SkillAgent, show_output: bool) -> Result<(), AppError> {
145+
let skills_package =
146+
std::env::var("KEITO_SKILLS_PACKAGE").unwrap_or_else(|_| DEFAULT_SKILLS_PACKAGE.into());
144147
let status = ProcessCommand::new("npx")
145148
.args([
146149
"--yes",
147-
"skills@latest",
150+
&skills_package,
148151
"add",
149152
source,
150153
"-g",
@@ -159,11 +162,11 @@ fn run_skills_add(source: &str, agent: SkillAgent, show_output: bool) -> Result<
159162
.stdout(child_stdio(show_output))
160163
.stderr(child_stdio(show_output))
161164
.status()
162-
.map_err(|e| AppError::Config(format!("Failed to run npx skills: {e}")))?;
165+
.map_err(|e| AppError::Config(format!("Failed to run the skills installer: {e}")))?;
163166

164167
if !status.success() {
165168
return Err(AppError::Config(format!(
166-
"npx skills add failed for {}",
169+
"Skills installer failed for {}",
167170
agent.display_name()
168171
)));
169172
}

tests/cli_integration.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ fn skill_install_configures_agent_hooks_with_fake_skills_cli() {
287287
assert!(!output_text.contains("fake claude installer output"));
288288

289289
let log = fs::read_to_string(npx_log).unwrap();
290-
assert!(log.contains("skills@latest add /tmp/keito-skill"));
290+
assert!(log.contains("skills@1.5.6 add /tmp/keito-skill"));
291291
assert!(log.contains("-a codex"));
292292
assert!(log.contains("-a claude-code"));
293293
assert!(temp_dir.path().join(".codex/hooks.json").exists());

0 commit comments

Comments
 (0)