Skip to content

Dashboard shows no data after fresh install (v0.1.1) — 3 potential issues found #14

@seokjoon-yoon

Description

@seokjoon-yoon

Hi, thanks for building cops — really excited about having observability for Claude Code sessions.

After a fresh install of v0.1.1 on macOS (Apple Silicon), I completed all the setup steps (Google OAuth, cops add, daemon running via LaunchAgent), but the dashboard at cops.team-attention.com shows 0 tokens, 0 sessions, 0 projects.

I spent some time debugging and traced through the source code to understand what might be going wrong. Sharing my findings below in case they're helpful.


1. cops add doesn't set organizationId in global config

When I run cops add, the project-level config (<project>/.cops/config.json) gets the correct organizationId, but the global config (~/.cops/config.json) ends up with organizationId: "".

What I found in the source:

In cli/internal/service/tracking/tracking_service.go, the AddProject() method saves the local config with params.OrganizationID correctly:

localConfig := &config.LocalConfig{
    ProjectID:      projectID,
    OrganizationID: params.OrganizationID,  // ✓ set here
}
s.configRepo.SaveLocalConfig(projectPath, localConfig)

But when constructing the domain.Project for the global config, OrganizationID isn't assigned:

project := &domain.Project{
    ProjectAbstract: domain.ProjectAbstract{
        ID:   projectID,
        Name: name,
        Path: projectPath,
    },
    IsGitProject: isGitProject,
    RegisteredAt: time.Now(),
    // OrganizationID not set → Go zero value ""
}

The field exists on the struct (shared/domain/project.go), it's just not populated during construction.

To reproduce:

cops add /path/to/project
cat ~/.cops/config.json          # → organizationId: ""
cat /path/to/project/.cops/config.json  # → organizationId: "abc123..." (correct)

2. Daemon doesn't appear to send data to the API server

I noticed the daemon process is running and reading JSONL files (SQLite file_positions are being updated), but there are no outgoing network connections:

lsof -p $(pgrep cops-daemon) | grep -i "tcp\|ssl\|https"
# → (no results)

The API server itself is reachable (curl returns 404 at root, which is expected).

What I found in the source:

Looking at daemon/internal/platform/interceptor/auth_interceptor.go, when GetAccessToken() returns an error, the interceptor returns CodeUnauthenticated without calling next() — so the HTTP request is never made:

token, err := i.authState.GetAccessToken(ctx)
if err != nil {
    return nil, connect.NewError(connect.CodeUnauthenticated, err)
}

In daemon/internal/service/logwatcher/log_service.go, when send fails, returnLinesToBuffer() puts unsent lines back in memory. But since SQLite file positions were already advanced (in the fsnotify handler, before flush), those lines would be lost if the daemon restarts.

The daemon logs only show startup messages — no send/flush/batch related output — which is consistent with requests being blocked at the interceptor level.


3. Initial scan on daemon startup seems to run before watch targets are ready

Every time the daemon starts, I see this in the logs:

loaded file positions count=0
log fsnotify handler started
no watched directories, skipping initial scan    ← scan happens here
fsnotify handlers started
all handlers started
updated watch targets watching=326               ← targets arrive here

What I found in the source:

In daemon/cmd/internal/container/register_fsnotify.go, the startup sequence is:

  1. SubscriberHandler (LogPubsubHandler) — starts a goroutine listening on a pubsub channel
  2. PublisherHandler (ConfigWatcherFsnotifyHandler) — publishes watch targets to the buffered channel
  3. FsnotifyHandler (LogFsnotifyHandler) — calls scanExistingFiles() which checks watcher.WatchList()

Since the pubsub consumer goroutine from step 1 may not have processed the message from step 2 by the time step 3 checks the watch list, WatchList() returns empty and the scan is skipped.

I tried clearing the file_positions table in SQLite and restarting, but since the scan itself is skipped, it didn't help.


Environment

Item Value
cops version v0.1.1
OS macOS 15 (Apple Silicon)
Daemon LaunchAgent
Auth Google OAuth completed, ~/.cops/auth.json present

Workaround I'm using

Manually editing ~/.cops/config.json to add the correct organizationId (copied from the project-level config). This addresses issue 1, though issues 2 and 3 may still apply.


Happy to provide more details or test anything if that would help. Thanks for your time!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions