| name | tempo-report |
|---|---|
| description | Use when user asks for a Tempo time report, worklog summary, daily work report, or says "tempo report", "tempo:report", "отчёт tempo", "покажи что я делал", "что я залогировал". Works with Jira worklogs, Activity Streams, Git commits, changelog/comments, and local activity sources. |
| license | MIT |
| compatibility | Requires bash and python3 for bundled scripts. Optional richer reports use git, jq, curl, Jira tools when available, or Jira HTTP access via JIRA_URL and JIRA_PERSONAL_TOKEN. Tests require jq. |
| tags | jiratempoworklogreportingproductivity |
| owners | redickowii |
| metadata | {"author":"redickowii","version":"1.0"} |
Tempo Report
Build a Tempo worklog recommendation for one day or a short date range. Use Jira worklogs, Jira activity, comments, Git commits, and configured local activity folders. Keep sources separate: Worklog, Git, Changelog, Comments, Local.
Core rules:
- Report generation is read-only. Never add Jira/Tempo worklogs unless the user explicitly asks for writes.
- Dry-run or validation prompts must not perform real Jira writes, save reports, import configs, or mutate files.
- Never print secrets, token values, full env dumps, or local file contents.
- Never pad time to
minDailyHours; show shortfall honestly.
##Trigger
Use when the user asks for a Tempo report, worklog summary, daily time report, or asks what they did/logged. Examples: tempo за вчера, tempo report 2026-05-20, отчёт tempo, покажи что я делал.
Help triggers (?, help, --help, usage, помощь, как пользоваться) mean show usage only.
##Data Backends
- Required: bundled script
scripts/tempo-data.shinside the installed skill directory. - Jira data can come from any available backend: shell-provided Jira tools, MCP-backed Jira tools, Jira CLI, or Jira HTTP/API access. Do not require MCP.
- Optional shell tools for richer reports:
git,jq,curl. - Optional env for Jira HTTP/API and Activity Streams:
JIRA_PERSONAL_TOKEN,JIRA_URL. - Optional Jira tool names, when provided by the current shell:
jira_search,jira_get_issue,jira_get_worklog; optionaljira_add_worklogfor writing time.
Never print secret values.
##Config Resolution
Use shell-neutral config shared by OpenCode, Claude, Pi, Warm, and other shells:
global: ~/.config/tempo-report/config.json
project: ${PROJECT_ROOT}/.tempo-report.jsonProject config overrides global config. If any canonical config exists, use only canonical config and do not inspect legacy config.
If no canonical config exists, check known legacy configs only as import candidates:
Claude Code global: ~/.claude/tempo-report.json
Claude Code project: ${PROJECT_ROOT}/.claude/commands/tempo-report.json
OpenCode global: ~/.config/opencode/tempo-report.json
OpenCode project: ${PROJECT_ROOT}/.opencode/tempo-report.jsonLegacy configs are not fallback configs. Import requires user confirmation and target confirmation before writing. If no canonical or legacy config exists, default creation target is project config ${PROJECT_ROOT}/.tempo-report.json; global config is optional. After import, offer to remove legacy config; default answer is No.
.agents/skills/... is skill installation only, not runtime settings.
Runtime root rules:
PROJECT_ROOTmeans the real report project root: the user's current working copy or an explicitly requested project path.- If the current working directory contains
.tempo-report.json, project-local mode is active: MUST usePROJECT_ROOT=./and toolworkdirset to that directory. - In project-local mode, using an absolute
PROJECT_ROOTfor the same directory is a fail pattern; absolute roots are only for running from outside the report project or for global/shared settings. - Before any config/report command, choose
PROJECT_ROOTexplicitly and keep it fixed for the whole report. - Run bundled scripts with tool
workdirset to the current report project (project-local./) or setTEMPO_PROJECT_ROOTtoPROJECT_ROOTbefore invoking the script. - Do not use
$HOME,/tmp/opencode,/tmp, the skill install directory, or another temporary folder as runtimeworkdir. - If root is ambiguous, ask the user for the project path before running config/report commands.
- If a command returns
invalid report project root, STOP and ask forPROJECT_ROOT; do not glob, search, or inspect$HOMEto discover configs.
Set the installed skill directory before running bundled scripts from another project. Path depends on shell/install location:
TEMPO_SKILL_DIR="/path/to/installed/tempo-report"
PROJECT_ROOT="./" # project-local when cwd contains .tempo-report.jsonUseful commands:
# From the report project directory, use PROJECT_ROOT=./.
# From outside the project, use an absolute PROJECT_ROOT and tool workdir set to that path.
bash "$TEMPO_SKILL_DIR/scripts/tempo-data.sh" config-paths
bash "$TEMPO_SKILL_DIR/scripts/tempo-data.sh" load-config [CONFIG_PATH]
bash "$TEMPO_SKILL_DIR/scripts/tempo-data.sh" import-config [SOURCE_PATH] SCOPE # SCOPE: global|projectImport/create rules:
load-configmay reportneedsSetupand legacy candidates, but must not import automatically.- Ask before creating canonical config or importing legacy config; confirm target scope/path.
- After import, ask before deleting legacy config; default answer is No.
##Config Fields
{
"currentUser": {
"jiraLogin": "username",
"jiraKey": "JIRAUSER123",
"gitEmails": ["user@example.com"]
},
"projectsPath": "../projects",
"reportsSubdir": "tempo",
"autoSave": "self",
"eveningHour": 18,
"minDailyHours": 6.75,
"localActivitySources": ["~/work/docs"],
"userMappings": {}
}gitEmail string is legacy; normalize to gitEmails array. Arrays in project config replace global arrays.
localActivitySources is generic: docs, logs, exports, temp files, diagrams, snapshots, or any configured folders. Paths are user/project-specific and must stay in config.
##Workflow
###1. Resolve date, root, and user
Preflight:
- Resolve the date with any safe
workdir. - If the current working directory contains
.tempo-report.json, set project-localPROJECT_ROOT=./. - Otherwise resolve
PROJECT_ROOTfrom the user's explicit request or known current workspace. - If
PROJECT_ROOTis unclear, ask; do not search$HOME. - Run every config/report command with tool
workdirset to the report project orTEMPO_PROJECT_ROOT=PROJECT_ROOT.
bash "$TEMPO_SKILL_DIR/scripts/tempo-data.sh" get-date [YYYY-MM-DD] [YYYY-MM-DD] [EVENING_HOUR]
bash "$TEMPO_SKILL_DIR/scripts/tempo-data.sh" check-env
TEMPO_PROJECT_ROOT="$PROJECT_ROOT" bash "$TEMPO_SKILL_DIR/scripts/tempo-data.sh" load-configNo args means auto date: today after eveningHour, otherwise yesterday. Weekend auto mode suggests Friday unless date is explicit. Text after date can override user; otherwise use currentUser.
###2. Collect candidate issues
Use union of all sources. Never iterate issue keys manually.
Candidate sources:
| Source | Method |
|---|---|
| Worklog | worklogAuthor = "LOGIN" AND worklogDate = "DATE" |
| Assignee | assignee = "LOGIN" AND updated >= "DATE" |
| Code Reviewer | "Code Reviewer" = "LOGIN" AND updated >= "DATE" |
| Activity Streams | bash "$TEMPO_SKILL_DIR/scripts/tempo-data.sh" activity-streams DATE LOGIN JIRA_URL |
| Git commits | Extract issue keys from commit messages |
| Comments | Fetch comments for all candidate issues |
Use JQL with fields="key,summary,status", not *all.
Coverage requirement:
- Final candidate set is the union of every source above.
- Fetch changelog and comments for every candidate issue, including issues that already have worklogs.
- If batch changelog fails, fall back to per-issue fetch; do not skip silently.
- Before final report, list any unprocessed candidates with reason.
- Candidate discovery is not attribution: do not count time unless the task is definitely identified and has direct evidence for the target day.
- Keep weak candidates, zero-evidence candidates, and unmapped activity out of the main recommendation table.
###3. Fetch worklogs
For each candidate issue:
Use current Jira backend to fetch worklogs for each candidate issue. If shell Jira tools exist, jira_get_worklog(issue_key="KEY") is acceptable; otherwise use Jira CLI or Jira HTTP/API equivalent.
Filter by started date and author. started is the date time was logged for; created is only when the entry was created.
###4. Fetch changelog and comments
Fetch changelog for all candidate tasks, even if worklog exists. Batch if available; otherwise fetch each issue with expand=changelog. Comments are separate from changelog and must be fetched separately with fields="comment".
Filter activity by user and target day. Exclude worklog bookkeeping fields: WorklogId, timeestimate, timespent.
Do not mix categories:
- Worklog is explicit logged time only.
- Changelog is field/status/assignee activity only.
- Comments are not in changelog; fetch and estimate separately.
- Worklog bookkeeping fields are not activity.
Estimate Jira activity:
| Activity | Estimate |
|---|---|
| Status transition / code-review transition | 15m |
| Assignee change | 5m |
| Short comment | 5-10m |
| Medium discussion | 10-20m |
| Detailed code review / bug triage | 30-60m |
###5. Fetch Git commits
Always fetch Git, even if worklogs cover the day.
bash "$TEMPO_SKILL_DIR/scripts/tempo-data.sh" git-commits DATE EMAIL PROJECTS_PATH
bash "$TEMPO_SKILL_DIR/scripts/tempo-data.sh" git-diff HASH REPO_PATH
bash "$TEMPO_SKILL_DIR/scripts/tempo-data.sh" estimate-time INTERVAL_SEC ADDED REMOVED TYPESearch every git repo under projectsPath and every email in gitEmails. The script checks CommitDate when AuthorDate is outside target day, so rebased/amended/cherry-picked commits are still counted when relevant.
###6. Fetch local activity
If localActivitySources exists, fetch local activity:
bash "$TEMPO_SKILL_DIR/scripts/tempo-data.sh" local-activity DATE [CONFIG_PATH]Rules:
- Use metadata for all files.
- Read content only for safe text extensions and size limits.
- Never print file contents.
- Extract task keys from path, filename, and safe text content.
- Prefer a concrete content issue over a parent folder issue.
- Group file events by source, task key, and time proximity.
- Count local-only time only when the Jira task key appears in the path segment or filename of the active file/directory for that event.
- Do not count local time from content-only mentions, metadata-only mentions, inferred context, or repeated edits without a Jira key in path/filename; report them in the warning/appendix, not totals.
- If local activity clearly belongs to a project/folder but no exact Jira task is determined, keep it unmapped and warn the user that it may need mapping to an existing or new task.
- Deduplicate with Jira/Git when clearly same work.
###6a. Optional chronological calculation
Use this when user asks for chronology/timeline, when source totals overlap heavily, or when normal summing looks misleading.
Process:
- Build one timeline from Git commit
time, Jira changelogcreated, worklogstarted, commentscreated, and local activity timestamps. - Sort by time; assign intervals to the previous active task.
- Exclude breaks over 30m unless evidence says work continued.
- Treat merge commits as 15m flat unless there is clear work beyond merge handling.
- Split intervals for commits/comments that clearly mention multiple tasks.
- Still show source columns separately; use chronology only to avoid double count in unique work.
###7. Format report
Show full report in chat first, then save when autoSave allows. If saved, final answer must include the same summary table and totals as the saved file.
# Tempo Report — YYYY-MM-DD
| Задача | Название | Worklog | Git | Changelog | Comments | Local | Рекомендация |
|--------|----------|---------|-----|-----------|----------|-------|--------------|
| EDS-123 | Summary text | 3h | 30m | — | — | — | 3h 30m |
| EDS-456 | Local work | — | — | — | — | 2h | 2h |
**Итого Worklog:** Xh Ym
**Итого Git:** Xh Ym
**Итого Changelog:** Xh Ym
**Итого Comments:** Xh Ym
**Итого Local:** Xh Ym
**Уникальная работа (без пересечений):** Xh Ym
## Warning: ambiguous or unmapped activity (not counted)
- `repo/path` or commit summary without Jira key — Xm, not counted; ask user whether to map to an existing task or create a new one.
- Weak local mention `EDS-0000` found only in file content — not counted without stronger evidence.Rules:
- Worklog = explicitly logged time.
- Changelog = Jira field activity, not comments and not worklog bookkeeping.
- Comments = user comments/reviews/discussions.
- Local = configured local file activity.
- Count time in the main report only for definitely identified Jira tasks with direct evidence for the target day.
- Do not count weak or ambiguous evidence in recommendations: content-only local key mentions, metadata-only local mentions, local-only activity without Jira key in path/filename, assignee/reviewer candidates without user activity, Activity Streams candidates without user changelog/comment/worklog/git/local evidence, and git commits without a Jira key.
- Put ambiguous/unmapped activity after all totals in a separate warning/appendix section. Use it only to help the user understand folders/projects/possible future tasks; do not include it in totals or recommendations.
- Do not create
NO-ISSUErows in the main recommendation table. Unmapped git belongs in the warning/appendix section. - Do not include zero-time Jira candidates in the main table; list them only as unprocessed/zero-evidence candidates if useful.
- Do not adjust time to reach
minDailyHours; show the shortfall honestly. - Manual adjustments only when user asks.
- Escape
|in summaries. - Use
—for zero time. - Show all source columns even when empty for counted tasks.
- If total unique work is below
minDailyHours, show the shortfall; do not invent time.
###7a. Main table validation contract
Before showing or saving a report, validate the main recommendation table.
The main table MUST NOT contain:
NO-ISSUErows.LOCAL-ACTIVITYrows.- Rows with zero recommendation (
—,0m, or all source columns empty). - Local-only rows unless the evidence explicitly says the Jira key appeared in the active file path segment or filename.
- Assignee/reviewer/activity-stream candidates without direct same-day user evidence.
- Git-only rows whose commit subject/body/path has no Jira key.
If any row violates this contract:
- Remove it from the main table.
- Move it to
Warning: ambiguous or unmapped activity (not counted)with the reason it was not counted. - Recalculate totals without that row.
- Only then show/save the report.
A report that violates this contract is invalid and must not be saved as the final report.
autoSave modes:
| Mode | Behavior |
|---|---|
off | Ask before saving |
self | Save own reports only |
self+specified | Save own reports and explicitly named users |
all | Save every report |
If saved, final chat response must still include the full saved table and totals. Saving is not a substitute for showing the report.
###8. Save report
Path:
${PROJECT_ROOT}/${reportsSubdir}/YYYY-MM-DD.md
${PROJECT_ROOT}/${reportsSubdir}/YYYY-MM-DD_login.md # other userAfter saving, re-read or otherwise verify the saved report before saying it was saved.
###9. Add Tempo worklogs only on request
If user asks to write worklogs, first confirm a write-capable Jira backend is available. If unavailable, stop and tell user what is missing. If the same prompt asks for a report and says to immediately log missing hours, build/show the report first, then ask separate confirmation before any write call.
Use format:
write worklog via available backend, for example jira_add_worklog(
issue_key="KEY",
time_spent="1h 30m",
started="YYYY-MM-DDTHH:MM:SS.000+0300"
)Do not pass comment to jira_add_worklog; that tool can fail with it. For other backends, follow backend requirements. Verify by fetching worklogs back.
##Dry-Run Acceptance Checks
For a prompt like tempo за вчера, expected behavior:
- Activate this skill and do not ask for date clarification.
- Resolve yesterday via
get-dateor direct date calculation. - Resolve
PROJECT_ROOTbefore config/report commands; use./when the current project contains.tempo-report.json; if unclear, ask instead of searching$HOME. - Load config through canonical resolution rules with tool
workdirset to the report project orTEMPO_PROJECT_ROOT=PROJECT_ROOT. - Collect Worklog, Git, Changelog, Comments, and Local as separate sources.
- Filter worklogs by
started, notcreated. - Use candidate searches; never manually iterate issue keys.
- Include only definitely identified tasks with non-zero direct evidence in the main counted table.
- Validate the main table contract before showing/saving: no
NO-ISSUE,LOCAL-ACTIVITY, zero-time rows, or unqualified local-only rows. - Put weak/unmapped/zero-evidence activity after totals as warnings/appendix only.
- Do not print secrets or local file contents.
- Do not write Jira worklogs unless separately requested and confirmed.
- Do not save/import config outside the rules above.
Fail patterns:
- Immediately calling
jira_add_worklogduring report generation. - Mixing Worklog and Changelog totals.
- Using worklog
createddate as the report date. - Padding recommendations to reach
minDailyHours. - Counting
NO-ISSUE,LOCAL-ACTIVITY, weak local mentions, local-only activity without Jira key in path/filename, or zero-evidence candidates in the main recommendation table. - Saving a report before the main table validation contract passes.
- Using an absolute
PROJECT_ROOTwhen current cwd already contains project-local.tempo-report.json. - Performing real bash/Jira calls in an explicit dry-run/test-only request.
##Error Handling
| Situation | Action |
|---|---|
| Invalid report project root | Stop and ask for PROJECT_ROOT; do not search or glob $HOME |
| No Jira read backend | Stop and tell user which backend/env/tool is missing |
| No Jira write backend | Do not attempt writes; ask user to enable it |
| Canonical config missing | If legacy candidates exist, ask whether to import; otherwise ask to create project config |
| Activity Streams fails | Notify user and fall back to Jira/JQL sources |
| Changelog batch fails | Fetch per issue |
| Worklog issue has too many entries | Warn and skip that issue's worklogs |
| No Git commits | Keep Git column empty and note it |
User notifications:
- Retryable failure:
⚠️ <action> failed: <reason>. Retrying... - Retry recovered:
✓ <action> recovered on retry - Permanent partial failure:
⚠️ <action> permanently failed: <reason>. Proceeding without it.
##Installation
fs-skills install tempo-report
export TEMPO_SKILL_DIR="/path/to/installed/tempo-report"
chmod +x "$TEMPO_SKILL_DIR/scripts/tempo-data.sh"
cd "$TEMPO_SKILL_DIR" && bash tests/test-config-resolution.sh && bash tests/test-local-activity.shTests require jq.