Skip to content

Commit c66780c

Browse files
solzipclaude
andcommitted
feat: Sprint C-2 + C-3 — 팀 Git 중앙 Repo + 리포트
team.py: - init_team(): repo clone + .team-config.json 로드 + 보안 규칙 병합 - team_stats(): 팀원별/프로젝트별 세션 통계 - print_team_stats(): 터미널 대시보드 출력 - team_weekly_report(): 팀 주간 마크다운 리포트 생성 cli.py: - team 서브커맨드 (stats, weekly, monthly, init, add-member) - init --team <url> 옵션 (팀 모드 초기화) - delete --last / --session (세션 삭제) .team-config.json 스키마: - team_name, members, roles (member/lead/admin) - security (mask_paths, content_filters, required_secret_scan) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 7feb1d9 commit c66780c

File tree

2 files changed

+402
-1
lines changed

2 files changed

+402
-1
lines changed

src/claude_diary/cli.py

Lines changed: 84 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,24 @@ def main():
6060
p_config.add_argument("--add-exporter", help="Add exporter (interactive)")
6161

6262
# init
63-
sub.add_parser("init", help="Initialize claude-diary setup")
63+
p_init = sub.add_parser("init", help="Initialize claude-diary setup")
64+
p_init.add_argument("--team", dest="team_repo", help="Team repo URL for team mode")
6465

6566
# migrate
6667
sub.add_parser("migrate", help="Migrate v1.0 env vars to config.json")
6768

69+
# team
70+
p_team = sub.add_parser("team", help="Team management commands")
71+
p_team.add_argument("action", nargs="?", default="stats",
72+
choices=["stats", "weekly", "monthly", "init", "add-member"],
73+
help="Team action")
74+
p_team.add_argument("--project", "-p", help="Filter by project")
75+
p_team.add_argument("--member", help="Filter by member")
76+
p_team.add_argument("--month", "-m", help="Month (YYYY-MM)")
77+
p_team.add_argument("--repo", help="Team repo URL (for init)")
78+
p_team.add_argument("--name", help="Member name (for init/add-member)")
79+
p_team.add_argument("--role", default="member", help="Role (for add-member)")
80+
6881
# reindex
6982
sub.add_parser("reindex", help="Rebuild search index")
7083

@@ -101,6 +114,7 @@ def main():
101114
"init": cmd_init,
102115
"migrate": cmd_migrate,
103116
"reindex": cmd_reindex,
117+
"team": cmd_team,
104118
"audit": cmd_audit,
105119
"delete": cmd_delete,
106120
"dashboard": cmd_dashboard,
@@ -529,6 +543,14 @@ def cmd_init(args):
529543
config = load_config()
530544
diary_dir = os.path.expanduser(config["diary_dir"])
531545

546+
# Team mode init
547+
if hasattr(args, 'team_repo') and args.team_repo:
548+
from claude_diary.team import init_team
549+
print("Initializing claude-diary (team mode)...")
550+
print()
551+
init_team(args.team_repo)
552+
return
553+
532554
print("Initializing claude-diary...")
533555
print()
534556

@@ -607,6 +629,67 @@ def cmd_reindex(args):
607629
print("Index: %s" % index_path)
608630

609631

632+
# ── Team ──
633+
634+
def cmd_team(args):
635+
from claude_diary.team import (
636+
init_team, get_team_repo_path, team_stats,
637+
print_team_stats, team_weekly_report
638+
)
639+
640+
if args.action == "init":
641+
repo_url = args.repo
642+
if not repo_url:
643+
repo_url = input("Team repo URL: ").strip()
644+
name = args.name
645+
if not name:
646+
name = input("Your name: ").strip()
647+
print("Initializing team mode...")
648+
init_team(repo_url, name)
649+
print("\nDone! Sessions will auto-push to team repo.")
650+
return
651+
652+
config = load_config()
653+
repo_path = get_team_repo_path(config)
654+
if not repo_path or not os.path.isdir(repo_path):
655+
print("Team not configured. Run: claude-diary team init --repo <url>")
656+
return
657+
658+
if args.action == "stats":
659+
data = team_stats(repo_path, month=args.month)
660+
print_team_stats(data)
661+
662+
elif args.action in ("weekly", "monthly"):
663+
lang = config.get("lang", "ko")
664+
result = team_weekly_report(repo_path, lang=lang)
665+
if result:
666+
report, filepath = result
667+
print(report)
668+
print("---")
669+
print("Saved: %s" % filepath)
670+
else:
671+
print("No team data found.")
672+
673+
elif args.action == "add-member":
674+
name = args.name or input("Member name: ").strip()
675+
role = args.role
676+
team_config_path = os.path.join(repo_path, ".team-config.json")
677+
tc = {}
678+
if os.path.exists(team_config_path):
679+
with open(team_config_path, "r") as f:
680+
tc = json.load(f)
681+
tc.setdefault("members", [])
682+
tc.setdefault("roles", {})
683+
if name not in tc["members"]:
684+
tc["members"].append(name)
685+
tc["roles"][name] = role
686+
with open(team_config_path, "w") as f:
687+
json.dump(tc, f, indent=2, ensure_ascii=False)
688+
# Create member dir
689+
Path(os.path.join(repo_path, "members", name)).mkdir(parents=True, exist_ok=True)
690+
print("Added member '%s' with role '%s'" % (name, role))
691+
692+
610693
# ── Audit ──
611694

612695
def cmd_audit(args):

0 commit comments

Comments
 (0)