Skip to content

Commit a431179

Browse files
authored
Merge pull request #15 from osodevops/codex/skill-cli-onboarding
Add Keito skill onboarding commands
2 parents a4848db + aceeaf1 commit a431179

10 files changed

Lines changed: 625 additions & 3 deletions

File tree

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,14 @@ 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.5] - 2026-05-12
9+
10+
### Added
11+
12+
- `keito skill install`, `keito skill status`, and `keito skill doctor` commands for installing and verifying the Keito Agent Skill.
13+
- Optional interactive Agent Skill install prompt after `keito auth login`.
14+
- JSON-safe skill installer execution so child installer output does not contaminate `--json` responses.
15+
816
## [0.1.4] - 2026-05-12
917

1018
### 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.4"
3+
version = "0.1.5"
44
edition = "2021"
55
description = "CLI for AI agents and humans to track billable time against the Keito platform"
66
license = "MIT"

src/cli/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
pub mod auth;
22
pub mod clients;
33
pub mod projects;
4+
pub mod skill;
45
pub mod time;
56

67
use clap::{Parser, Subcommand};
@@ -104,4 +105,6 @@ pub enum Command {
104105
Time(time::TimeCommand),
105106
/// Browse projects and tasks
106107
Projects(projects::ProjectsCommand),
108+
/// Install and verify the Keito agent skill
109+
Skill(skill::SkillCommand),
107110
}

src/cli/skill.rs

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
use clap::{Args, Subcommand, ValueEnum};
2+
3+
#[derive(Args)]
4+
#[command(after_long_help = "\
5+
The Keito Skill is the agent UX layer on top of the Keito CLI. The skill
6+
uses the CLI for authentication and API writes, then installs Claude Code /
7+
Codex lifecycle hooks so local coding sessions can be logged automatically.
8+
9+
EXAMPLES:
10+
keito skill install
11+
keito skill install --agent codex
12+
keito skill status --json
13+
keito skill doctor")]
14+
pub struct SkillCommand {
15+
#[command(subcommand)]
16+
pub command: SkillSubcommand,
17+
}
18+
19+
#[derive(Subcommand)]
20+
pub enum SkillSubcommand {
21+
/// Install the Keito Skill and configure supported agent hooks
22+
#[command(long_about = "\
23+
Install the Keito Skill via the open skills CLI, then run the installed hook
24+
installer for each selected agent.
25+
26+
By default this configures both Codex and Claude Code. The skill still needs
27+
per-repository setup after installation: cd into a client repo and run
28+
/track-time-keito to select its Keito client, project, and task.")]
29+
Install {
30+
/// Skill source for npx skills add
31+
#[arg(
32+
long,
33+
default_value = "keito-ai/keito-skill",
34+
env = "KEITO_SKILL_SOURCE"
35+
)]
36+
source: String,
37+
38+
/// Agent hook target to configure
39+
#[arg(long, value_enum)]
40+
agent: Vec<SkillAgent>,
41+
42+
/// Skip running npx skills add and only run hook installers if present
43+
#[arg(long)]
44+
skip_skills_add: bool,
45+
},
46+
47+
/// Show install/auth/hook status for the Keito Skill
48+
Status,
49+
50+
/// Run readiness checks and print next actions
51+
Doctor,
52+
}
53+
54+
#[derive(Debug, Clone, Copy, ValueEnum, PartialEq, Eq)]
55+
pub enum SkillAgent {
56+
Codex,
57+
ClaudeCode,
58+
}
59+
60+
impl SkillAgent {
61+
pub fn skills_cli_name(self) -> &'static str {
62+
match self {
63+
SkillAgent::Codex => "codex",
64+
SkillAgent::ClaudeCode => "claude-code",
65+
}
66+
}
67+
68+
pub fn display_name(self) -> &'static str {
69+
match self {
70+
SkillAgent::Codex => "Codex",
71+
SkillAgent::ClaudeCode => "Claude Code",
72+
}
73+
}
74+
}

src/commands/auth.rs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
use colored::Colorize;
2-
use dialoguer::{Input, Password};
2+
use dialoguer::{Confirm, Input, Password};
3+
use std::io::IsTerminal;
34

45
use crate::api::KeitorClient;
56
use crate::cli::auth::{AuthCommand, AuthSubcommand};
67
use crate::cli::GlobalFlags;
8+
use crate::commands::skill;
79
use crate::config::{AppConfig, ResolvedAuth};
810
use crate::error::AppError;
911
use crate::output::{self, OutputMode};
@@ -71,6 +73,27 @@ async fn login(global: &GlobalFlags, mode: OutputMode) -> Result<(), AppError> {
7173
"Credentials saved to {}.",
7274
AppConfig::config_path()?.display()
7375
);
76+
maybe_offer_skill_install(global, mode).await?;
77+
}
78+
79+
Ok(())
80+
}
81+
82+
async fn maybe_offer_skill_install(global: &GlobalFlags, mode: OutputMode) -> Result<(), AppError> {
83+
if mode != OutputMode::Table || global.quiet || !std::io::stdin().is_terminal() {
84+
return Ok(());
85+
}
86+
87+
let install = Confirm::new()
88+
.with_prompt("Install the Keito agent skill for Claude Code / Codex?")
89+
.default(true)
90+
.interact()
91+
.map_err(|e| AppError::Config(format!("Input error: {e}")))?;
92+
93+
if install {
94+
skill::install_defaults(global, mode).await?;
95+
} else {
96+
println!("You can install it later with: keito skill install");
7497
}
7598

7699
Ok(())

src/commands/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
pub mod auth;
22
pub mod clients;
33
pub mod projects;
4+
pub mod skill;
45
pub mod time;

0 commit comments

Comments
 (0)