| name | worklog-sync |
| description | Sync kanban board tasks to EOB weekly worklogs. Reads completed/in-progress kanban cards, maps them to worklog projects, estimates hours from timestamps, aggregates by day, and submits via the EOB API. |
| license | MIT |
Overview
Reads kanban board tasks and creates weekly worklog entries in the Engineering Operation Board (EOB).
Tasks are aggregated by date + project + work type into one worklog card per group.
Project Classification
Each kanban project has a worklog_type:
| type | Behavior |
|---|
work | Maps to an EOB project; worklog created with project_id |
non-project | Worklog created without project_id (work type only) |
personal | Excluded from sync entirely |
Project Settings Storage
Primary: Kanban DB project_settings table (via PUT /api/project-settings/:project)
Fallback: ~/.claude/worklog-sync.json โ project_map (only if the deployed API has not been updated yet)
CREATE TABLE IF NOT EXISTS project_settings (
project TEXT PRIMARY KEY,
worklog_type TEXT NOT NULL DEFAULT 'work',
eob_project_id TEXT,
eob_product_line_id TEXT,
default_work_type_code TEXT DEFAULT 'ENG-SW',
label TEXT
);
Kanban API for project_settings
KANBAN_API="$BASE_URL"
curl -s "${AUTH_HEADER[@]}" "$KANBAN_API/api/project-settings"
curl -s "${AUTH_HEADER[@]}" "$KANBAN_API/api/project-settings/$PROJECT"
curl -s "${AUTH_HEADER[@]}" -X PUT "$KANBAN_API/api/project-settings/$PROJECT" \
-H 'Content-Type: application/json' \
-d '{"worklog_type":"work","eob_project_id":"<UUID>","default_work_type_code":"ENG-SW","label":"..."}'
If the API returns 404, fall back to project_map in config file. Do not read any local DB directly.
Configuration
~/.claude/worklog-sync.json:
{
"eob_base_url": "https://eob.10.182.252.32.sslip.io",
"kanban_api": "https://cyanlunakanban.vercel.app",
"kanban_auth_token": "<X-Kanban-Auth token>",
"access_token": null,
"refresh_token": null,
"user_id": null,
"project_map": {
"edwards.oqc.infra": { "worklog_type": "work", "eob_project_id": "ac78d5ae-a15e-4a40-9638-8109539d6633", "default_work_type_code": "ENG-SW", "label": "OQC Digitalization Infrastructure" },
"unify": { "worklog_type": "work", "eob_project_id": "013c7ee7-edcc-46bc-bcc8-55b15bb2481f", "default_work_type_code": "ENG-SW", "label": "Unify Plasma Single" },
"edwards.operation.board": { "worklog_type": "non-project", "default_work_type_code": "ENG-SW", "label": "Team DX / Productivity" },
"testrig-dashboard": { "worklog_type": "non-project", "default_work_type_code": "ENG-SW", "label": "Team Work" },
"3dx.api": { "worklog_type": "non-project", "default_work_type_code": "ENG-SW", "label": "3DX API (Team Work)" },
"cpet.db": { "worklog_type": "personal" },
"cpet": { "worklog_type": "personal" },
"ai.cycling.workout.planner": { "worklog_type": "personal" },
"ai-cycling-coach": { "worklog_type": "personal" },
"unahouse.finance": { "worklog_type": "personal" },
"today.bike": { "worklog_type": "personal" },
"asan.bicycle": { "worklog_type": "personal" },
"cyanluna-portfolio": { "worklog_type": "personal" },
"cyanluna.skills": { "worklog_type": "personal" },
"bangwahu": { "worklog_type": "personal" },
"remotion-video-gen": { "worklog_type": "personal" },
"type1recovery": { "worklog_type": "personal" },
"kanban-board": { "worklog_type": "personal" }
}
}
Commands
/worklog-sync login โ Authenticate with EOB
-
Ask user for email and password via AskUserQuestion.
-
Authenticate:
EOB="https://eob.10.182.252.32.sslip.io"
AUTH=$(curl -s -X POST "$EOB/api/auth/login" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "username=$EMAIL&password=$PASSWORD")
- Extract tokens and get user info:
TOKEN=$(echo "$AUTH" | python3 -c "import sys,json; print(json.load(sys.stdin)['access_token'])")
REFRESH=$(echo "$AUTH" | python3 -c "import sys,json; print(json.load(sys.stdin)['refresh_token'])")
ME=$(curl -s "$EOB/api/auth/me" -H "Authorization: Bearer $TOKEN")
USER_ID=$(echo "$ME" | python3 -c "import sys,json; print(json.load(sys.stdin)['id'])")
- Save to
~/.claude/worklog-sync.json.
/worklog-sync map โ Configure Project Mapping
- Fetch all kanban projects and their current settings:
BOARD=$(curl -s "${AUTH_HEADER[@]}" "$KANBAN_API/api/board")
- Fetch EOB project hierarchy for matching:
PROJECTS=$(curl -s "$EOB/api/projects/hierarchy" -H "Authorization: Bearer $TOKEN")
-
For each kanban project without settings, ask user via AskUserQuestion:
- worklog_type:
work / non-project / personal
- If
work: select EOB project from hierarchy
- Default work type code
-
Save via API:
curl -s "${AUTH_HEADER[@]}" -X PUT "$KANBAN_API/api/project-settings/$PROJECT" \
-H 'Content-Type: application/json' \
-d '{"worklog_type": "work", "eob_project_id": "...", "label": "..."}'
/worklog-sync โ Main Sync Flow
Procedure:
- Load auth & refresh token if needed
CONFIG=$(cat ~/.claude/worklog-sync.json)
EOB=... TOKEN=... REFRESH=... USER_ID=...
If token expired, try refresh โ if refresh fails, prompt /worklog-sync login.
- Determine target week (default: current week MonโSun)
TODAY=$(date +%Y-%m-%d)
DOW=$(date -d "$TODAY" +%u)
MONDAY=$(date -d "$TODAY -$((DOW-1)) days" +%Y-%m-%d)
SUNDAY=$(date -d "$MONDAY +6 days" +%Y-%m-%d)
- Fetch kanban board
KANBAN_API=$(echo "$CONFIG" | python3 -c "import sys,json; print(json.load(sys.stdin).get('kanban_api','https://cyanlunakanban.vercel.app'))")
KANBAN_TOKEN=$(echo "$CONFIG" | python3 -c "import sys,json; print(json.load(sys.stdin).get('kanban_auth_token',''))")
BOARD=$(curl -s -H "X-Kanban-Auth: $KANBAN_TOKEN" "$KANBAN_API/api/board")
- Load project mappings: try
board.project_settings first, fall back to config.project_map
- Filter out projects where
worklog_type == "personal" โ skip entirely
- Projects not in any mapping โ flag as "UNMAPPED" in preview, ask user to classify
-
Collect tasks relevant for the week
- Status
done with completed_at within the target week
- Status
impl, impl_review, test, plan, plan_review with timestamps within the week
-
Estimate hours from timestamps
Use task lifecycle timestamps to calculate actual work time per day:
started_at โ planned_at = planning work
planned_at โ reviewed_at = review + iteration
reviewed_at โ tested_at = implementation time
tested_at โ completed_at = testing time
started_at โ completed_at = total elapsed (fallback)
Rules:
- Calculate elapsed time between phase timestamps
- Cap at 8h per day per task (workday assumption)
- If elapsed > 1 day, distribute hours across work days (MonโFri) within the range
- Minimum: 0.5h per task phase
- Round to nearest 0.5h
agent_log timestamps can be used for more granular per-day breakdown
Example:
- Task #42:
started_at=04/01 09:00, completed_at=04/02 15:00
- Elapsed: ~1.25 work days โ 04/01: 4h, 04/02: 4h (distribute evenly)
-
Fetch existing worklogs (duplicate check)
EXISTING=$(curl -s "$EOB/api/worklogs?user_id=$USER_ID&start_date=$MONDAY&end_date=$SUNDAY" \
-H "Authorization: Bearer $TOKEN")
Skip if same date + project + similar description already exists.
- Fetch work type tree (resolve codes to IDs)
WORK_TYPES=$(curl -s "$EOB/api/work-types/tree" -H "Authorization: Bearer $TOKEN")
-
Aggregate into daily worklog cards
Core rule: same date + same project + same work_type โ one worklog card.
Group all task entries by (date, project, work_type_code), then:
- hours: Sum of all tasks in the group (cap at 8h per card)
- project_id: From
project_settings.eob_project_id
- work_type_category_id: Resolve code from work type tree
- description: Brief list of what was done inside the card
Description format โ concise activity log, not individual task dumps:
์ธ์ฆ ๋ชจ๋ ๊ตฌํ ์๋ฃ, API ๊ฒ์ฆ ์์ , ์ฌ์ด๋๋ฐ ์ ๋ ฌ ๊ฐ์
- Each item: short summary (task title condensed to ~15 chars) + ์๋ฃ/์งํ ์ค
- Comma-separated, one line
- If too many items (>5), summarize:
SW ๊ฐ๋ฐ 7๊ฑด (์ธ์ฆ ๋ชจ๋, API ๊ฒ์ฆ ์ธ 5๊ฑด)
Daily cap: If a single card exceeds 8h, cap at 8h. Remaining hours are dropped (user can adjust in preview).
Example aggregation:
Raw tasks for 02/27, OQC Digitalization, ENG-SW:
#37 run.sh ์คํ ๋ชจ๋ ๊ฐ์ (0.5h)
#40 SemiAutoTaskForm (0.5h)
#41 TaskSchema parser (0.5h)
#42 Edge Runner timeout (0.5h)
#44 Gherkin DB ๋ง์ด๊ทธ๋ ์ด์
(0.5h)
โ Aggregated card:
date: 2026-02-27
project: OQC Digitalization Infrastructure
work_type: ENG-SW
hours: 2.5h
description: "run.sh ์คํ๋ชจ๋ ๊ฐ์ , SemiAutoTaskForm, TaskSchema parser, Edge Runner timeout, Gherkin DB ๋ง์ด๊ทธ๋ ์ด์
์๋ฃ"
-
Preview to user
## Worklog Preview: 2026-02-24 ~ 2026-03-01
| Date | Project | Type | Hours | Description |
|-------|----------------------|-------------|-------|----------------------------------------------------|
| 02/24 | OQC Digitalization | ENG-SW | 1.0h | DB ๋๋ฉ์ธ ๋ถ๋ฆฌ ์๋ฃ |
| 02/24 | Unify Plasma Single | ENG-SW | 5.5h | SQL ํตํฉ๊ด๋ฆฌ, db-viewer ์ ๊ฑฐ, config manager ์์ฑ ์ธ |
| 02/25 | OQC Digitalization | ENG-SW | 2.0h | FT&CC ์นดํ๋ก๊ทธ, Inspection ์ ํ, ์๋ํ ๋ฐฐ์ง ์ธ |
| 02/25 | OQC Digitalization | ENG-SW-TST | 0.5h | Auto task form ํ
์คํธ |
| 02/27 | OQC Digitalization | ENG-SW | 8.0h | Gherkin Pattern A, Corrective ํญ, run.sh ๊ฐ์ ์ธ |
| 02/27 | Unify Plasma Single | ENG-SW | 8.0h | Config Manager ํตํฉ, Metadata Viewer ์ธ |
**Total: 35h / 12 cards** (personal 3๊ฑด ์ ์ธ)
Proceed? (Enter to confirm, or edit)
-
User adjusts via AskUserQuestion if needed (hours, project, work type, date, remove).
-
Submit approved entries
curl -s -X POST "$EOB/api/worklogs" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d "{
\"date\": \"$DATE\",
\"user_id\": \"$USER_ID\",
\"project_id\": \"$PROJECT_ID\",
\"work_type_category_id\": $WTC_ID,
\"hours\": $HOURS,
\"description\": \"$DESCRIPTION\"
}"
- Report results
## Sync Complete
Created 3 entries (9h) for 2026-03-30 ~ 2026-04-05. Failed: 0
/worklog-sync status โ Weekly Summary
- Load auth, fetch current week's worklogs:
curl -s "$EOB/api/worklogs?user_id=$USER_ID&start_date=$MONDAY&end_date=$SUNDAY" \
-H "Authorization: Bearer $TOKEN"
- Display:
## Week: 2026-03-30 ~ 2026-04-05
| Day | Hours | Entries |
|-----|-------|---------|
| Mon 03/30 | 3.75h | 5 |
| Tue 03/31 | 4.0h | 5 |
| Wed 04/01 | 8.0h | 3 |
| Thu 04/02 | 4.5h | 8 |
| Fri 04/03 | 2.5h | 3 |
| **Total** | **22.75h / 40h** | **24** |
Work Type Quick Reference
| Code | Name | When to Use |
|---|
ENG-SW | Software Development | Default for kanban coding tasks |
ENG-SW-COD | Implementation (Coding) | Specific coding work |
ENG-SW-REQ | Requirements Analysis | Planning/requirements tasks |
ENG-SW-TST | Unit Testing | Test writing |
ENG-SW-DBG | Debugging | Bug fixes |
PRJ-REV | Review & Approval | Code review tasks |
PRJ-PLN | Planning & Scheduling | Sprint planning |
MTG-INT | Internal Meeting | Team meetings |
QMS-QC | Quality Control | QC-related tasks |
SUP-TKT | Ticket/Issue Resolution | Support tickets |
Task-to-WorkType Inference Rules
When default_work_type_code doesn't cover it, infer from task content:
- Title contains "review", "approve" โ
PRJ-REV
- Title contains "fix", "bug", "debug" โ
ENG-SW-DBG
- Title contains "test" โ
ENG-SW-TST
- Title contains "meeting", "sync", "standup" โ
MTG-INT
- Tags contain "qc", "quality" โ
QMS-QC
- Default fallback: project's
default_work_type_code
Notes
- 24h daily limit: EOB API rejects worklogs if total hours for a day exceed 24.
- Duplicate prevention: Checks existing worklogs before creating.
- Token expiry: Access tokens expire in 30 min; auto-refreshes via refresh token (7 days).
- Kanban API fallback: Do not query any local DB directly. Use the deployed Kanban API, or fall back only to
project_map for classification metadata.