Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -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"
Expand Down
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -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.

<p align="center">
Expand Down Expand Up @@ -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`)
Expand Down
10 changes: 5 additions & 5 deletions src/cli/skill.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,17 @@ 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",
default_value = "osodevops/keito-skill",
env = "KEITO_SKILL_SOURCE"
)]
source: String,
Expand All @@ -39,7 +39,7 @@ per-repository setup after installation: cd into a client repo and run
#[arg(long, value_enum)]
agent: Vec<SkillAgent>,

/// 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,
},
Expand Down
11 changes: 7 additions & 4 deletions src/commands/skill.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -58,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
}

Expand Down Expand Up @@ -141,10 +142,12 @@ fn default_agents() -> Vec<SkillAgent> {
}

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",
Expand All @@ -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()
)));
}
Expand Down
2 changes: 1 addition & 1 deletion tests/cli_integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand Down
Loading